Skip to content

grpc-benchmark: Add benchmark client and local runner#2737

Merged
arjan-bal merged 25 commits into
grpc:masterfrom
arjan-bal:grpc-benchmark-client
Jul 24, 2026
Merged

grpc-benchmark: Add benchmark client and local runner#2737
arjan-bal merged 25 commits into
grpc:masterfrom
arjan-bal:grpc-benchmark-client

Conversation

@arjan-bal

@arjan-bal arjan-bal commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Contributes to: #2666

This PR introduces the benchmarking client. It also adds a local runner binary that exercises the worker, server, and client within a single process, making it easy to run benchmarks locally.

Similar to gRPC-Java, the client uses the hdrhistogram crate for its histogram implementation. Because the Rust crate does not support a thread-safe, lock-free implementation natively, the client leverages a tokio::sync::watch channel and a tokio::sync::mpsc channel to coordinate between the worker task and the client RPC tasks when collecting stats. This design avoids the need to acquire a mutex lock when reporting the latency of each RPC.

@arjan-bal

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements the benchmark client and worker client execution logic for the gRPC benchmark suite, including support for collecting latency statistics using histograms and running smoke tests. The feedback highlights several important improvements: preventing empty authority overrides from failing gRPC requests, handling empty histograms to avoid reporting incorrect minimum latencies, adding a small delay in the unary call retry loop to prevent 100% CPU usage on failures, and replacing an unsafe .unwrap() with proper error handling when accessing the benchmark client.

Comment thread grpc-benchmark/src/client.rs
Comment thread grpc-benchmark/src/client.rs
Comment thread grpc-benchmark/src/client.rs
Comment thread grpc-benchmark/src/worker.rs Outdated
@arjan-bal arjan-bal closed this Jul 16, 2026
@arjan-bal arjan-bal reopened this Jul 17, 2026
@arjan-bal arjan-bal changed the title grpc-benchmark: Add benchmark client grpc-benchmark: Add benchmark client and local runner Jul 17, 2026
@arjan-bal

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a benchmark tool (bench) and implements the client-side benchmarking logic (BenchmarkClient) along with its integration into the worker service. It also updates the benchmark server to support dynamic port binding. The review feedback highlights two critical issues in client.rs: first, stale histogram reports from previous timed-out requests can corrupt benchmark statistics, which can be resolved by draining the receiver channel; second, if a streaming task fails, it exits prematurely, causing the stats aggregation to hang indefinitely. Re-establishing the stream on failure is recommended to prevent this hang.

Comment thread grpc-benchmark/src/client.rs
Comment thread grpc-benchmark/src/client.rs
@arjan-bal
arjan-bal force-pushed the grpc-benchmark-client branch from e39fe6e to 8dfa7d9 Compare July 20, 2026 16:38
Comment thread grpc-benchmark/src/lib.rs
#[allow(unused)]
pub mod generated {
pub mod benchmark_service_grpc {
grpc::include_proto!("grpc/testing", "benchmark_service");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dfawley, since this macro includes both generates.rs and the _grpc.pb.rs, it doesn't handle multiple service files well. I wonder if we need our own generatetd_grpc.rs or require users to separately import protos and grpc.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree something like would make sense. Not including the proto messages via our macro seems the most promising to me, but we'd probably have to do a little experimenting.

Comment thread grpc-benchmark/src/client.rs Outdated
}
let channel = builder.build();

let histogram = Histogram::new_with_max(histogram_params.max_possible as u64, 3)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move histogram initialization outside the for loop, since it doesn't change per-channel? Placed here it makes it seems there is a reason it is being create per-channel, since all the other invariants were created before the for loop.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ends up in the TestOptions/RpcOptions which is per-channel, though, so doesn't it have to be? Unless it's Copy.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is already being copied for each task in start_rpcs()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved histogram initialization outside the loop and cloned it in the loop.

Comment thread grpc-benchmark/src/client.rs Outdated
}
let channel = builder.build();

let histogram = Histogram::new_with_max(histogram_params.max_possible as u64, 3)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ends up in the TestOptions/RpcOptions which is per-channel, though, so doesn't it have to be? Unless it's Copy.

@arjan-bal arjan-bal assigned arjan-bal and unassigned ejona86 and dfawley Jul 24, 2026
@arjan-bal
arjan-bal merged commit ef95e07 into grpc:master Jul 24, 2026
26 checks passed
@arjan-bal
arjan-bal deleted the grpc-benchmark-client branch July 24, 2026 10:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants