Skip to content

Benchmark: support -c correctly - #3170

Merged
mgravell merged 1 commit into
mainfrom
marc/benchmark-connection-per-client
Aug 10, 2026
Merged

Benchmark: support -c correctly#3170
mgravell merged 1 commit into
mainfrom
marc/benchmark-connection-per-client

Conversation

@mgravell

@mgravell mgravell commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

give each client its own connection unless +m specified

readme.md documents +m/-m as "when enabled clients share a connection, otherwise each client has a separate connection". The classic (old-core) leg did not implement the second half: OldCoreBenchmarkBase built a single ConnectionMultiplexer in its constructor and GetClient(int index) ignored the index entirely, returning that one IDatabase to every worker. Multiplexed was never read on this leg at all -- +m parsed and then did nothing.

So -c was CONCURRENCY (in-flight requests pipelined onto one connection), not connection count, on the leg that ships. The fan-out above it was always correct: BenchmarkBase allocates ClientCount tasks and calls GetClient(i) per worker; only the worker-to-connection mapping collapsed.

A multiplexer is one connection per endpoint by design, so "a connection per client" means a multiplexer per client. Now builds Multiplexed ? 1 : ClientCount of them and maps worker i to i % connectionCount, so +m reproduces the previous behaviour exactly and is the only way to get it. NewCoreBenchmark already did this (new(count: Multiplexed ? 1 : ClientCount)); BridgeBenchmark shares this base and inherits the fix.

VERIFIED against a live server, sampling DURING the run from two independent vantage points -- the OS TCP table by owning pid, and the server's own CLIENT LIST:

-c 1 OS 1,1,1,1 CLIENT LIST 1 (+ the cli itself)
-c 8 OS 8,8,8,8 CLIENT LIST 8
-c 50 OS 50,50,50,50 CLIENT LIST 50
-c 50 +m OS 1,1,1,1 CLIENT LIST 1

The +m cell is the discriminating one: without it, a fix that simply hard-wired N connections would pass just as happily. --basic also exercised (exit 0).

AND A BANNER THAT CANNOT AGREE WITH A FLAG THAT DID NOTHING. The per-test banner printed ", mux" whenever +m was passed -- including on the leg where it had no effect -- so it reported the FLAG, not the behaviour, and could not have caught this. ConnectionCount is virtual, defaulting to the intended count, and OldCoreBenchmarkBase overrides it with _connectionMultiplexers.Length: the number actually created. It is printed on the ### ... ### announce line, which survives -q so a harness can gate on it, and in the per-test banner.

Checklist

  • I fully and freely contribute this code in accordance with the project license (and am legally able to do so)
  • I take responsibility for this contribution's quality and correctness, including any portions produced with AI assistance (see CONTRIBUTING.md).

…t its own

readme.md documents `+m`/`-m` as "when enabled clients share a connection,
otherwise each client has a separate connection". The classic (old-core) leg did
not implement the second half: OldCoreBenchmarkBase built a single
ConnectionMultiplexer in its constructor and `GetClient(int index)` ignored the
index entirely, returning that one IDatabase to every worker. `Multiplexed` was
never read on this leg at all -- `+m` parsed and then did nothing.

So `-c` was CONCURRENCY (in-flight requests pipelined onto one connection), not
connection count, on the leg that ships. The fan-out above it was always correct:
BenchmarkBase allocates ClientCount tasks and calls GetClient(i) per worker; only
the worker-to-connection mapping collapsed.

A multiplexer is one connection per endpoint by design, so "a connection per
client" means a multiplexer per client. Now builds `Multiplexed ? 1 :
ClientCount` of them and maps worker i to `i % connectionCount`, so `+m`
reproduces the previous behaviour exactly and is the only way to get it.
NewCoreBenchmark already did this (`new(count: Multiplexed ? 1 : ClientCount)`);
BridgeBenchmark shares this base and inherits the fix.

VERIFIED against a live server, sampling DURING the run from two independent
vantage points -- the OS TCP table by owning pid, and the server's own
CLIENT LIST:

  -c 1        OS 1,1,1,1     CLIENT LIST 1 (+ the cli itself)
  -c 8        OS 8,8,8,8     CLIENT LIST 8
  -c 50       OS 50,50,50,50 CLIENT LIST 50
  -c 50 +m    OS 1,1,1,1     CLIENT LIST 1

The `+m` cell is the discriminating one: without it, a fix that simply hard-wired
N connections would pass just as happily. `--basic` also exercised (exit 0).

AND A BANNER THAT CANNOT AGREE WITH A FLAG THAT DID NOTHING. The per-test banner
printed ", mux" whenever `+m` was passed -- including on the leg where it had no
effect -- so it reported the FLAG, not the behaviour, and could not have caught
this. `ConnectionCount` is virtual, defaulting to the intended count, and
OldCoreBenchmarkBase overrides it with `_connectionMultiplexers.Length`: the
number actually created. It is printed on the `### ... ###` announce line, which
survives `-q` so a harness can gate on it, and in the per-test banner.
@mgravell mgravell changed the title The classic leg used ONE connection whatever -c said Benchmark: support -c correctly Aug 10, 2026
@mgravell
mgravell merged commit 14f624b into main Aug 10, 2026
7 of 8 checks passed
@mgravell
mgravell deleted the marc/benchmark-connection-per-client branch August 10, 2026 08:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant