├── java_aot_bench ├── settings.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ ├── application.yml │ │ ├── META-INF │ │ │ └── native-image │ │ │ │ └── helloworld │ │ │ │ └── basic-application │ │ │ │ └── native-image.properties │ │ └── logback.xml │ │ └── java │ │ └── helloworld │ │ ├── GreetingService.java │ │ ├── Application.java │ │ └── GreetingEndpoint.java ├── micronaut-cli.yml ├── Dockerfile ├── build.gradle └── gradlew.bat ├── rust_wtx_bench ├── .gitignore ├── .cargo │ └── config.toml ├── src │ ├── grpc_bindings.rs │ └── main.rs ├── rust-toolchain ├── Dockerfile ├── Cargo.toml └── build.rs ├── .dockerignore ├── java_armeria_bench ├── settings.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── Dockerfile └── build.gradle ├── d_grpc_bench ├── .dockerignore ├── dub.json ├── dub.selections.json ├── source │ ├── GreeterImpl.d │ └── server.d └── Dockerfile ├── php_grpc_bench ├── .dockerignore ├── composer.json ├── .rr.yaml ├── worker.php ├── src │ └── HelloworldService.php └── Dockerfile ├── rust_grpcio_bench ├── .gitignore ├── src │ ├── proto │ │ ├── mod.rs │ │ └── gen │ │ │ └── mod.rs │ └── main.rs ├── .cargo │ └── config ├── Dockerfile ├── build.rs └── Cargo.toml ├── rust_tonic_mt_bench ├── .gitignore ├── .cargo │ └── config ├── build.rs ├── Dockerfile ├── Cargo.toml └── src │ └── main.rs ├── rust_tonic_st_bench ├── .gitignore ├── .cargo │ └── config ├── build.rs ├── Dockerfile ├── Cargo.toml └── src │ └── main.rs ├── swift_grpc_bench ├── Sources │ ├── Model │ │ └── .gitkeep │ └── Server │ │ ├── GreeterProvider.swift │ │ └── main.swift ├── Dockerfile └── Package.swift ├── cpp_asio_grpc_bench ├── .dockerignore ├── CMakeLists.txt └── Dockerfile ├── cpp_grpc_mt_bench ├── .dockerignore └── Dockerfile ├── cpp_grpc_st_bench ├── .dockerignore └── Dockerfile ├── dotnet_grpc_bench ├── .dockerignore ├── Dockerfile ├── GreeterServer │ ├── GreeterServer.csproj │ ├── Services │ │ └── GreeterService.cs │ ├── Program.cs │ └── ServiceProvidersMiddleware.cs └── Greeter.sln ├── erlang_grpcbox_bench ├── .dockerignore ├── config │ ├── vm.args │ └── sys.config ├── .gitignore ├── src │ ├── erlang_grpcbox_bench.app.src │ ├── erlang_grpcbox_bench_app.erl │ ├── egb_handler.erl │ └── erlang_grpcbox_bench_sup.erl ├── Dockerfile ├── rebar.lock └── rebar.config ├── lua_grpc_st_onhold ├── .dockerignore ├── conanfile.txt ├── greeter_service.lua ├── greeter_server.lua └── Dockerfile ├── rust_thruster_mt_bench ├── .gitignore ├── build.rs ├── Dockerfile ├── Cargo.toml └── src │ └── main.rs ├── rust_thruster_st_bench ├── .gitignore ├── build.rs ├── Dockerfile ├── Cargo.toml └── src │ └── main.rs ├── elixir_grpc_bench_onhold ├── .dockerignore ├── lib │ ├── endpoint.ex │ ├── helloworld_app.ex │ └── server.ex ├── config │ ├── dev.exs │ ├── prod.exs │ └── config.exs ├── rel │ ├── env.bat.eex │ ├── remote.vm.args.eex │ ├── vm.args.eex │ └── env.sh.eex ├── mix.exs ├── Dockerfile └── mix.lock ├── java_micronaut_workstealing_bench ├── settings.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ ├── application.yml │ │ └── logback.xml │ │ └── java │ │ └── helloworld │ │ ├── GreetingService.java │ │ ├── Application.java │ │ ├── GreetingEndpoint.java │ │ └── ServerBuilderListener.java ├── micronaut-cli.yml ├── Dockerfile ├── build.gradle └── gradlew.bat ├── node_grpcjs_st_bench ├── .dockerignore ├── Dockerfile ├── package.json └── greeter_server.js ├── scala_zio_bench ├── project │ ├── build.properties │ └── plugins.sbt ├── src │ └── main │ │ └── scala │ │ └── com │ │ └── example │ │ └── helloworld │ │ ├── GreeterImpl.scala │ │ └── GreeterServer.scala ├── Dockerfile └── build.sbt ├── scala_fs2_bench ├── project │ ├── build.properties │ └── plugins.sbt ├── build.sbt ├── src │ └── main │ │ └── scala │ │ └── com │ │ └── example │ │ └── helloworld │ │ ├── GreeterServiceImpl.scala │ │ └── GreeterServer.scala └── Dockerfile ├── haskell_grpc_haskell_bench ├── .gitignore ├── Makefile ├── cabal.project ├── grpc-haskell-bench.cabal ├── app │ └── Main.hs └── Dockerfile ├── java_micronaut_bench ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ └── main │ │ ├── resources │ │ ├── application.yml │ │ └── logback.xml │ │ └── java │ │ └── helloworld │ │ ├── GreetingService.java │ │ ├── Application.java │ │ └── GreetingEndpoint.java ├── micronaut-cli.yml ├── settings.gradle ├── Dockerfile └── build.gradle ├── scala_akka_bench ├── project │ ├── build.properties │ └── plugins.sbt ├── src │ └── main │ │ ├── resources │ │ └── application.conf │ │ └── scala │ │ └── com │ │ └── example │ │ └── helloworld │ │ ├── GreeterServiceImpl.scala │ │ └── GreeterServer.scala ├── Dockerfile └── build.sbt ├── scala_pekko_bench ├── project │ ├── build.properties │ └── plugins.sbt ├── src │ └── main │ │ ├── resources │ │ └── application.conf │ │ └── scala │ │ └── com │ │ └── example │ │ └── helloworld │ │ ├── GreeterServiceImpl.scala │ │ └── GreeterServer.scala ├── Dockerfile └── build.sbt ├── scenarios ├── string_10B │ ├── payload │ └── helloworld.proto ├── string_100B │ ├── payload │ └── helloworld.proto ├── complex_proto │ ├── payload │ └── helloworld.proto ├── string_1kB │ ├── payload │ └── helloworld.proto └── string_10kB │ └── helloworld.proto ├── kotlin_grpc_bench ├── settings.gradle.kts ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── Dockerfile ├── build.gradle.kts ├── src │ └── main │ │ └── kotlin │ │ └── io │ │ └── grpc │ │ └── examples │ │ └── helloworld │ │ └── HelloWorldServer.kt └── gradlew.bat ├── dart_grpc_onhold ├── .dockerignore ├── pubspec.yaml ├── Dockerfile └── bin │ └── server.dart ├── php_swoole_grpc_onhold ├── composer.json ├── Dockerfile └── server.php ├── java_quarkus_bench ├── .dockerignore ├── src │ └── main │ │ ├── resources │ │ └── application.properties │ │ └── java │ │ └── com │ │ └── example │ │ └── HelloService.java ├── .mvn │ └── wrapper │ │ └── maven-wrapper.properties ├── .gitignore └── Dockerfile ├── .scala-steward.conf ├── .gitignore ├── java_vertx_grpc_bench ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── Dockerfile ├── settings.gradle ├── build.gradle └── src │ └── main │ └── java │ └── vertx │ └── Main.java ├── java_hotspot_grpc_sgc_bench ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── settings.gradle └── Dockerfile ├── crystal_grpc_bench ├── shard.yml ├── src │ └── server.cr └── Dockerfile ├── rust_pajamax_bench ├── build.rs ├── Dockerfile ├── Cargo.toml ├── README.md └── src │ └── helloworld.rs ├── setup_scenario.sh ├── python_grpc_bench ├── Dockerfile └── server.py ├── ruby_grpc_bench ├── Dockerfile └── server.rb ├── go_connect_bench ├── go.mod ├── Dockerfile ├── example │ └── main.go └── go.sum ├── python_async_grpc_bench ├── Dockerfile └── server.py ├── collect_stats.sh ├── go_vtconnect_bench ├── go.mod ├── Dockerfile └── example │ └── main.go ├── .github ├── workflows │ ├── shellcheck.yml │ ├── rubocop.yml │ ├── bug_report.md │ └── issue_bench.yml ├── PULL_REQUEST_TEMPLATE.md └── dependabot.yml ├── java_hotspot_grpc_g1gc_bench └── Dockerfile ├── java_hotspot_grpc_pgc_bench └── Dockerfile ├── java_hotspot_grpc_she_bench └── Dockerfile ├── java_hotspot_grpc_zgc_bench └── Dockerfile ├── go_grpc_bench ├── go.mod ├── Dockerfile └── example │ └── main.go ├── go_vtgrpc_bench ├── go.mod ├── Dockerfile └── example │ └── main.go ├── example_benchmark.sh ├── CONTRIBUTING.md ├── java_openj9_grpc_gencon_bench ├── Dockerfile └── populate_scc.sh ├── detailed ├── java_openj9_grpc_nogc_bench │ └── Dockerfile ├── java_openj9_grpc_balanced_bench │ └── Dockerfile ├── java_openj9_grpc_metronome_bench │ └── Dockerfile ├── java_openj9_grpc_optavgpause_bench │ └── Dockerfile └── java_openj9_grpc_optthruput_bench │ └── Dockerfile ├── java_quarkus_native_bench └── Dockerfile ├── clean.sh ├── analyze.sh ├── LICENSE └── analyze └── results_analyze.rb /java_aot_bench/settings.gradle: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /rust_wtx_bench/.gitignore: -------------------------------------------------------------------------------- 1 | target -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | /*_bench/Dockerfile 2 | -------------------------------------------------------------------------------- /java_armeria_bench/settings.gradle: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /d_grpc_bench/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /php_grpc_bench/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /rust_grpcio_bench/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /rust_tonic_mt_bench/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /rust_tonic_st_bench/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /swift_grpc_bench/Sources/Model/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpp_asio_grpc_bench/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /cpp_grpc_mt_bench/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /cpp_grpc_st_bench/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /dotnet_grpc_bench/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /erlang_grpcbox_bench/.dockerignore: -------------------------------------------------------------------------------- 1 | .gitignore -------------------------------------------------------------------------------- /lua_grpc_st_onhold/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /rust_thruster_mt_bench/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /rust_thruster_st_bench/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/settings.gradle: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /node_grpcjs_st_bench/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | -------------------------------------------------------------------------------- /rust_grpcio_bench/src/proto/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod gen; 2 | -------------------------------------------------------------------------------- /scala_zio_bench/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.10.7 -------------------------------------------------------------------------------- /java_aot_bench/gradle.properties: -------------------------------------------------------------------------------- 1 | micronautVersion=2.5.1 2 | -------------------------------------------------------------------------------- /scala_fs2_bench/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.10.7 2 | -------------------------------------------------------------------------------- /haskell_grpc_haskell_bench/.gitignore: -------------------------------------------------------------------------------- 1 | dist-newstyle 2 | src-gen/ 3 | -------------------------------------------------------------------------------- /java_micronaut_bench/gradle.properties: -------------------------------------------------------------------------------- 1 | micronautVersion=2.5.1 2 | -------------------------------------------------------------------------------- /scala_akka_bench/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.10.7 2 | -------------------------------------------------------------------------------- /scala_pekko_bench/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.11.7 2 | -------------------------------------------------------------------------------- /scenarios/string_10B/payload: -------------------------------------------------------------------------------- 1 | {"request":{"name":"1234567890"}} 2 | -------------------------------------------------------------------------------- /kotlin_grpc_bench/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "examples" 2 | -------------------------------------------------------------------------------- /dart_grpc_onhold/.dockerignore: -------------------------------------------------------------------------------- 1 | .dockerignore 2 | Dockerfile 3 | .dart_tool/ -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/gradle.properties: -------------------------------------------------------------------------------- 1 | micronautVersion=2.5.1 2 | -------------------------------------------------------------------------------- /rust_grpcio_bench/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = [ "-C", "target-cpu=native" ] 3 | -------------------------------------------------------------------------------- /rust_grpcio_bench/src/proto/gen/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod helloworld; 2 | pub mod helloworld_grpc; 3 | -------------------------------------------------------------------------------- /rust_tonic_mt_bench/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = [ "-C", "target-cpu=native" ] 3 | -------------------------------------------------------------------------------- /rust_tonic_st_bench/.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = [ "-C", "target-cpu=native" ] 3 | -------------------------------------------------------------------------------- /rust_wtx_bench/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = [ "-C", "target-cpu=native" ] 3 | -------------------------------------------------------------------------------- /rust_wtx_bench/src/grpc_bindings.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/protos/mod.rs")); 2 | -------------------------------------------------------------------------------- /rust_wtx_bench/rust-toolchain: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2025-10-31" 3 | profile = "minimal" 4 | -------------------------------------------------------------------------------- /php_swoole_grpc_onhold/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "swoole/grpc": "^1.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /java_quarkus_bench/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !target/*-runner 3 | !target/*-runner.jar 4 | !target/lib/* 5 | !target/quarkus-app/* -------------------------------------------------------------------------------- /rust_tonic_mt_bench/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | tonic_build::compile_protos("proto/helloworld/helloworld.proto").unwrap(); 3 | } 4 | -------------------------------------------------------------------------------- /rust_tonic_st_bench/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | tonic_build::compile_protos("proto/helloworld/helloworld.proto").unwrap(); 3 | } 4 | -------------------------------------------------------------------------------- /.scala-steward.conf: -------------------------------------------------------------------------------- 1 | buildRoots = [".", "scala_akka_bench", "scala_fs2_bench", "scala_zio_bench"] 2 | pullRequests.frequency = "90 days" 3 | -------------------------------------------------------------------------------- /java_quarkus_bench/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | quarkus.grpc.server.port=50051 2 | quarkus.arc.context-propagation.enabled=false -------------------------------------------------------------------------------- /rust_thruster_mt_bench/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | prost_build::compile_protos(&["proto/helloworld/helloworld.proto"], &["proto/"]).unwrap(); 3 | } 4 | -------------------------------------------------------------------------------- /rust_thruster_st_bench/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | prost_build::compile_protos(&["proto/helloworld/helloworld.proto"], &["proto/"]).unwrap(); 3 | } 4 | -------------------------------------------------------------------------------- /java_aot_bench/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesnyRumcajs/grpc_bench/HEAD/java_aot_bench/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /scenarios/string_100B/payload: -------------------------------------------------------------------------------- 1 | {"request":{"name":"The grpc server implementation is not as performant as we expected. This's extremely bad technology."}} 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | results/ 2 | *.tmp 3 | proto/ 4 | payload/ 5 | 6 | # Gradle and IntelliJ 7 | .idea/ 8 | .gradle/ 9 | 10 | # Build output 11 | build/ 12 | -------------------------------------------------------------------------------- /java_armeria_bench/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesnyRumcajs/grpc_bench/HEAD/java_armeria_bench/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /kotlin_grpc_bench/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesnyRumcajs/grpc_bench/HEAD/kotlin_grpc_bench/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /scala_fs2_bench/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("org.typelevel" % "sbt-fs2-grpc" % "2.7.21") 2 | 3 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.3.1") 4 | -------------------------------------------------------------------------------- /java_micronaut_bench/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesnyRumcajs/grpc_bench/HEAD/java_micronaut_bench/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /java_aot_bench/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | application: 3 | name: hello-world-java 4 | grpc: 5 | server: 6 | port: 50051 7 | -------------------------------------------------------------------------------- /java_vertx_grpc_bench/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesnyRumcajs/grpc_bench/HEAD/java_vertx_grpc_bench/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /java_micronaut_bench/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | application: 3 | name: hello-world-java 4 | grpc: 5 | server: 6 | port: 50051 7 | -------------------------------------------------------------------------------- /scala_pekko_bench/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("org.apache.pekko" % "pekko-grpc-sbt-plugin" % "1.2.0") 2 | 3 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.3.1") 4 | -------------------------------------------------------------------------------- /java_hotspot_grpc_sgc_bench/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesnyRumcajs/grpc_bench/HEAD/java_hotspot_grpc_sgc_bench/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /crystal_grpc_bench/shard.yml: -------------------------------------------------------------------------------- 1 | name: crystal_grpc_test 2 | version: 0.1.0 3 | dependencies: 4 | logger: 5 | github: crystal-lang/logger.cr 6 | grpc: 7 | github: jgaskins/grpc 8 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/lib/endpoint.ex: -------------------------------------------------------------------------------- 1 | defmodule Helloworld.Endpoint do 2 | use GRPC.Endpoint 3 | 4 | intercept(GRPC.Logger.Server) 5 | run(Helloworld.Greeter.Server) 6 | end 7 | -------------------------------------------------------------------------------- /lua_grpc_st_onhold/conanfile.txt: -------------------------------------------------------------------------------- 1 | [requires] 2 | grpc_cb_core/0.1@jinq0123/testing 3 | lua-cpp/5.3.4@jinq0123/testing 4 | lua-intf/0.1@jinq0123/testing 5 | 6 | [generators] 7 | cmake 8 | -------------------------------------------------------------------------------- /java_aot_bench/src/main/resources/META-INF/native-image/helloworld/basic-application/native-image.properties: -------------------------------------------------------------------------------- 1 | Args = -H:Name=hello-world-java \ 2 | -H:Class=helloworld.Application 3 | -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesnyRumcajs/grpc_bench/HEAD/java_micronaut_workstealing_bench/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | application: 3 | name: hello-world-java 4 | grpc: 5 | server: 6 | port: 50051 7 | -------------------------------------------------------------------------------- /dart_grpc_onhold/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: helloworld 2 | 3 | environment: 4 | sdk: '>=2.19.0 <3.0.0' 5 | 6 | dependencies: 7 | async: ^2.10.0 8 | grpc: ^3.1.0 9 | protobuf: ^2.1.0 10 | -------------------------------------------------------------------------------- /rust_pajamax_bench/build.rs: -------------------------------------------------------------------------------- 1 | fn main() -> Result<(), Box> { 2 | pajamax_build::compile_protos_in_local(&["proto/helloworld/helloworld.proto"], &["."])?; 3 | Ok(()) 4 | } 5 | -------------------------------------------------------------------------------- /rust_wtx_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1.82 2 | WORKDIR /app 3 | COPY rust_wtx_bench /app 4 | COPY proto /app/protos 5 | RUN cargo build --release 6 | ENTRYPOINT ["/app/target/release/helloworld-server"] -------------------------------------------------------------------------------- /php_grpc_bench/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "spiral/php-grpc": "^1.0" 4 | }, 5 | "autoload": { 6 | "psr-4": { 7 | "": "src/" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /node_grpcjs_st_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20.3 2 | 3 | WORKDIR /app 4 | COPY node_grpcjs_st_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN npm install 8 | 9 | ENTRYPOINT [ "node", "greeter_server.js" ] 10 | -------------------------------------------------------------------------------- /scenarios/complex_proto/payload: -------------------------------------------------------------------------------- 1 | {"request":{"name":"a name","d":4.55332,"f":232.3,"b":true,"n":32,"l":444325235223,"c1":"ofcouse","pets":[{"name":"Bof the dog","color":"BLUE"}, {"name":"Kim the cat","color":"RED"}]}} 2 | -------------------------------------------------------------------------------- /scala_akka_bench/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.lightbend.akka.grpc" % "sbt-akka-grpc" % "2.3.2") 2 | 3 | addSbtPlugin("com.github.sbt" % "sbt-javaagent" % "0.1.8") 4 | 5 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.3.1") 6 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/config/dev.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | 3 | config :grpc, start_server: true 4 | 5 | config :logger, 6 | level: :debug, 7 | compile_time_purge_level: :debug, 8 | sync_threshold: 10_000, 9 | truncate: 4096 10 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/config/prod.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | 3 | config :grpc, start_server: true 4 | 5 | config :logger, 6 | level: :debug, 7 | compile_time_purge_level: :debug, 8 | sync_threshold: 10_000, 9 | truncate: 4096 10 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/config/config.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | 3 | config :grpc, start_server: true 4 | 5 | config :logger, 6 | level: :debug, 7 | compile_time_purge_level: :debug, 8 | sync_threshold: 10_000, 9 | truncate: 4096 10 | -------------------------------------------------------------------------------- /rust_thruster_mt_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1.82 2 | 3 | WORKDIR /app 4 | COPY rust_thruster_mt_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN cargo build --release --locked 8 | 9 | ENTRYPOINT ["/app/target/release/helloworld-server"] 10 | -------------------------------------------------------------------------------- /rust_thruster_st_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1.82 2 | 3 | WORKDIR /app 4 | COPY rust_thruster_st_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN cargo build --release --locked 8 | 9 | ENTRYPOINT ["/app/target/release/helloworld-server"] 10 | -------------------------------------------------------------------------------- /erlang_grpcbox_bench/config/vm.args: -------------------------------------------------------------------------------- 1 | -name erlang_grpcbox_bench@127.0.0.1 2 | -setcookie erlang_grpcbox_bench 3 | 4 | # https://www.erlang.org/doc/man/erl.html 5 | 6 | +A 10 7 | 8 | +K true 9 | 10 | +sbwt none 11 | +sbwtdcpu none 12 | +sbwtdio none 13 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/rel/env.bat.eex: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem Set the release to work across nodes. 3 | rem RELEASE_DISTRIBUTION must be "sname" (local), "name" (distributed) or "none". 4 | rem set RELEASE_DISTRIBUTION=name 5 | rem set RELEASE_NODE=<%= @release.name %> 6 | -------------------------------------------------------------------------------- /d_grpc_bench/dub.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "description": "A simple example for gRPC.", 4 | "license": "MIT", 5 | "targetType": "executable", 6 | "dependencies": { 7 | "grpc" :{"path": "grpc-dlang"} 8 | }, 9 | "dflags-ldc": ["-flto=full"] 10 | } 11 | -------------------------------------------------------------------------------- /java_aot_bench/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /java_aot_bench/src/main/java/helloworld/GreetingService.java: -------------------------------------------------------------------------------- 1 | package helloworld; 2 | 3 | import javax.inject.Singleton; 4 | 5 | @Singleton 6 | public class GreetingService { 7 | 8 | String sayHello(String name) { 9 | return name; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /java_armeria_bench/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /java_micronaut_bench/src/main/java/helloworld/GreetingService.java: -------------------------------------------------------------------------------- 1 | package helloworld; 2 | 3 | import javax.inject.Singleton; 4 | 5 | @Singleton 6 | public class GreetingService { 7 | 8 | String sayHello(String name) { 9 | return name; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /java_quarkus_bench/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /kotlin_grpc_bench/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /java_aot_bench/src/main/java/helloworld/Application.java: -------------------------------------------------------------------------------- 1 | package helloworld; 2 | 3 | import io.micronaut.runtime.Micronaut; 4 | 5 | public class Application { 6 | 7 | public static void main(String[] args) { 8 | Micronaut.run(Application.class); 9 | } 10 | } -------------------------------------------------------------------------------- /java_micronaut_bench/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /java_micronaut_bench/micronaut-cli.yml: -------------------------------------------------------------------------------- 1 | applicationType: grpc 2 | defaultPackage: helloworld 3 | testFramework: junit 4 | sourceLanguage: java 5 | buildTool: gradle 6 | features: [annotation-api, app-name, gradle, grpc, java, java-application, junit, logback, readme, shade, yaml] 7 | -------------------------------------------------------------------------------- /java_vertx_grpc_bench/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /java_hotspot_grpc_sgc_bench/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /java_micronaut_bench/src/main/java/helloworld/Application.java: -------------------------------------------------------------------------------- 1 | package helloworld; 2 | 3 | import io.micronaut.runtime.Micronaut; 4 | 5 | public class Application { 6 | 7 | public static void main(String[] args) { 8 | Micronaut.run(Application.class); 9 | } 10 | } -------------------------------------------------------------------------------- /java_micronaut_bench/settings.gradle: -------------------------------------------------------------------------------- 1 | dependencyResolutionManagement { 2 | repositories { 3 | mavenCentral() 4 | } 5 | versionCatalogs { 6 | create("mn") { 7 | from("io.micronaut.platform:micronaut-platform:4.0.0") 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/micronaut-cli.yml: -------------------------------------------------------------------------------- 1 | applicationType: grpc 2 | defaultPackage: com.example 3 | testFramework: junit 4 | sourceLanguage: java 5 | buildTool: gradle 6 | features: [annotation-api, app-name, gradle, grpc, java, java-application, junit, logback, readme, shade, yaml] 7 | -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/src/main/java/helloworld/GreetingService.java: -------------------------------------------------------------------------------- 1 | package helloworld; 2 | 3 | import javax.inject.Singleton; 4 | 5 | @Singleton 6 | public class GreetingService { 7 | 8 | String sayHello(String name) { 9 | return name; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /scala_akka_bench/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | akka.http.server.max-connections = 1500 2 | akka.http.server.preview.enable-http2 = on 3 | akka.http.server.http2.min-collect-strict-entity-size = 1 4 | akka.actor.default-dispatcher.fork-join-executor.parallelism-max = ${GRPC_SERVER_CPUS} 5 | -------------------------------------------------------------------------------- /dotnet_grpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/sdk:9.0 2 | 3 | WORKDIR /app 4 | COPY dotnet_grpc_bench /app 5 | COPY proto /proto 6 | 7 | RUN dotnet build -c Release Greeter.sln 8 | 9 | ENTRYPOINT [ "dotnet", "run" , "-c", "Release", "-p", "GreeterServer", "--no-build" ] 10 | -------------------------------------------------------------------------------- /scala_pekko_bench/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | pekko.http.server.max-connections = 1500 2 | pekko.http.server.preview.enable-http2 = on 3 | pekko.http.server.http2.min-collect-strict-entity-size = 1 4 | pekko.actor.default-dispatcher.fork-join-executor.parallelism-max = ${GRPC_SERVER_CPUS} 5 | -------------------------------------------------------------------------------- /d_grpc_bench/dub.selections.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileVersion": 1, 3 | "versions": { 4 | "grpc": {"path":"grpc-dlang"}, 5 | "hunt": "1.7.15", 6 | "hunt-extra": "1.2.3", 7 | "hunt-http": "0.8.1", 8 | "hunt-net": "0.7.1", 9 | "hunt-openssl": "1.0.5", 10 | "protobuf": "0.6.2" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/src/main/java/helloworld/Application.java: -------------------------------------------------------------------------------- 1 | package helloworld; 2 | 3 | import io.micronaut.runtime.Micronaut; 4 | 5 | public class Application { 6 | 7 | public static void main(String[] args) { 8 | Micronaut.run(Application.class); 9 | } 10 | } -------------------------------------------------------------------------------- /rust_pajamax_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1.82 2 | 3 | WORKDIR /app 4 | COPY rust_pajamax_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN apt-get update && apt-get install -y cmake protobuf-compiler-grpc 8 | RUN cargo build --release 9 | 10 | ENTRYPOINT ["/app/target/release/helloworld"] 11 | -------------------------------------------------------------------------------- /java_aot_bench/micronaut-cli.yml: -------------------------------------------------------------------------------- 1 | applicationType: default 2 | defaultPackage: helloworld 3 | testFramework: junit 4 | sourceLanguage: java 5 | buildTool: gradle 6 | features: [annotation-api, app-name, graalvm, gradle, http-client, java, java-application, junit, logback, netty-server, readme, shade, yaml] 7 | -------------------------------------------------------------------------------- /rust_grpcio_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1.82 2 | 3 | RUN apt update && apt install -y protobuf-compiler cmake 4 | 5 | WORKDIR /app 6 | COPY rust_grpcio_bench /app 7 | COPY proto /app/src/proto 8 | 9 | RUN cargo build --release --locked 10 | 11 | ENTRYPOINT ["/app/target/release/helloworld-server"] 12 | -------------------------------------------------------------------------------- /scala_fs2_bench/build.sbt: -------------------------------------------------------------------------------- 1 | name := "fs2-grpc-quickstart-scala" 2 | 3 | version := "1.0" 4 | 5 | scalaVersion := "2.13.16" 6 | 7 | run / fork := true 8 | 9 | enablePlugins(Fs2Grpc) 10 | 11 | libraryDependencies ++= Seq( 12 | "io.grpc" % "grpc-netty-shaded" % scalapb.compiler.Version.grpcJavaVersion 13 | ) 14 | -------------------------------------------------------------------------------- /php_grpc_bench/.rr.yaml: -------------------------------------------------------------------------------- 1 | grpc: 2 | listen: "tcp://:50051" 3 | proto: "proto/helloworld/helloworld.proto" 4 | workers: 5 | command: "php worker.php" 6 | pool: 7 | numWorkers: 4 8 | 9 | limit: 10 | interval: 1 11 | services: 12 | grpc: 13 | TTL: 0 14 | idleTTL: 0 15 | execTTL: 60 16 | -------------------------------------------------------------------------------- /php_swoole_grpc_onhold/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM phpswoole/swoole:php8.1-alpine 2 | 3 | WORKDIR /app 4 | 5 | COPY php_swoole_grpc_bench/composer.json /app/composer.json 6 | COPY php_swoole_grpc_bench/server.php /app/server.php 7 | 8 | RUN composer install --optimize-autoloader --classmap-authoritative 9 | 10 | CMD php server.php 11 | -------------------------------------------------------------------------------- /setup_scenario.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | SCENARIO=$1 4 | COPY_PAYLOAD=$2 5 | 6 | rm -rf proto 7 | mkdir -p proto/helloworld 8 | cp scenarios/"${SCENARIO}"/helloworld.proto proto/helloworld 9 | 10 | if ${COPY_PAYLOAD}; then 11 | rm -rf payload 12 | mkdir -p payload 13 | cp scenarios/"${SCENARIO}"/payload payload/payload 14 | fi 15 | -------------------------------------------------------------------------------- /rust_grpcio_bench/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let proto_root = "src/proto/helloworld"; 3 | let proto_out = "src/proto/gen"; 4 | println!("cargo:rerun-if-changed={}", proto_root); 5 | protoc_grpcio::compile_grpc_protos(&["helloworld.proto"], &[proto_root], &proto_out, None) 6 | .expect("Failed to compile gRPC definitions!"); 7 | } 8 | -------------------------------------------------------------------------------- /python_grpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.13-slim 2 | 3 | WORKDIR /app 4 | COPY python_grpc_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN python -m pip install grpcio grpcio-tools 8 | RUN python -m grpc_tools.protoc -I/app/proto/helloworld --python_out=. --grpc_python_out=. helloworld.proto 9 | 10 | ENTRYPOINT [ "python", "/app/server.py" ] 11 | -------------------------------------------------------------------------------- /rust_tonic_mt_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1.82 2 | 3 | WORKDIR /app 4 | COPY rust_tonic_mt_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN apt-get update && apt-get install -y cmake protobuf-compiler-grpc 8 | RUN rustup component add rustfmt 9 | RUN cargo build --release --locked 10 | 11 | ENTRYPOINT ["/app/target/release/helloworld-server"] 12 | -------------------------------------------------------------------------------- /rust_tonic_st_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1.82 2 | 3 | WORKDIR /app 4 | COPY rust_tonic_st_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN apt-get update && apt-get install -y cmake protobuf-compiler-grpc 8 | RUN rustup component add rustfmt 9 | RUN cargo build --release --locked 10 | 11 | ENTRYPOINT ["/app/target/release/helloworld-server"] 12 | -------------------------------------------------------------------------------- /node_grpcjs_st_bench/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grpc-examples", 3 | "version": "0.1.0", 4 | "dependencies": { 5 | "@grpc/proto-loader": "^0.7.2", 6 | "async": "^3.2.4", 7 | "google-protobuf": "^3.21.0", 8 | "@grpc/grpc-js": "^1.8.15", 9 | "lodash": "^4.6.1", 10 | "minimist": "^1.2.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /java_hotspot_grpc_sgc_bench/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { // The google mirror is less flaky than mavenCentral() 4 | url "https://maven-central.storage-download.googleapis.com/repos/central/data/" 5 | } 6 | gradlePluginPortal() 7 | } 8 | } 9 | 10 | rootProject.name = 'examples' 11 | -------------------------------------------------------------------------------- /ruby_grpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:3 2 | 3 | WORKDIR /app 4 | COPY ruby_grpc_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN gem install grpc grpc-tools 8 | RUN mkdir -p /app/lib && grpc_tools_ruby_protoc -I /app/proto/helloworld /app/proto/helloworld/helloworld.proto --ruby_out=/app/lib --grpc_out=/app/lib 9 | 10 | ENTRYPOINT ruby server.rb 11 | 12 | -------------------------------------------------------------------------------- /go_connect_bench/go.mod: -------------------------------------------------------------------------------- 1 | module example 2 | 3 | go 1.22 4 | toolchain go1.24.1 5 | 6 | require ( 7 | connectrpc.com/connect v1.16.1 8 | go.uber.org/automaxprocs v1.5.3 9 | golang.org/x/net v0.38.0 10 | ) 11 | 12 | require ( 13 | golang.org/x/text v0.23.0 // indirect 14 | google.golang.org/protobuf v1.33.0 // indirect 15 | ) 16 | 17 | replace local => ./ 18 | -------------------------------------------------------------------------------- /erlang_grpcbox_bench/.gitignore: -------------------------------------------------------------------------------- 1 | .rebar3 2 | _* 3 | .eunit 4 | *.o 5 | *.beam 6 | *.plt 7 | *.swp 8 | *.swo 9 | .erlang.cookie 10 | ebin 11 | log 12 | erl_crash.dump 13 | .rebar 14 | logs 15 | .idea 16 | *.iml 17 | rebar3.crashdump 18 | *~ 19 | 20 | _build 21 | 22 | /src/helloworld_greeter_bhvr.erl 23 | /src/helloworld_greeter_client.erl 24 | /src/helloworld_pb.erl 25 | -------------------------------------------------------------------------------- /python_async_grpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.13-slim 2 | 3 | WORKDIR /app 4 | COPY python_async_grpc_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN python -m pip install grpcio grpcio-tools asyncio 8 | RUN python -m grpc_tools.protoc -I/app/proto/helloworld --python_out=. --grpc_python_out=. helloworld.proto 9 | 10 | ENTRYPOINT [ "python", "/app/server.py" ] 11 | -------------------------------------------------------------------------------- /scala_zio_bench/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | val zioGrpcVersion = "0.6.3" 2 | 3 | addSbtPlugin("com.thesamet" % "sbt-protoc" % "1.0.7") 4 | 5 | libraryDependencies ++= Seq( 6 | "com.thesamet.scalapb.zio-grpc" %% "zio-grpc-codegen" % zioGrpcVersion, 7 | "com.thesamet.scalapb" %% "compilerplugin" % "0.11.17" 8 | ) 9 | 10 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.3.1") 11 | -------------------------------------------------------------------------------- /collect_stats.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | NAME=$1 4 | REPORT_DIR=${2:-"results"} 5 | 6 | rm -f "${REPORT_DIR}"/"${NAME}".stats 7 | 8 | sleep 1 9 | 10 | while true; do 11 | (docker stats \ 12 | --no-stream \ 13 | --format "table {{.CPUPerc}}\t{{.MemUsage}}" \ 14 | "${NAME}" | grep -v CPU) >>"${REPORT_DIR}"/"${NAME}".stats 2>/dev/null || break 15 | sleep 5 || break 16 | done 17 | -------------------------------------------------------------------------------- /d_grpc_bench/source/GreeterImpl.d: -------------------------------------------------------------------------------- 1 | module GreeterImpl; 2 | 3 | import helloworld.helloworld; 4 | import helloworld.helloworldRpc; 5 | import grpc; 6 | 7 | /** 8 | * 9 | */ 10 | class GreeterImpl : GreeterBase { 11 | override Status SayHello(HelloRequest request, ref HelloReply reply) { 12 | reply.response = request.request; 13 | return Status.OK; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /go_vtconnect_bench/go.mod: -------------------------------------------------------------------------------- 1 | module example 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | connectrpc.com/connect v1.16.1 7 | go.akshayshah.org/connectproto v0.6.0 8 | go.uber.org/automaxprocs v1.5.3 9 | golang.org/x/net v0.38.0 10 | ) 11 | 12 | require ( 13 | golang.org/x/text v0.23.0 // indirect 14 | google.golang.org/protobuf v1.33.0 // indirect 15 | ) 16 | 17 | replace local => ./ 18 | -------------------------------------------------------------------------------- /.github/workflows/shellcheck.yml: -------------------------------------------------------------------------------- 1 | name: ShellCheck 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | shellcheck: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v4 13 | 14 | - name: Run shellcheck 15 | uses: ludeeus/action-shellcheck@2.0.0 16 | with: 17 | check_together: 'yes' 18 | severity: error 19 | -------------------------------------------------------------------------------- /java_micronaut_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:23-jdk-noble 2 | 3 | WORKDIR /app 4 | COPY java_micronaut_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 6 | 7 | RUN /app/gradlew installDist 8 | 9 | ENV GC "-XX:+UseParallelGC" 10 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 11 | 12 | ENTRYPOINT ["/app/build/install/app/bin/app"] 13 | 14 | -------------------------------------------------------------------------------- /rust_pajamax_bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_pajamax" 3 | version = "0.2.0" 4 | authors = ["Wu Bingzheng "] 5 | edition = "2021" 6 | license = "MIT" 7 | 8 | [[bin]] 9 | name = "helloworld" 10 | path = "src/helloworld.rs" 11 | 12 | [dependencies] 13 | pajamax = "0.2.0" 14 | prost = "0.13.5" 15 | 16 | [build-dependencies] 17 | pajamax-build = "0.2.0" 18 | prost-build = "0.14.1" 19 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/lib/helloworld_app.ex: -------------------------------------------------------------------------------- 1 | defmodule HelloworldApp do 2 | use Application 3 | 4 | def start(_type, _args) do 5 | children = [ 6 | {GRPC.Server.Supervisor, 7 | {Helloworld.Endpoint, 50051, [num_acceptors: 1000, max_connections: 1_000_000]}} 8 | ] 9 | 10 | opts = [strategy: :one_for_one, name: HelloworldApp] 11 | Supervisor.start_link(children, opts) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:23-jdk-noble 2 | 3 | WORKDIR /app 4 | COPY java_micronaut_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 6 | 7 | RUN /app/gradlew installDist 8 | 9 | ENV GC "-XX:+UseParallelGC" 10 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 11 | 12 | ENTRYPOINT ["/app/build/install/app/bin/app"] 13 | 14 | -------------------------------------------------------------------------------- /kotlin_grpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:23-jdk-noble 2 | 3 | WORKDIR /app 4 | COPY kotlin_grpc_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/hello_world.proto 6 | 7 | RUN /app/gradlew installDist 8 | 9 | ENV GC "-XX:+UseParallelGC" 10 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 11 | 12 | ENTRYPOINT [ "/app/build/install/examples/bin/hello-world-server" ] 13 | -------------------------------------------------------------------------------- /java_aot_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/graalvm/graalvm-ce:ol8-java17-22.3.3 as rel 2 | 3 | WORKDIR /app 4 | COPY java_aot_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 6 | 7 | RUN /app/gradlew assemble 8 | 9 | RUN gu install native-image 10 | 11 | RUN native-image --no-server --static --no-fallback -jar /app/build/libs/app-0.1-all.jar 12 | 13 | ENTRYPOINT [ "/app/hello-world-java" ] 14 | -------------------------------------------------------------------------------- /java_vertx_grpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:23-jdk-noble 2 | 3 | WORKDIR /app 4 | COPY java_vertx_grpc_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 6 | 7 | RUN /app/gradlew assemble 8 | 9 | ENV GC "-XX:+UseSerialGC" 10 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 11 | 12 | ENTRYPOINT ["java", "-jar", "/app/build/libs/java_vertx_grpc_bench-all.jar" ] 13 | -------------------------------------------------------------------------------- /java_hotspot_grpc_g1gc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:23-jdk-noble 2 | 3 | WORKDIR /app 4 | COPY java_hotspot_grpc_sgc_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 6 | 7 | RUN /app/gradlew installDist 8 | 9 | ENV GC "-XX:+UseG1GC" 10 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 11 | 12 | ENTRYPOINT [ "/app/build/install/examples/bin/hello-world-server" ] 13 | -------------------------------------------------------------------------------- /java_hotspot_grpc_sgc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:23-jdk-noble 2 | 3 | WORKDIR /app 4 | COPY java_hotspot_grpc_sgc_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 6 | 7 | RUN /app/gradlew installDist 8 | 9 | ENV GC "-XX:+UseSerialGC" 10 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 11 | 12 | ENTRYPOINT [ "/app/build/install/examples/bin/hello-world-server" ] 13 | -------------------------------------------------------------------------------- /java_vertx_grpc_bench/settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user manual at https://docs.gradle.org/7.5.1/userguide/multi_project_builds.html 8 | */ 9 | 10 | rootProject.name = 'java_vertx_grpc_bench' 11 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/lib/server.ex: -------------------------------------------------------------------------------- 1 | defmodule Helloworld.Greeter.Server do 2 | use GRPC.Server, service: Helloworld.Greeter.Service, compressors: [GRPC.Compressor.Gzip] 3 | 4 | alias Helloworld.HelloReply 5 | 6 | @spec say_hello(Helloworld.HelloRequest.t(), GRPC.Server.Stream.t()) :: 7 | Helloworld.HelloReply.t() 8 | def say_hello(request, _stream) do 9 | HelloReply.new(response: request.request) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/rel/remote.vm.args.eex: -------------------------------------------------------------------------------- 1 | ## Customize flags given to the VM: https://erlang.org/doc/man/erl.html 2 | ## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here 3 | 4 | ## Number of dirty schedulers doing IO work (file, sockets, and others) 5 | ##+SDio 5 6 | 7 | ## Increase number of concurrent ports/sockets 8 | ##+Q 65536 9 | 10 | ## Tweak GC to run more often 11 | ##-env ERL_FULLSWEEP_AFTER 10 12 | -------------------------------------------------------------------------------- /java_hotspot_grpc_pgc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:23-jdk-noble 2 | 3 | WORKDIR /app 4 | COPY java_hotspot_grpc_sgc_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 6 | 7 | RUN /app/gradlew installDist 8 | 9 | ENV GC "-XX:+UseParallelGC" 10 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 11 | 12 | ENTRYPOINT [ "/app/build/install/examples/bin/hello-world-server" ] 13 | -------------------------------------------------------------------------------- /java_hotspot_grpc_she_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:23-jdk-noble 2 | 3 | WORKDIR /app 4 | COPY java_hotspot_grpc_sgc_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 6 | 7 | RUN /app/gradlew installDist 8 | 9 | ENV GC "-XX:+UseShenandoahGC" 10 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 11 | 12 | ENTRYPOINT [ "/app/build/install/examples/bin/hello-world-server" ] 13 | 14 | -------------------------------------------------------------------------------- /haskell_grpc_haskell_bench/Makefile: -------------------------------------------------------------------------------- 1 | CABAL ?= cabal 2 | PROTO_COMPILE_HS = ~/.cabal/bin/compile-proto-file 3 | 4 | grpc-haskell: 5 | ($(CABAL) build proto3-suite && mkdir -p ~/.cabal/bin && \ 6 | $(CABAL) exec which compile-proto-file | tail -1 | xargs -I{} cp {} $(PROTO_COMPILE_HS)) 7 | ($(PROTO_COMPILE_HS) \ 8 | --includeDir /usr/local/include \ 9 | --includeDir ../proto/helloworld \ 10 | --proto helloworld.proto \ 11 | --out ./src-gen/) 12 | -------------------------------------------------------------------------------- /java_hotspot_grpc_zgc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:23-jdk-noble 2 | 3 | WORKDIR /app 4 | COPY java_hotspot_grpc_sgc_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 6 | 7 | RUN /app/gradlew installDist 8 | 9 | ENV GC "-XX:+UseZGC -XX:+ZGenerational" 10 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 11 | 12 | ENTRYPOINT [ "/app/build/install/examples/bin/hello-world-server" ] 13 | -------------------------------------------------------------------------------- /java_armeria_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:23-jdk-noble 2 | 3 | WORKDIR /app 4 | COPY java_armeria_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 6 | 7 | RUN /app/gradlew installDist 8 | 9 | ENV GC "-XX:+UseG1GC" 10 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70 -Dcom.linecorp.armeria.validateHeaders=false" 11 | 12 | ENTRYPOINT [ "/app/build/install/app/bin/hello-world-server" ] 13 | -------------------------------------------------------------------------------- /php_grpc_bench/worker.php: -------------------------------------------------------------------------------- 1 | registerService(\Helloworld\GreeterInterface::class, new HelloworldService()); 14 | 15 | $w = new RoadRunner\Worker(new Goridge\StreamRelay(STDIN, STDOUT)); 16 | $server->serve($w); 17 | -------------------------------------------------------------------------------- /go_grpc_bench/go.mod: -------------------------------------------------------------------------------- 1 | module example 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | go.uber.org/automaxprocs v1.5.3 7 | google.golang.org/grpc v1.63.2 8 | ) 9 | 10 | require ( 11 | golang.org/x/net v0.38.0 // indirect 12 | golang.org/x/sys v0.31.0 // indirect 13 | golang.org/x/text v0.23.0 // indirect 14 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect 15 | google.golang.org/protobuf v1.33.0 // indirect 16 | ) 17 | 18 | replace local => ./ 19 | -------------------------------------------------------------------------------- /rust_grpcio_bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_grpcio" 3 | version = "0.1.0" 4 | authors = ["Trisfald "] 5 | edition = "2021" 6 | 7 | [profile.release] 8 | opt-level = 3 9 | codegen-units = 1 10 | lto = true 11 | 12 | [dependencies] 13 | jemallocator = "0.5.4" 14 | grpcio = "0.13" 15 | protobuf = "2" 16 | futures = "0.3" 17 | 18 | [build-dependencies] 19 | protoc-grpcio = "3" 20 | 21 | [[bin]] 22 | name = "helloworld-server" 23 | path = "src/main.rs" 24 | -------------------------------------------------------------------------------- /d_grpc_bench/source/server.d: -------------------------------------------------------------------------------- 1 | module server; 2 | 3 | import GreeterImpl; 4 | import grpc; 5 | import hunt.logging; 6 | import std.stdio; 7 | 8 | void main() 9 | { 10 | string host = "0.0.0.0"; 11 | ushort port = 50051; 12 | 13 | GrpcServer server = new GrpcServer(); 14 | server.listen(host , port); 15 | server.register(new GreeterImpl.GreeterImpl()); 16 | server.start(); 17 | 18 | writeln("Server started on ", host, ":", port); 19 | 20 | getchar(); 21 | } 22 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/rel/vm.args.eex: -------------------------------------------------------------------------------- 1 | ## Customize flags given to the VM: https://erlang.org/doc/man/erl.html 2 | ## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here 3 | 4 | ## Number of dirty schedulers doing IO work (file, sockets, and others) 5 | ##+SDio 5 6 | 7 | ## Increase number of concurrent ports/sockets 8 | ##+Q 65536 9 | 10 | ## Tweak GC to run more often 11 | ##-env ERL_FULLSWEEP_AFTER 10 12 | +sbwt none 13 | +sbwtdcpu none 14 | +sbwtdio none 15 | +K true 16 | -------------------------------------------------------------------------------- /dotnet_grpc_bench/GreeterServer/GreeterServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /scala_zio_bench/src/main/scala/com/example/helloworld/GreeterImpl.scala: -------------------------------------------------------------------------------- 1 | package com.example.helloworld 2 | 3 | import io.grpc.StatusException 4 | import io.grpc.examples.helloworld.helloworld.ZioHelloworld.Greeter 5 | import io.grpc.examples.helloworld.helloworld.{HelloReply, HelloRequest} 6 | import zio.{IO, ZIO} 7 | 8 | 9 | object GreeterImpl extends Greeter { 10 | override def sayHello(request: HelloRequest): IO[StatusException, HelloReply] = 11 | ZIO.succeed(HelloReply(request.request)) 12 | } 13 | -------------------------------------------------------------------------------- /php_grpc_bench/src/HelloworldService.php: -------------------------------------------------------------------------------- 1 | setResponse($in->getRequest()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Summary of changes** 2 | Changes introduced in this pull request: 3 | - 4 | 5 | 6 | 7 | **Reference issue to close (if applicable)** 8 | 9 | 10 | 11 | 12 | **Other information and links** 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /erlang_grpcbox_bench/src/erlang_grpcbox_bench.app.src: -------------------------------------------------------------------------------- 1 | {application, erlang_grpcbox_bench, 2 | [{description, "An OTP app for https://github.com/LesnyRumcajs/grpc_bench"} 3 | ,{vsn, "0.1.0"} 4 | ,{modules, []} 5 | ,{registered, []} 6 | ,{env, []} 7 | ,{mod, {erlang_grpcbox_bench_app,[]}} 8 | ,{applications, [kernel 9 | ,stdlib 10 | ,sasl 11 | ,ctx 12 | ,grpcbox 13 | ]} 14 | 15 | ,{licenses, ["MIT"]} 16 | ,{links, []} 17 | ]}. 18 | -------------------------------------------------------------------------------- /erlang_grpcbox_bench/src/erlang_grpcbox_bench_app.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc erlang_grpcbox_bench public API 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | -module(erlang_grpcbox_bench_app). 6 | -behaviour(application). 7 | 8 | -export([start/2, stop/1]). 9 | 10 | start(_StartType, _StartArgs) -> 11 | erlang_grpcbox_bench_sup:start_link(). 12 | 13 | stop(_State) -> 14 | ok. 15 | 16 | %% internal functions 17 | -------------------------------------------------------------------------------- /erlang_grpcbox_bench/src/egb_handler.erl: -------------------------------------------------------------------------------- 1 | %% Copyright © 2021 Pierre Fenoll ‹pierrefenoll@gmail.com› 2 | %% -*- coding: utf-8 -*- 3 | -module(egb_handler). 4 | -behavior(helloworld_greeter_bhvr). 5 | 6 | -export([say_hello/2]). 7 | 8 | %% @doc Unary RPC 9 | -spec say_hello(ctx:ctx(), helloworld_pb:hello_request()) -> 10 | {ok, helloworld_pb:hello_reply(), ctx:ctx()} | grpcbox_stream:grpc_error_response(). 11 | 12 | say_hello(Ctx, #{request := Request}) -> 13 | Rep = #{response => Request}, 14 | {ok, Rep, Ctx}. 15 | -------------------------------------------------------------------------------- /go_grpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.23.2-bookworm 2 | 3 | WORKDIR /app 4 | COPY go_grpc_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN apt update && apt install -y protobuf-compiler 8 | RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.33.0 9 | RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0 10 | 11 | RUN protoc -I /app/proto/helloworld /app/proto/helloworld/helloworld.proto --go-grpc_out=/app/ --go_out=/app/ 12 | RUN go mod tidy && go build ./... && go install ./... 13 | 14 | ENTRYPOINT example 15 | -------------------------------------------------------------------------------- /java_aot_bench/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.github/workflows/rubocop.yml: -------------------------------------------------------------------------------- 1 | name: Rubocop 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | push: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | rubocop: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: Set up Ruby 17 | uses: ruby/setup-ruby@v1 18 | with: 19 | ruby-version: '3.0' 20 | - name: Run rubocop 21 | run: | 22 | gem install rubocop --no-document --version 1.60.1 23 | rubocop 24 | -------------------------------------------------------------------------------- /java_micronaut_bench/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /java_quarkus_bench/.gitignore: -------------------------------------------------------------------------------- 1 | #Maven 2 | target/ 3 | pom.xml.tag 4 | pom.xml.releaseBackup 5 | pom.xml.versionsBackup 6 | release.properties 7 | 8 | # Eclipse 9 | .project 10 | .classpath 11 | .settings/ 12 | bin/ 13 | 14 | # IntelliJ 15 | .idea 16 | *.ipr 17 | *.iml 18 | *.iws 19 | 20 | # NetBeans 21 | nb-configuration.xml 22 | 23 | # Visual Studio Code 24 | .vscode 25 | .factorypath 26 | 27 | # OSX 28 | .DS_Store 29 | 30 | # Vim 31 | *.swp 32 | *.swo 33 | 34 | # patch 35 | *.orig 36 | *.rej 37 | 38 | # Local environment 39 | .env 40 | -------------------------------------------------------------------------------- /crystal_grpc_bench/src/server.cr: -------------------------------------------------------------------------------- 1 | require "grpc" 2 | require "grpc/http2" 3 | 4 | require "./protobufs/helloworld_services.pb" 5 | require "./protobufs/helloworld.pb" 6 | 7 | class HelloWorldHandler < Helloworld::Greeter 8 | def say_hello(request : Helloworld::HelloRequest) : Helloworld::HelloReply 9 | Helloworld::HelloReply.new(response: request.request) 10 | end 11 | end 12 | 13 | grpc = GRPC::Server.new 14 | grpc << HelloWorldHandler.new 15 | 16 | server = HTTP2::ClearTextServer.new([grpc]) 17 | server.listen "0.0.0.0", 50051 18 | 19 | -------------------------------------------------------------------------------- /haskell_grpc_haskell_bench/cabal.project: -------------------------------------------------------------------------------- 1 | packages: 2 | . 3 | 4 | source-repository-package 5 | type: git 6 | location: https://github.com/awakesecurity/gRPC-haskell.git 7 | tag: d20c20d63c170b5eaf5725f03f7b7060352af402 8 | 9 | source-repository-package 10 | type: git 11 | location: https://github.com/awakesecurity/gRPC-haskell.git 12 | tag: d20c20d63c170b5eaf5725f03f7b7060352af402 13 | subdir: core 14 | 15 | package grpc-haskell-core 16 | extra-include-dirs: /usr/local/include 17 | extra-lib-dirs: /usr/local/lib 18 | -------------------------------------------------------------------------------- /go_vtgrpc_bench/go.mod: -------------------------------------------------------------------------------- 1 | module example 2 | 3 | go 1.22 4 | toolchain go1.24.1 5 | 6 | require ( 7 | github.com/planetscale/vtprotobuf v0.6.0 8 | go.uber.org/automaxprocs v1.5.3 9 | google.golang.org/grpc v1.63.2 10 | ) 11 | 12 | require ( 13 | golang.org/x/net v0.38.0 // indirect 14 | golang.org/x/sys v0.31.0 // indirect 15 | golang.org/x/text v0.23.0 // indirect 16 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect 17 | google.golang.org/protobuf v1.33.0 // indirect 18 | ) 19 | 20 | replace local => ./ 21 | -------------------------------------------------------------------------------- /rust_tonic_st_bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_tonic" 3 | version = "0.1.0" 4 | authors = ["LesnyRumcajs "] 5 | edition = "2021" 6 | 7 | [profile.release] 8 | opt-level = 3 9 | codegen-units = 1 10 | lto = true 11 | 12 | [dependencies] 13 | jemallocator = "0.5.0" 14 | tonic = "0.11" 15 | prost = "0.12" 16 | tokio = { version = "1.43", features = ["rt", "macros", "io-util"] } 17 | 18 | [build-dependencies] 19 | tonic-build = "0.11" 20 | 21 | [[bin]] 22 | name = "helloworld-server" 23 | path = "src/main.rs" 24 | -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example_benchmark.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a sample benchmarking script which will test the implementations with increasing number of available CPUs. 3 | 4 | bash build.sh || exit 1 5 | 6 | export GRPC_BENCHMARK_DURATION=120s 7 | export GRPC_BENCHMARK_WARMUP=30s 8 | export GRPC_SERVER_RAM=4096m 9 | export GRPC_CLIENT_CPUS=11 10 | 11 | cpus=0 12 | while [ $cpus -ne 4 ] 13 | do 14 | cpus=$(($cpus+1)) 15 | echo "Benchmarking for $cpus CPU(s)" 16 | GRPC_SERVER_CPUS=$cpus bash bench.sh || exit 2 17 | sleep 60 18 | done 19 | 20 | echo "Benchmarking finished" 21 | -------------------------------------------------------------------------------- /scala_fs2_bench/src/main/scala/com/example/helloworld/GreeterServiceImpl.scala: -------------------------------------------------------------------------------- 1 | package io.grpc.examples.helloworld 2 | 3 | import cats.effect.IO 4 | import io.grpc.examples.helloworld.helloworld.GreeterGrpc.Greeter 5 | import io.grpc.examples.helloworld.helloworld.{GreeterFs2Grpc, HelloReply, HelloRequest} 6 | 7 | import scala.concurrent.Future 8 | 9 | 10 | class GreeterServiceImpl extends GreeterFs2Grpc[IO, io.grpc.Metadata] { 11 | override def sayHello(request: HelloRequest, ctx: io.grpc.Metadata): IO[HelloReply] = 12 | IO.pure(HelloReply(request.request)) 13 | } 14 | -------------------------------------------------------------------------------- /rust_tonic_mt_bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_tonic" 3 | version = "0.1.0" 4 | authors = ["LesnyRumcajs "] 5 | edition = "2021" 6 | 7 | [profile.release] 8 | opt-level = 3 9 | codegen-units = 1 10 | lto = true 11 | 12 | [dependencies] 13 | jemallocator = "0.5.0" 14 | tonic = "0.11" 15 | prost = "0.12" 16 | tokio = { version = "1.45", features = ["parking_lot", "rt-multi-thread", "macros", "io-util"] } 17 | 18 | [build-dependencies] 19 | tonic-build = "0.11" 20 | 21 | [[bin]] 22 | name = "helloworld-server" 23 | path = "src/main.rs" 24 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/rel/env.sh.eex: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Sets and enables heart (recommended only in daemon mode) 4 | # case $RELEASE_COMMAND in 5 | # daemon*) 6 | # HEART_COMMAND="$RELEASE_ROOT/bin/$RELEASE_NAME $RELEASE_COMMAND" 7 | # export HEART_COMMAND 8 | # export ELIXIR_ERL_OPTIONS="-heart" 9 | # ;; 10 | # *) 11 | # ;; 12 | # esac 13 | 14 | # Set the release to work across nodes. 15 | # RELEASE_DISTRIBUTION must be "sname" (local), "name" (distributed) or "none". 16 | # export RELEASE_DISTRIBUTION=name 17 | # export RELEASE_NODE=<%= @release.name %> 18 | -------------------------------------------------------------------------------- /java_quarkus_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:23-jdk-noble 2 | 3 | WORKDIR /app 4 | 5 | COPY java_quarkus_bench /app 6 | COPY proto /app/src/main/proto 7 | 8 | RUN /app/mvnw clean package 9 | 10 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. 11 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" 12 | 13 | ENTRYPOINT java -Dquarkus.http.idle-timeout=0 -Dmutiny.disableCallBackDecorators=true -Dquarkus.grpc.server.instances="${GRPC_SERVER_CPUS:-1}" -jar /app/target/quarkus-app/quarkus-run.jar 14 | -------------------------------------------------------------------------------- /scala_fs2_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sbtscala/scala-sbt:eclipse-temurin-23.0.1_11_1.10.7_3.6.3 as BUILDER 2 | 3 | WORKDIR /app 4 | COPY scala_fs2_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/protobuf/helloworld.proto 6 | 7 | RUN sbt assembly 8 | 9 | FROM eclipse-temurin:23-jdk-noble 10 | 11 | ENV GC "-XX:+UseParallelGC" 12 | ENV _JAVA_OPTIONS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 13 | 14 | COPY --from=builder /app/target/scala-2.13/fs2-grpc-quickstart-scala-assembly-1.0.jar . 15 | 16 | ENTRYPOINT ["java", "-jar", "fs2-grpc-quickstart-scala-assembly-1.0.jar"] 17 | -------------------------------------------------------------------------------- /scala_zio_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sbtscala/scala-sbt:eclipse-temurin-23.0.1_11_1.10.7_3.6.3 as BUILDER 2 | 3 | WORKDIR /app 4 | COPY scala_zio_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/protobuf/helloworld.proto 6 | 7 | RUN sbt assembly 8 | 9 | FROM eclipse-temurin:23-jdk-noble 10 | 11 | ENV GC "-XX:+UseParallelGC" 12 | ENV _JAVA_OPTIONS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 13 | 14 | COPY --from=builder /app/target/scala-2.13/zio-grpc-quickstart-scala-assembly-1.0.jar . 15 | 16 | ENTRYPOINT ["java", "-jar", "zio-grpc-quickstart-scala-assembly-1.0.jar"] 17 | -------------------------------------------------------------------------------- /scala_akka_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sbtscala/scala-sbt:eclipse-temurin-23.0.1_11_1.10.7_3.6.3 as BUILDER 2 | 3 | WORKDIR /app 4 | COPY scala_akka_bench /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/protobuf/helloworld.proto 6 | 7 | RUN sbt assembly 8 | 9 | FROM eclipse-temurin:23-jdk-noble 10 | 11 | ENV GC "-XX:+UseParallelGC" 12 | ENV _JAVA_OPTIONS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 13 | 14 | COPY --from=builder /app/target/scala-2.13/akka-grpc-quickstart-scala-assembly-1.0.jar . 15 | 16 | ENTRYPOINT ["java", "-jar", "akka-grpc-quickstart-scala-assembly-1.0.jar"] 17 | -------------------------------------------------------------------------------- /scala_pekko_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sbtscala/scala-sbt:eclipse-temurin-23.0.1_11_1.10.7_3.6.3 as BUILDER 2 | 3 | WORKDIR /app 4 | COPY scala_pekko_bench/ /app 5 | COPY proto/helloworld/helloworld.proto /app/src/main/protobuf/helloworld.proto 6 | 7 | RUN sbt assembly 8 | 9 | FROM eclipse-temurin:23-jdk-noble 10 | 11 | ENV GC "-XX:+UseParallelGC" 12 | ENV _JAVA_OPTIONS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 13 | 14 | COPY --from=builder /app/target/scala-2.13/pekko-grpc-quickstart-scala-assembly-1.0.jar . 15 | 16 | ENTRYPOINT ["java", "-jar", "pekko-grpc-quickstart-scala-assembly-1.0.jar"] 17 | -------------------------------------------------------------------------------- /crystal_grpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM crystallang/crystal:1.7.2 2 | 3 | WORKDIR /app 4 | COPY crystal_grpc_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN shards install 8 | RUN apt update && apt install -y protobuf-compiler protobuf-compiler-grpc 9 | RUN mkdir -p src/protobufs && protoc -I proto \ 10 | --grpc_out=src/protobufs \ 11 | --crystal_out=src/protobufs \ 12 | --plugin=protoc-gen-grpc=bin/grpc_crystal \ 13 | --plugin=protoc-gen-crystal=bin/protoc-gen-crystal \ 14 | proto/helloworld/helloworld.proto 15 | 16 | RUN crystal build src/server.cr --release -o bin/server 17 | ENTRYPOINT bin/server 18 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Please note we have a code of conduct, please follow it in all your interactions with the project. 4 | 5 | ## Pull Request Process 6 | 7 | 1. All new benchmarks must be performed through Docker, no additional dependencies must be required. 8 | 2. Update the README.md with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations and container parameters. 9 | 3. You may merge the Pull Request in once you have the sign-off of one contributor, or if you do not have permission to do that, you may request the reviewer to merge it for you. 10 | -------------------------------------------------------------------------------- /java_openj9_grpc_gencon_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ibm-semeru-runtimes:open-23.0.1_11-jdk 2 | 3 | WORKDIR /app 4 | COPY java_hotspot_grpc_sgc_bench/ /app 5 | COPY java_openj9_grpc_gencon_bench/populate_scc.sh /app 6 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 7 | 8 | RUN /app/gradlew installDist 9 | 10 | ENV GC "-Xpolicy:gencon" 11 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 12 | 13 | RUN /app/populate_scc.sh 14 | ENV JAVA_OPTS "${JAVA_OPTS} -Xshareclasses:name=grcp,cacheDir=/app/.classCache" 15 | 16 | ENTRYPOINT [ "/app/build/install/examples/bin/hello-world-server" ] 17 | -------------------------------------------------------------------------------- /cpp_grpc_st_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcc:12.2.0 2 | 3 | RUN apt-get update && apt-get install -y protobuf-compiler protobuf-compiler-grpc libgrpc++-dev libjemalloc-dev 4 | 5 | WORKDIR /app 6 | COPY cpp_grpc_st_bench /app 7 | COPY proto /app/proto 8 | 9 | RUN mkdir gen && \ 10 | protoc --proto_path=/app/proto/helloworld --cpp_out=gen helloworld.proto && \ 11 | protoc --proto_path=/app/proto/helloworld --grpc_out=gen --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` helloworld.proto 12 | RUN g++ -O3 -flto main.cpp gen/helloworld.grpc.pb.cc gen/helloworld.pb.cc -Igen -lgrpc++ -lprotobuf -lgrpc -ljemalloc 13 | 14 | ENTRYPOINT /app/a.out 15 | -------------------------------------------------------------------------------- /detailed/java_openj9_grpc_nogc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM adoptopenjdk:14.0.2_8-jre-openj9-0.21.0-bionic 2 | 3 | WORKDIR /app 4 | COPY java_hotspot_grpc_sgc_bench /app 5 | COPY java_openj9_grpc_gencon_bench/populate_scc.sh /app 6 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 7 | 8 | RUN /app/gradlew installDist 9 | 10 | ENV GC "-Xpolicy:nogc" 11 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 12 | 13 | RUN /app/populate_scc.sh 14 | ENV JAVA_OPTS "${JAVA_OPTS} -Xshareclasses:name=grcp,cacheDir=/app/.classCache" 15 | 16 | ENTRYPOINT [ "/app/build/install/examples/bin/hello-world-server" ] 17 | -------------------------------------------------------------------------------- /erlang_grpcbox_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/library/erlang:26.0.1@sha256:c42d00aff6fae5206b47a8868698fe1edfdc8e08d3bfa35c786833e8f72ba638 as builder 2 | 3 | WORKDIR /app 4 | COPY erlang_grpcbox_bench /app 5 | COPY proto /app/proto 6 | RUN mkdir -p _build/default/lib/erlang_grpcbox_bench/ebin && rebar3 grpc gen --protos=proto/helloworld --force 7 | RUN rebar3 as prod tar 8 | RUN mkdir -p /opt/rel 9 | RUN tar -zxf _build/prod/rel/*/*.tar.gz -C /opt/rel 10 | 11 | 12 | FROM debian:bullseye AS release 13 | WORKDIR /app 14 | COPY --from=builder /opt/rel . 15 | EXPOSE 50051 16 | ENTRYPOINT ["/app/bin/erlang_grpcbox_bench"] 17 | CMD ["foreground"] 18 | -------------------------------------------------------------------------------- /detailed/java_openj9_grpc_balanced_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM adoptopenjdk:14.0.2_8-jre-openj9-0.21.0-bionic 2 | 3 | WORKDIR /app 4 | COPY java_hotspot_grpc_sgc_bench/ /app 5 | COPY java_openj9_grpc_gencon_bench/populate_scc.sh /app 6 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 7 | 8 | RUN /app/gradlew installDist 9 | 10 | ENV GC "-Xpolicy:balanced" 11 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 12 | 13 | RUN /app/populate_scc.sh 14 | ENV JAVA_OPTS "${JAVA_OPTS} -Xshareclasses:name=grcp,cacheDir=/app/.classCache" 15 | 16 | ENTRYPOINT [ "/app/build/install/examples/bin/hello-world-server" ] 17 | -------------------------------------------------------------------------------- /detailed/java_openj9_grpc_metronome_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM adoptopenjdk:14.0.2_8-jre-openj9-0.21.0-bionic 2 | 3 | WORKDIR /app 4 | COPY java_hotspot_grpc_sgc_bench /app 5 | COPY java_openj9_grpc_gencon_bench/populate_scc.sh /app 6 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 7 | 8 | RUN /app/gradlew installDist 9 | 10 | ENV GC "-Xpolicy:metronome" 11 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 12 | 13 | RUN /app/populate_scc.sh 14 | ENV JAVA_OPTS "${JAVA_OPTS} -Xshareclasses:name=grcp,cacheDir=/app/.classCache" 15 | 16 | ENTRYPOINT [ "/app/build/install/examples/bin/hello-world-server" ] 17 | -------------------------------------------------------------------------------- /detailed/java_openj9_grpc_optavgpause_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM adoptopenjdk:14.0.2_8-jre-openj9-0.21.0-bionic 2 | 3 | WORKDIR /app 4 | COPY java_hotspot_grpc_sgc_bench /app 5 | COPY java_openj9_grpc_gencon_bench/populate_scc.sh /app 6 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 7 | 8 | RUN /app/gradlew installDist 9 | 10 | ENV GC "-Xpolicy:optavgpause" 11 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 12 | 13 | RUN /app/populate_scc.sh 14 | ENV JAVA_OPTS "${JAVA_OPTS} -Xshareclasses:name=grcp,cacheDir=/app/.classCache" 15 | 16 | ENTRYPOINT [ "/app/build/install/examples/bin/hello-world-server" ] 17 | -------------------------------------------------------------------------------- /detailed/java_openj9_grpc_optthruput_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM adoptopenjdk:14.0.2_8-jre-openj9-0.21.0-bionic 2 | 3 | WORKDIR /app 4 | COPY java_hotspot_grpc_sgc_bench /app 5 | COPY java_openj9_grpc_gencon_bench/populate_scc.sh /app 6 | COPY proto/helloworld/helloworld.proto /app/src/main/proto/helloworld.proto 7 | 8 | RUN /app/gradlew installDist 9 | 10 | ENV GC "-Xpolicy:optthruput" 11 | ENV JAVA_OPTS "${GC} -XX:MinRAMPercentage=70 -XX:MaxRAMPercentage=70" 12 | 13 | RUN /app/populate_scc.sh 14 | ENV JAVA_OPTS "${JAVA_OPTS} -Xshareclasses:name=grcp,cacheDir=/app/.classCache" 15 | 16 | ENTRYPOINT [ "/app/build/install/examples/bin/hello-world-server" ] 17 | -------------------------------------------------------------------------------- /cpp_grpc_mt_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcc:12.2.0 2 | 3 | RUN apt-get update && apt-get install -y protobuf-compiler protobuf-compiler-grpc libgrpc++-dev libjemalloc-dev 4 | 5 | WORKDIR /app 6 | COPY cpp_grpc_mt_bench /app 7 | COPY proto /app/proto 8 | 9 | RUN mkdir gen && \ 10 | protoc --proto_path=/app/proto/helloworld --cpp_out=gen helloworld.proto && \ 11 | protoc --proto_path=/app/proto/helloworld --grpc_out=gen --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` helloworld.proto 12 | RUN g++ --std=c++20 -O3 -flto main.cpp gen/helloworld.grpc.pb.cc gen/helloworld.pb.cc -Igen -lgrpc++ -lprotobuf -lgrpc -lpthread -ljemalloc 13 | 14 | ENTRYPOINT /app/a.out 15 | -------------------------------------------------------------------------------- /go_connect_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.23.2-bookworm 2 | 3 | WORKDIR /app 4 | COPY go_connect_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN apt update && apt install -y protobuf-compiler 8 | RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.33.0 9 | RUN go install connectrpc.com/connect/cmd/protoc-gen-connect-go@v1.16.1 10 | 11 | RUN protoc -I /app/proto/helloworld /app/proto/helloworld/helloworld.proto --go_out=/app/ --connect-go_out=/app/ 12 | RUN sed -i 's/proto\/helloworld/local\/proto\/helloworld/g' proto/helloworld/helloworldconnect/helloworld.connect.go 13 | RUN go mod tidy && go build ./... && go install ./... 14 | 15 | ENTRYPOINT example 16 | -------------------------------------------------------------------------------- /java_quarkus_bench/src/main/java/com/example/HelloService.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.grpc.examples.helloworld.HelloReply; 4 | import io.grpc.examples.helloworld.HelloRequest; 5 | import io.grpc.examples.helloworld.MutinyGreeterGrpc; 6 | import io.quarkus.grpc.GrpcService; 7 | import io.smallrye.mutiny.Uni; 8 | 9 | @GrpcService 10 | public class HelloService extends MutinyGreeterGrpc.GreeterImplBase { 11 | 12 | @Override 13 | public Uni sayHello(HelloRequest request) { 14 | return Uni.createFrom().item( 15 | HelloReply.newBuilder().setResponse(request.getRequest()).build() 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /java_quarkus_native_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/graalvm/graalvm-ce:ol8-java17-22.3.3 as rel 2 | 3 | WORKDIR /app 4 | 5 | RUN gu install native-image 6 | 7 | COPY java_quarkus_bench /app 8 | COPY proto /app/src/main/proto 9 | 10 | RUN /app/mvnw clean package -Pnative 11 | 12 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. 13 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" 14 | 15 | ENTRYPOINT /app/target/java_quarkus_bench-1.0.0-SNAPSHOT-runner -Dquarkus.http.idle-timeout=0 -Dmutiny.disableCallBackDecorators=true -Dquarkus.grpc.server.instances="${GRPC_SERVER_CPUS:-1}" 16 | -------------------------------------------------------------------------------- /lua_grpc_st_onhold/greeter_service.lua: -------------------------------------------------------------------------------- 1 | --- Hello world greeter example server side service. 2 | -- greeter_service.lua 3 | 4 | local M = {} 5 | 6 | local grpc = require("grpc_lua.grpc_lua") 7 | grpc.import_proto_file("helloworld.proto") 8 | 9 | ------------------------------------------------------------------------------- 10 | --- Public functions. 11 | -- @section public 12 | 13 | function M.SayHello(request, replier) 14 | assert("table" == type(request)) 15 | assert("table" == type(replier)) 16 | -- replier:reply() can be called later after return. 17 | local response = { message = request.name } 18 | replier:reply(response); 19 | end -- SayHello() 20 | 21 | return M 22 | -------------------------------------------------------------------------------- /lua_grpc_st_onhold/greeter_server.lua: -------------------------------------------------------------------------------- 1 | --- Hello world greeter example server. 2 | -- greeter_server.lua 3 | 4 | -- Current work dir: grpc-lua/examples/helloworld 5 | package.path = "grpc-lua/src/lua/?.lua;" .. package.path 6 | 7 | local grpc = require("grpc_lua.grpc_lua") 8 | 9 | local function main() 10 | local svr = grpc.server() 11 | local server_address = "0.0.0.0:50051" 12 | svr:add_listening_port(server_address) 13 | -- Service implementation is a table. 14 | local service = require("greeter_service") 15 | svr:register_service("helloworld.Greeter", service) 16 | print("Server listening on " .. server_address) 17 | svr:run() 18 | end -- main() 19 | 20 | main() 21 | -------------------------------------------------------------------------------- /erlang_grpcbox_bench/config/sys.config: -------------------------------------------------------------------------------- 1 | [{sasl, [{utc_log, true} 2 | ]} 3 | 4 | ,{grpcbox, [{servers, [#{grpc_opts => #{service_protos => [helloworld_pb 5 | ] 6 | ,services => #{'helloworld.Greeter' => egb_handler 7 | } 8 | } 9 | ,transport_opts => #{ssl => false} 10 | ,listen_opts => #{port => 50051 11 | ,ip => {0,0,0,0} 12 | } 13 | }]} 14 | ]} 15 | 16 | ]. 17 | -------------------------------------------------------------------------------- /go_vtgrpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.23.2-bookworm 2 | 3 | WORKDIR /app 4 | COPY go_vtgrpc_bench /app 5 | COPY proto /app/proto 6 | 7 | ENV GOBIN /go/bin 8 | 9 | RUN apt update && apt install -y protobuf-compiler 10 | RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.33.0 11 | RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0 12 | RUN go install github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto@v0.6.0 13 | 14 | RUN protoc -I /app/proto/helloworld /app/proto/helloworld/helloworld.proto --go-grpc_out=/app/ --go_out=/app/ --go-vtproto_out=/app/ --plugin protoc-gen-go-vtproto="${GOBIN}/protoc-gen-go-vtproto" --go-vtproto_opt=features=marshal+unmarshal+size 15 | RUN go mod tidy && go build ./... && go install ./... 16 | 17 | ENTRYPOINT example 18 | -------------------------------------------------------------------------------- /haskell_grpc_haskell_bench/grpc-haskell-bench.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: 2.4 2 | name: grpc-haskell-bench 3 | version: 0.1.0.0 4 | 5 | executable haskell-grpc-haskell-bench 6 | main-is: Main.hs 7 | hs-source-dirs: app src-gen 8 | other-modules: Helloworld 9 | build-depends: 10 | , base >=4.14 && <5 11 | , bytestring 12 | , containers 13 | , deepseq 14 | , grpc-haskell 15 | , grpc-haskell-core 16 | , proto3-suite ^>=0.6 17 | , proto3-wire ^>=1.4 18 | , text 19 | , vector 20 | 21 | default-language: Haskell2010 22 | ghc-options: 23 | -O2 -Wall -Wcompat -Widentities -Wincomplete-record-updates 24 | -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints 25 | -threaded -rtsopts 26 | -------------------------------------------------------------------------------- /rust_thruster_st_bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_thruster" 3 | version = "0.1.0" 4 | authors = ["trezm "] 5 | edition = "2018" 6 | 7 | [profile.release] 8 | opt-level = 3 9 | codegen-units = 1 10 | lto = true 11 | 12 | [dependencies] 13 | async-trait = "0.1" 14 | bytes = "1.2.1" 15 | dotenv = "0.15.0" 16 | env_logger = "0.7.1" 17 | log = "0.4" 18 | hyper = "0.14.19" 19 | http = "1.3.1" 20 | http-body = "0.4.5" 21 | jemallocator = "0.5.0" 22 | prost = "0.11.0" 23 | thruster = { version = "1.3.10", features = ["hyper_server"] } 24 | thruster-grpc = "0.2.3" 25 | tokio = { version = "1.45", features = ["rt", "macros", "io-util"] } 26 | 27 | futures = "0.3.24" 28 | 29 | [build-dependencies] 30 | prost-build = "0.6" 31 | 32 | [[bin]] 33 | name = "helloworld-server" 34 | path = "src/main.rs" 35 | -------------------------------------------------------------------------------- /haskell_grpc_haskell_bench/app/Main.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | {-# LANGUAGE GADTs #-} 3 | {-# LANGUAGE OverloadedLists #-} 4 | {-# LANGUAGE OverloadedStrings #-} 5 | {-# LANGUAGE RecordWildCards #-} 6 | 7 | module Main where 8 | 9 | import Network.GRPC.HighLevel 10 | import Network.GRPC.HighLevel.Generated 11 | 12 | import Helloworld 13 | 14 | main :: IO () 15 | main = 16 | greeterServer 17 | (Greeter{ greeterSayHello = sayHello }) 18 | defaultServiceOptions{serverHost = "0.0.0.0", serverPort = 50051} 19 | 20 | sayHello 21 | :: ServerRequest 'Normal HelloRequest HelloReply 22 | -> IO (ServerResponse 'Normal HelloReply) 23 | sayHello (ServerNormalRequest _metadata HelloRequest{..}) = do 24 | return $ ServerNormalResponse (HelloReply helloRequestRequest) [] StatusOk "" 25 | -------------------------------------------------------------------------------- /rust_wtx_bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [[bin]] 2 | name = "helloworld-server" 3 | path = "src/main.rs" 4 | 5 | [dependencies] 6 | quick-protobuf = { default-features = false, version = "0.8" } 7 | tokio = { default-features = false, features = ["parking_lot", "rt-multi-thread"], version = "1.0" } 8 | wtx = { default-features = false, features = ["grpc-server", "http", "nightly", "optimization", "quick-protobuf", "tokio"], version = "0.40" } 9 | 10 | [build-dependencies] 11 | pb-rs = { default-features = false, version = "0.10" } 12 | 13 | [package] 14 | edition = "2021" 15 | name = "wtx" 16 | version = "0.0.0" 17 | 18 | [profile.release] 19 | codegen-units = 1 20 | debug = false 21 | debug-assertions = false 22 | incremental = false 23 | lto = true 24 | opt-level = 3 25 | overflow-checks = false 26 | panic = 'abort' 27 | rpath = false 28 | strip = "symbols" 29 | -------------------------------------------------------------------------------- /rust_thruster_mt_bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_thruster" 3 | version = "0.1.0" 4 | authors = ["trezm "] 5 | edition = "2018" 6 | 7 | [profile.release] 8 | opt-level = 3 9 | codegen-units = 1 10 | lto = true 11 | 12 | [dependencies] 13 | async-trait = "0.1" 14 | bytes = "1.2.1" 15 | dotenv = "0.15.0" 16 | env_logger = "0.7.1" 17 | log = "0.4" 18 | hyper = "0.14.19" 19 | http = "1.3.1" 20 | http-body = "0.4.5" 21 | jemallocator = "0.5.0" 22 | prost = "0.11.0" 23 | thruster = { version = "1.3.10", features = ["hyper_server"] } 24 | thruster-grpc = "0.2.3" 25 | tokio = { version = "1.43", features = ["parking_lot", "rt-multi-thread", "macros", "io-util"] } 26 | 27 | futures = "0.3.24" 28 | 29 | [build-dependencies] 30 | prost-build = "0.6" 31 | 32 | [[bin]] 33 | name = "helloworld-server" 34 | path = "src/main.rs" 35 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Please see the documentation for all configuration options: 2 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 3 | 4 | version: 2 5 | updates: 6 | - package-ecosystem: "cargo" 7 | directories: 8 | - "**/*" 9 | open-pull-requests-limit: 1 10 | schedule: 11 | interval: "weekly" 12 | # https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot#enabling-dependabot-version-updates-for-actions 13 | - package-ecosystem: "github-actions" 14 | directory: "/" 15 | open-pull-requests-limit: 1 16 | schedule: 17 | interval: "weekly" 18 | - package-ecosystem: "docker" 19 | directories: 20 | - "**/*" 21 | open-pull-requests-limit: 1 22 | schedule: 23 | interval: "weekly" 24 | -------------------------------------------------------------------------------- /clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export GRPC_IMAGE_NAME="${GRPC_IMAGE_NAME:-grpc_bench}" 4 | 5 | 6 | ## The list of benchmarks to clean 7 | BENCHMARKS_TO_CLEAN="${@}" 8 | 9 | IMAGES_TO_CLEAN="${BENCHMARKS_TO_CLEAN:-}" 10 | 11 | ## ...or use all the *_bench dirs by default 12 | BENCHMARKS_TO_CLEAN="${BENCHMARKS_TO_CLEAN:-$(find . -maxdepth 1 -name '*_bench' -type d | sort)}" 13 | 14 | for benchmark in ${BENCHMARKS_TO_CLEAN}; do 15 | benchmark=${benchmark##*/} 16 | 17 | for scenario in $(find scenarios/ -maxdepth 1 -type d | tail -n+2 | sort); do 18 | scenario=${scenario##scenarios/} 19 | IMAGES_TO_CLEAN="${IMAGES_TO_CLEAN} ${GRPC_IMAGE_NAME}:${benchmark}-${scenario}" 20 | done 21 | 22 | IMAGES_TO_CLEAN="${IMAGES_TO_CLEAN} $( 23 | grep -i '^FROM ' "${benchmark}"/Dockerfile | awk '{print $2}' 24 | )" 25 | done 26 | 27 | docker image remove ${IMAGES_TO_CLEAN} 28 | -------------------------------------------------------------------------------- /scala_zio_bench/build.sbt: -------------------------------------------------------------------------------- 1 | name := "zio-grpc-quickstart-scala" 2 | 3 | version := "1.0" 4 | 5 | scalaVersion := "2.13.16" 6 | 7 | run / fork := true 8 | 9 | val grpcVersion = "1.64.2" 10 | 11 | Compile / PB.targets := Seq( 12 | scalapb.gen(grpc = true) -> (Compile / sourceManaged).value, 13 | scalapb.zio_grpc.ZioCodeGenerator -> (Compile / sourceManaged).value, 14 | ) 15 | 16 | libraryDependencies ++= Seq( 17 | "com.thesamet.scalapb" %% "scalapb-runtime-grpc" % scalapb.compiler.Version.scalapbVersion, 18 | "io.grpc" % "grpc-netty" % grpcVersion 19 | ) 20 | 21 | // https://scalapb.github.io/docs/grpc/#grpc-netty-issues 22 | assembly / assemblyMergeStrategy := { 23 | case x if x.contains("io.netty.versions.properties") => MergeStrategy.discard 24 | case x => 25 | val oldStrategy = (assembly / assemblyMergeStrategy).value 26 | oldStrategy(x) 27 | } 28 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Helloworld.Mixfile do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :helloworld, 7 | version: "0.1.0", 8 | elixir: "~> 1.13", 9 | build_embedded: Mix.env() == :prod, 10 | start_permanent: Mix.env() == :prod, 11 | deps: deps(), 12 | releases: releases() 13 | ] 14 | end 15 | 16 | def application do 17 | [mod: {HelloworldApp, []}, applications: [:logger, :grpc, :protobuf]] 18 | end 19 | 20 | defp deps do 21 | [ 22 | {:grpc, "~> 0.5.0"}, 23 | {:protobuf, "~> 0.10.0"}, 24 | {:dialyxir, "~> 0.5", only: [:dev, :test], runtime: false} 25 | ] 26 | end 27 | 28 | defp releases() do 29 | [ 30 | helloworld: [ 31 | include_executables_for: [:unix], 32 | applications: [runtime_tools: :permanent] 33 | ] 34 | ] 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /go_vtconnect_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.23.2-bookworm 2 | 3 | WORKDIR /app 4 | COPY go_vtconnect_bench /app 5 | COPY proto /app/proto 6 | 7 | ENV GOBIN /go/bin 8 | 9 | RUN apt update && apt install -y protobuf-compiler 10 | RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.33.0 11 | RUN go install connectrpc.com/connect/cmd/protoc-gen-connect-go@v1.16.1 12 | RUN go install github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto@v0.6.0 13 | RUN protoc -I /app/proto/helloworld /app/proto/helloworld/helloworld.proto --go_out=/app/ --connect-go_out=/app/ --go-vtproto_out=/app/ --plugin protoc-gen-go-vtproto="${GOBIN}/protoc-gen-go-vtproto" --go-vtproto_opt=features=marshal+unmarshal+size 14 | RUN sed -i 's/proto\/helloworld/local\/proto\/helloworld/g' proto/helloworld/helloworldconnect/helloworld.connect.go 15 | RUN go mod tidy && go build ./... && go install ./... 16 | 17 | ENTRYPOINT example 18 | -------------------------------------------------------------------------------- /rust_wtx_bench/build.rs: -------------------------------------------------------------------------------- 1 | use pb_rs::{types::FileDescriptor, ConfigBuilder}; 2 | use std::{ 3 | fs::{remove_dir_all, DirBuilder}, 4 | path::Path, 5 | }; 6 | 7 | fn main() { 8 | let cmd = std::env::var("CARGO_MANIFEST_DIR").unwrap(); 9 | let in_dir = Path::new(&cmd).join("protos"); 10 | let out_dir = Path::new(&std::env::var("OUT_DIR").unwrap()).join("protos"); 11 | if out_dir.exists() { 12 | remove_dir_all(&out_dir).unwrap(); 13 | } 14 | DirBuilder::new().create(&out_dir).unwrap(); 15 | FileDescriptor::run( 16 | &ConfigBuilder::new( 17 | &[Path::new(&cmd) 18 | .join("protos/helloworld/helloworld.proto") 19 | .as_path()], 20 | None, 21 | Some(&out_dir.as_path()), 22 | &[in_dir.as_path()], 23 | ) 24 | .unwrap() 25 | .build(), 26 | ) 27 | .unwrap(); 28 | } 29 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM elixir:1.14.3 2 | 3 | WORKDIR /app 4 | COPY elixir_grpc_bench /app 5 | COPY proto /app/proto 6 | 7 | RUN apt update && apt install -y git protobuf-compiler 8 | RUN mix local.hex --force 9 | RUN mix local.rebar --force 10 | RUN mix escript.install --force hex protobuf 11 | RUN cp /root/.mix/escripts/protoc-gen-elixir /usr/bin/ 12 | 13 | RUN protoc --proto_path=/app/proto/helloworld --elixir_out=plugins=grpc:./lib/ helloworld.proto 14 | 15 | ENV MIX_ENV=prod 16 | RUN mix do clean, deps.clean --all, deps.get, compile 17 | 18 | RUN mix release.init 19 | 20 | RUN echo "+sbwt none" >> /app/rel/vm.args.eex \ 21 | && echo "+sbwtdcpu none" >> /app/rel/vm.args.eex \ 22 | && echo "+sbwtdio none" >> /app/rel/vm.args.eex \ 23 | && echo "+K true" >> /app/rel/vm.args.eex 24 | 25 | RUN mix release 26 | 27 | 28 | CMD ["/app/_build/prod/rel/helloworld/bin/helloworld", "start"] 29 | -------------------------------------------------------------------------------- /analyze.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | RESULTS_DIR=${RESULTS_DIR:-"${@}"} 3 | 4 | echo "-----" 5 | echo "Benchmark finished. Detailed results are located in: ${RESULTS_DIR}" 6 | 7 | docker run --name analyzer --rm \ 8 | -v "${PWD}/analyze:/analyze:ro" \ 9 | -v "${PWD}/${RESULTS_DIR}:/reports:ro" \ 10 | ruby:3-slim-buster ruby /analyze/results_analyze.rb reports || 11 | exit 1 12 | 13 | cat > ${RESULTS_DIR}/bench.params << EOF 14 | Benchmark Execution Parameters: 15 | $(git log -1 --pretty="%h %cD %cn %s") 16 | - GRPC_BENCHMARK_DURATION=${GRPC_BENCHMARK_DURATION} 17 | - GRPC_BENCHMARK_WARMUP=${GRPC_BENCHMARK_WARMUP} 18 | - GRPC_SERVER_CPUS=${GRPC_SERVER_CPUS} 19 | - GRPC_SERVER_RAM=${GRPC_SERVER_RAM} 20 | - GRPC_CLIENT_CONNECTIONS=${GRPC_CLIENT_CONNECTIONS} 21 | - GRPC_CLIENT_CONCURRENCY=${GRPC_CLIENT_CONCURRENCY} 22 | - GRPC_CLIENT_QPS=${GRPC_CLIENT_QPS} 23 | - GRPC_CLIENT_CPUS=${GRPC_CLIENT_CPUS} 24 | - GRPC_REQUEST_SCENARIO=${GRPC_REQUEST_SCENARIO} 25 | - GRPC_GHZ_TAG=${GRPC_GHZ_TAG} 26 | EOF 27 | -------------------------------------------------------------------------------- /scenarios/string_1kB/payload: -------------------------------------------------------------------------------- 1 | {"request":{"name":"6MVjeMfskUeonWBkGUY5SOf49xcE1sVGlDAzBMudiCjYwZDYFO0IUmI4mKoPtukX43aj76XMkY1NcQGHZSNXv06dyvsXseKvPAm78mpUFI33cHK2xpMJJm4nT098tp1BiO9IlvV45KCUFcLHrvFNQ0DysQniNoVmMIFITAJhfkIbzaRP7nKkARjqcxdyh64XRiroJ9hJ6JiJnSh9681WWbLW2mEXBbf15mRb7zX2aiRvyMV4cSSvvIbNfaSTtqNmpnQ6fyTLsTtgXbUgOWEmxa2mEewGLUSvbQzVdV7WnbNfjSp8qdMChCAmToXVOV7iXfcC4X3EWSSK3CczJtQQo8aTIsI4bALQ3epHKNqVrNER76uFcqAYcMWoBMyHz3ehzGHPhxYlgrZ3xWi0hvqiQ8lU0q1pER19Y5kTZZyu69pC9grnNSicxnXB14YHAoECqzIC2GN7d16dQCEx3pNGo81dqerCAJTsxJJwlcxVFmxfSv4iLwTs8mkXZfewk8rlRtJhbKNbddkkAsDLX8DbQeT5qkGOwG84V6DuabLeVgyJnhkKVOuCJ7Ub57xZOqL6n5hh3CvX8Ii3O023Zcoef01BzryKcfx9x5fs79yzMH825gzC4kIrYl83nUy6vcEAkNi2dNlr9NHzL7rBQWX2zlhmTQYs0h74xTPFz8VzkNbOPJvBEbedwjVljkgWo7jqSMJq2wdhWSRucD2g2klVgKjpWtVuaKnHeA5xp7nAvw2x9SAVN1x3QNO5QvKoNwBZF5XcMvHJxGDZh4XSAhtPHEmh41WEIEODYVFuZ8ZpQLJ8gpBQQJ1XUI0EfDrZAKuJj22lv7NTaSYrKsUBBcFOoPqvbKVzBAZHURUL777kuv7kDayTfEeSjTfJGO6FCnkrMFaRNLKKMUlHZwa458bfnp3PyFmNLvemgQJmF4C325PhgiwxpRrE9GX0rOsXewsnJftGt5R8j8OJ0tIO9LxCeJXqSPbt3bD5NQzmYlJg"}} 2 | -------------------------------------------------------------------------------- /java_aot_bench/src/main/java/helloworld/GreetingEndpoint.java: -------------------------------------------------------------------------------- 1 | package helloworld; 2 | 3 | // tag::imports[] 4 | import io.grpc.examples.helloworld.GreeterGrpc; 5 | import io.grpc.examples.helloworld.HelloReply; 6 | import io.grpc.examples.helloworld.HelloRequest; 7 | import io.grpc.stub.StreamObserver; 8 | import javax.inject.Singleton; 9 | // end::imports[] 10 | 11 | // tag::clazz[] 12 | @Singleton 13 | public class GreetingEndpoint extends GreeterGrpc.GreeterImplBase { // <1> 14 | 15 | private final GreetingService greetingService; 16 | 17 | // <2> 18 | public GreetingEndpoint(GreetingService greetingService) { 19 | this.greetingService = greetingService; 20 | } 21 | 22 | @Override 23 | public void sayHello(HelloRequest request, StreamObserver responseObserver) { 24 | // <3> 25 | final var reply = HelloReply.newBuilder().setResponse(request.getRequest()).build(); 26 | responseObserver.onNext(reply); 27 | responseObserver.onCompleted(); 28 | } 29 | } 30 | // end::clazz[] 31 | -------------------------------------------------------------------------------- /haskell_grpc_haskell_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/library/haskell:8.10.7 2 | 3 | RUN apt-get update && apt-get install -y \ 4 | build-essential autoconf libtool libssl-dev pkg-config cmake git 5 | 6 | ARG PARALLEL 7 | RUN BUILD_DIR=$(mktemp -d) && \ 8 | cd $BUILD_DIR && \ 9 | git clone --depth 1 --branch v1.42.0 --recurse-submodules https://github.com/grpc/grpc && \ 10 | cd grpc && \ 11 | cmake -DCMAKE_INSTALL_PREFIX=/usr \ 12 | -DgRPC_BUILD_TESTS=OFF \ 13 | -DBUILD_SHARED_LIBS=ON \ 14 | -DgRPC_INSTALL=ON \ 15 | -DCMAKE_BUILD_TYPE=Release \ 16 | -DgRPC_SSL_PROVIDER=package \ 17 | . && \ 18 | make -j ${PARALLEL:-$(nproc)} && \ 19 | make install -j${PARALLEL:-$(nproc)} && \ 20 | rm -rf $BUILD_DIR 21 | 22 | COPY haskell_grpc_haskell_bench /app/bench 23 | COPY proto /app/proto 24 | 25 | RUN cd /app/bench && cabal update && make && cabal install 26 | 27 | RUN rm -rf /app 28 | 29 | ENTRYPOINT /root/.cabal/bin/haskell-grpc-haskell-bench +RTS -N${GRPC_SERVER_CPUS:-1} 30 | -------------------------------------------------------------------------------- /java_micronaut_bench/src/main/java/helloworld/GreetingEndpoint.java: -------------------------------------------------------------------------------- 1 | package helloworld; 2 | 3 | // tag::imports[] 4 | import io.grpc.examples.helloworld.GreeterGrpc; 5 | import io.grpc.examples.helloworld.HelloReply; 6 | import io.grpc.examples.helloworld.HelloRequest; 7 | import io.grpc.stub.StreamObserver; 8 | import javax.inject.Singleton; 9 | // end::imports[] 10 | 11 | // tag::clazz[] 12 | @Singleton 13 | public class GreetingEndpoint extends GreeterGrpc.GreeterImplBase { // <1> 14 | 15 | private final GreetingService greetingService; 16 | 17 | // <2> 18 | public GreetingEndpoint(GreetingService greetingService) { 19 | this.greetingService = greetingService; 20 | } 21 | 22 | @Override 23 | public void sayHello(HelloRequest request, StreamObserver responseObserver) { 24 | // <3> 25 | HelloReply reply = HelloReply.newBuilder().setResponse(request.getRequest()).build(); 26 | responseObserver.onNext(reply); 27 | responseObserver.onCompleted(); 28 | } 29 | } 30 | // end::clazz[] 31 | -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/src/main/java/helloworld/GreetingEndpoint.java: -------------------------------------------------------------------------------- 1 | package helloworld; 2 | 3 | // tag::imports[] 4 | import io.grpc.examples.helloworld.GreeterGrpc; 5 | import io.grpc.examples.helloworld.HelloReply; 6 | import io.grpc.examples.helloworld.HelloRequest; 7 | import io.grpc.stub.StreamObserver; 8 | import javax.inject.Singleton; 9 | // end::imports[] 10 | 11 | // tag::clazz[] 12 | @Singleton 13 | public class GreetingEndpoint extends GreeterGrpc.GreeterImplBase { // <1> 14 | 15 | private final GreetingService greetingService; 16 | 17 | // <2> 18 | public GreetingEndpoint(GreetingService greetingService) { 19 | this.greetingService = greetingService; 20 | } 21 | 22 | @Override 23 | public void sayHello(HelloRequest request, StreamObserver responseObserver) { 24 | // <3> 25 | final var reply = HelloReply.newBuilder().setResponse(request.getRequest()).build(); 26 | responseObserver.onNext(reply); 27 | responseObserver.onCompleted(); 28 | } 29 | } 30 | // end::clazz[] 31 | -------------------------------------------------------------------------------- /php_grpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:8.1.10-zts-bullseye 2 | 3 | WORKDIR /app 4 | 5 | RUN apt update && apt install -y protobuf-compiler wget git 6 | RUN pecl install protobuf 7 | 8 | RUN wget https://github.com/spiral/php-grpc/releases/download/v1.6.0/protoc-gen-php-grpc-1.6.0-linux-amd64.tar.gz 9 | RUN wget https://github.com/spiral/php-grpc/releases/download/v1.6.0/rr-grpc-1.6.0-linux-amd64.tar.gz 10 | RUN tar -xvf protoc-gen-php-grpc-1.6.0-linux-amd64.tar.gz && cp protoc-gen-php-grpc-1.6.0-linux-amd64/protoc-gen-php-grpc /usr/bin/ 11 | RUN tar -xvf rr-grpc-1.6.0-linux-amd64.tar.gz && cp rr-grpc-1.6.0-linux-amd64/rr-grpc /usr/bin/ 12 | 13 | COPY proto /app/proto 14 | COPY php_grpc_bench/composer.json /app/composer.json 15 | 16 | RUN mkdir src && protoc --php_out=src --php-grpc_out=src --proto_path=/app/proto/helloworld helloworld.proto 17 | RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" 18 | RUN php composer-setup.php --quiet 19 | RUN ./composer.phar install 20 | 21 | COPY php_grpc_bench /app 22 | 23 | ENTRYPOINT [ "rr-grpc", "serve" ] 24 | -------------------------------------------------------------------------------- /dart_grpc_onhold/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM dart:2.19.4 AS build 2 | 3 | WORKDIR /app 4 | COPY dart_grpc_bench/pubspec.yaml /app/pubspec.yaml 5 | COPY proto /app/proto 6 | 7 | RUN dart pub get 8 | COPY dart_grpc_bench /app 9 | # Ensure packages are still up-to-date if anything has changed 10 | RUN dart pub get --offline 11 | RUN apt update && apt install -y protobuf-compiler 12 | RUN dart pub global activate protoc_plugin 13 | RUN mkdir -p lib/src/generated 14 | RUN protoc --plugin=protoc-gen-dart=$HOME/.pub-cache/bin/protoc-gen-dart --proto_path=/app/proto/helloworld --dart_out=grpc:lib/src/generated -Iproto /app/proto/helloworld/helloworld.proto 15 | 16 | RUN dart compile exe bin/server.dart -o bin/server 17 | 18 | # ENTRYPOINT [ "/usr/bin/dart", "/app/bin/server.dart" ] 19 | 20 | # Build minimal serving image from AOT-compiled `/server` and required system 21 | # libraries and configuration files stored in `/runtime/` from the build stage. 22 | FROM scratch 23 | COPY --from=build /runtime/ / 24 | COPY --from=build /app/bin/server /app/bin/ 25 | 26 | # Start server. 27 | EXPOSE 50051 28 | CMD ["/app/bin/server"] -------------------------------------------------------------------------------- /dotnet_grpc_bench/GreeterServer/Services/GreeterService.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 gRPC authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | using Grpc.Core; 16 | using Helloworld; 17 | 18 | namespace GreeterServer.Services; 19 | 20 | public class GreeterService : Greeter.GreeterBase 21 | { 22 | // Server side handler of the SayHello RPC 23 | public override Task SayHello(HelloRequest request, ServerCallContext context) 24 | { 25 | return Task.FromResult(new HelloReply { Response = request.Request }); 26 | } 27 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 LesnyRumcajs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /php_swoole_grpc_onhold/server.php: -------------------------------------------------------------------------------- 1 | set([ 11 | 'trace_flags' => 0, 12 | 'log_file' => '/dev/null', 13 | 'log_level' => 5, 14 | 'open_http2_protocol' => true 15 | ]); 16 | 17 | $http->on('request', function ($request, $response) { 18 | 19 | try { 20 | $request_message = new HelloRequest; 21 | 22 | $response_message = new HelloReply(); 23 | $response_message->setResponse($request_message->getRequest()); 24 | 25 | $response->header('content-type', 'application/grpc'); 26 | $response->header('trailer', 'grpc-status, grpc-message'); 27 | 28 | $response->trailer('grpc-status' , '0'); 29 | $response->trailer('grpc-message', ''); 30 | 31 | $response->end(Parser::pack($response_message->serializeToString())); 32 | } catch (Throwable $e) { 33 | $response->status(400); 34 | $response->end('Bad Request'); 35 | } 36 | }); 37 | 38 | $http->start(); 39 | -------------------------------------------------------------------------------- /scala_akka_bench/src/main/scala/com/example/helloworld/GreeterServiceImpl.scala: -------------------------------------------------------------------------------- 1 | package io.grpc.examples.helloworld 2 | 3 | //#import 4 | import scala.concurrent.Future 5 | 6 | import akka.NotUsed 7 | import akka.actor.typed.ActorSystem 8 | import akka.stream.scaladsl.BroadcastHub 9 | import akka.stream.scaladsl.Keep 10 | import akka.stream.scaladsl.MergeHub 11 | import akka.stream.scaladsl.Sink 12 | import akka.stream.scaladsl.Source 13 | 14 | //#import 15 | 16 | //#service-request-reply 17 | //#service-stream 18 | class GreeterServiceImpl(system: ActorSystem[_]) extends Greeter { 19 | private implicit val sys: ActorSystem[_] = system 20 | 21 | //#service-request-reply 22 | val (inboundHub: Sink[HelloRequest, NotUsed], outboundHub: Source[HelloReply, NotUsed]) = 23 | MergeHub.source[HelloRequest] 24 | .map(request => HelloReply(request.request)) 25 | .toMat(BroadcastHub.sink[HelloReply])(Keep.both) 26 | .run() 27 | //#service-request-reply 28 | 29 | override def sayHello(request: HelloRequest): Future[HelloReply] = { 30 | Future.successful(HelloReply(request.request)) 31 | } 32 | } 33 | //#service-stream 34 | //#service-request-reply 35 | -------------------------------------------------------------------------------- /go_connect_bench/example/main.go: -------------------------------------------------------------------------------- 1 | // Package main implements a server for Greeter service. 2 | package main 3 | 4 | import ( 5 | "context" 6 | helloworld "local/proto/helloworld" 7 | helloworldconnect "local/proto/helloworld/helloworldconnect" 8 | "log" 9 | "net/http" 10 | 11 | "connectrpc.com/connect" 12 | _ "go.uber.org/automaxprocs" 13 | "golang.org/x/net/http2" 14 | "golang.org/x/net/http2/h2c" 15 | ) 16 | 17 | const ( 18 | port = ":50051" 19 | ) 20 | 21 | // server is used to implement helloworld.GreeterServer. 22 | type server struct { 23 | helloworldconnect.UnimplementedGreeterHandler 24 | } 25 | 26 | // SayHello implements helloworld.GreeterServer 27 | func (s *server) SayHello(ctx context.Context, in *connect.Request[helloworld.HelloRequest]) (*connect.Response[helloworld.HelloReply], error) { 28 | return connect.NewResponse(&helloworld.HelloReply{Response: in.Msg.GetRequest()}), nil 29 | } 30 | 31 | func main() { 32 | mux := http.NewServeMux() 33 | mux.Handle(helloworldconnect.NewGreeterHandler(&server{})) 34 | err := http.ListenAndServe( 35 | port, 36 | h2c.NewHandler(mux, &http2.Server{}), 37 | ) 38 | log.Fatalf("listen failed: %v", err) 39 | } 40 | -------------------------------------------------------------------------------- /.github/workflows/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve gRPC bench! 4 | title: '' 5 | labels: 'Bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | 12 | 13 | 14 | 15 | **To Reproduce** 16 | Steps to reproduce the behavior: 17 | 1. Go to '...' 18 | 2. Run '....' 19 | 3. See error 20 | 21 | 22 | 23 | **Log output** 24 | 25 |
26 | Log Output 27 | 28 | ```Paste log output here 29 | paste log output... 30 | ``` 31 |
32 | 33 | 34 | 35 | **Expected behaviour** 36 | 37 | 38 | 39 | 40 | **Screenshots** 41 | 42 | 43 | 44 | 45 | **Environment (please complete the following information):** 46 | - OS: 47 | - Rust version(e.g. `rustc --version`) 48 | - Branch/commit 49 | 50 | 51 | 52 | **Other information and links** 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /rust_wtx_bench/src/main.rs: -------------------------------------------------------------------------------- 1 | pub mod grpc_bindings; 2 | 3 | use wtx::{ 4 | de::format::QuickProtobuf, 5 | grpc::{GrpcManager, GrpcMiddleware}, 6 | http::{ 7 | server_framework::{post, Router, ServerFrameworkBuilder, State}, 8 | ReqResBuffer, StatusCode, 9 | }, 10 | rng::{simple_seed, Xorshift64}, 11 | }; 12 | 13 | fn main() -> wtx::Result<()> { 14 | tokio::runtime::Builder::new_multi_thread() 15 | .worker_threads(std::env::var("GRPC_SERVER_CPUS")?.parse()?) 16 | .enable_all() 17 | .build()? 18 | .block_on(async move { 19 | let router = Router::new( 20 | wtx::paths!(("/helloworld.Greeter/SayHello", post(say_hello))), 21 | GrpcMiddleware, 22 | )?; 23 | ServerFrameworkBuilder::new(Xorshift64::from(simple_seed()), router) 24 | .with_stream_aux(|_| Ok(QuickProtobuf)) 25 | .tokio("0.0.0.0:50051", |_| {}, |_| Ok(()), |_| {}) 26 | .await 27 | }) 28 | } 29 | 30 | async fn say_hello( 31 | _: State<'_, (), GrpcManager, ReqResBuffer>, 32 | ) -> wtx::Result { 33 | Ok(StatusCode::Ok) 34 | } 35 | -------------------------------------------------------------------------------- /rust_pajamax_bench/README.md: -------------------------------------------------------------------------------- 1 | Pajamax is different from most other frameworks which are asynchronous. 2 | Pajamax uses synchronous thread model (which is one of the reasons for 3 | its high performance), and it creates a thread for each incoming connection. 4 | That is to say, at the benchmark, the number of CPUs that pajamax 5 | can utilize depends on the number of concurrent connections, 6 | the `GRPC_CLIENT_CONNECTIONS`. 7 | 8 | Therefore, when run the benchmark, notice `GRPC_CLIENT_CONNECTIONS` and 9 | `GRPC_SERVER_CPUS` configrations: 10 | 11 | 1. If `GRPC_CLIENT_CONNECTIONS < GRPC_SERVER_CPUS`, Pajamax can 12 | not fully utilize CPUs; 13 | 14 | 2. If `GRPC_CLIENT_CONNECTIONS >> GRPC_SERVER_CPUS`, each CPU will 15 | have multiple threads, and switching between threads may affect 16 | performance; 17 | 18 | 3. However if `GRPC_CLIENT_CONNECTIONS = GRPC_SERVER_CPUS`, since 19 | Pajamax is much faster than the benchmark client `ghz`, the Pajamax 20 | still can not fully utilize CPUs. 21 | 22 | 4. So setting `GRPC_CLIENT_CONNECTIONS` slightly several times larger 23 | than `GRPC_SERVER_CPUS` may be the best. 24 | 25 | See Pajamax's [documentation](https://docs.rs/pajamax) for details. 26 | -------------------------------------------------------------------------------- /swift_grpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM swift:6.0.3 AS builder 2 | 3 | WORKDIR /app 4 | 5 | # Getting protoc-gen-swift and protoc-gen-grpc-swift 6 | RUN apt update && apt install -y protobuf-compiler git make 7 | RUN git clone --depth 1 --single-branch --branch 1.21.0 https://github.com/grpc/grpc-swift 8 | WORKDIR /app/grpc-swift 9 | RUN make plugins 10 | RUN cp /app/grpc-swift/protoc-* /usr/local/bin 11 | 12 | COPY swift_grpc_bench /app 13 | COPY proto /app/proto 14 | 15 | WORKDIR /app 16 | RUN protoc --proto_path=/app/proto/helloworld --plugin=/usr/local/bin/protoc-gen-swift --swift_opt=Visibility=Public --swift_out=/app/Sources/Model helloworld.proto 17 | RUN protoc --proto_path=/app/proto/helloworld --plugin=/usr/local/bin/protoc-gen-grpc-swift --grpc-swift_opt=Visibility=Public --grpc-swift_out=/app/Sources/Model helloworld.proto 18 | 19 | # Resolve package dependencies early and store them in the build cache, 20 | # for faster subsequent builds. 21 | RUN swift package resolve 22 | RUN swift build -c release -Xswiftc -enforce-exclusivity=unchecked 23 | 24 | FROM swift:6.0.3 25 | WORKDIR /app 26 | RUN mkdir /app/.build 27 | COPY --from=builder /app/.build /app/.build 28 | ENTRYPOINT [ "/app/.build/release/Server" ] 29 | -------------------------------------------------------------------------------- /dotnet_grpc_bench/Greeter.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 16 3 | VisualStudioVersion = 16.0.30323.103 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GreeterServer", "GreeterServer\GreeterServer.csproj", "{DDBFF994-E076-43AD-B18D-049DFC1B670C}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Any CPU = Debug|Any CPU 10 | Release|Any CPU = Release|Any CPU 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {DDBFF994-E076-43AD-B18D-049DFC1B670C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 14 | {DDBFF994-E076-43AD-B18D-049DFC1B670C}.Debug|Any CPU.Build.0 = Debug|Any CPU 15 | {DDBFF994-E076-43AD-B18D-049DFC1B670C}.Release|Any CPU.ActiveCfg = Release|Any CPU 16 | {DDBFF994-E076-43AD-B18D-049DFC1B670C}.Release|Any CPU.Build.0 = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(SolutionProperties) = preSolution 19 | HideSolutionNode = FALSE 20 | EndGlobalSection 21 | GlobalSection(ExtensibilityGlobals) = postSolution 22 | SolutionGuid = {A6C36D19-FC35-4A83-A1BD-F8429CEF3E86} 23 | EndGlobalSection 24 | EndGlobal 25 | -------------------------------------------------------------------------------- /go_vtconnect_bench/example/main.go: -------------------------------------------------------------------------------- 1 | // Package main implements a server for Greeter service. 2 | package main 3 | 4 | import ( 5 | "context" 6 | helloworld "local/proto/helloworld" 7 | helloworldconnect "local/proto/helloworld/helloworldconnect" 8 | "log" 9 | "net/http" 10 | 11 | "connectrpc.com/connect" 12 | "go.akshayshah.org/connectproto" 13 | _ "go.uber.org/automaxprocs" 14 | "golang.org/x/net/http2" 15 | "golang.org/x/net/http2/h2c" 16 | ) 17 | 18 | const ( 19 | port = ":50051" 20 | ) 21 | 22 | // server is used to implement helloworld.GreeterServer. 23 | type server struct { 24 | helloworldconnect.UnimplementedGreeterHandler 25 | } 26 | 27 | // SayHello implements helloworld.GreeterServer 28 | func (s *server) SayHello(ctx context.Context, in *connect.Request[helloworld.HelloRequest]) (*connect.Response[helloworld.HelloReply], error) { 29 | return connect.NewResponse(&helloworld.HelloReply{Response: in.Msg.GetRequest()}), nil 30 | } 31 | 32 | func main() { 33 | mux := http.NewServeMux() 34 | mux.Handle(helloworldconnect.NewGreeterHandler(&server{}, connectproto.WithBinaryVT())) 35 | err := http.ListenAndServe( 36 | port, 37 | h2c.NewHandler(mux, &http2.Server{}), 38 | ) 39 | log.Fatalf("listen failed: %v", err) 40 | } 41 | -------------------------------------------------------------------------------- /scala_pekko_bench/src/main/scala/com/example/helloworld/GreeterServiceImpl.scala: -------------------------------------------------------------------------------- 1 | package io.grpc.examples.helloworld 2 | 3 | //#import 4 | import scala.concurrent.Future 5 | 6 | import org.apache.pekko.NotUsed 7 | import org.apache.pekko.actor.typed.ActorSystem 8 | import org.apache.pekko.stream.scaladsl.BroadcastHub 9 | import org.apache.pekko.stream.scaladsl.Keep 10 | import org.apache.pekko.stream.scaladsl.MergeHub 11 | import org.apache.pekko.stream.scaladsl.Sink 12 | import org.apache.pekko.stream.scaladsl.Source 13 | 14 | //#import 15 | 16 | //#service-request-reply 17 | //#service-stream 18 | class GreeterServiceImpl(system: ActorSystem[_]) extends Greeter { 19 | private implicit val sys: ActorSystem[_] = system 20 | 21 | //#service-request-reply 22 | val (inboundHub: Sink[HelloRequest, NotUsed], outboundHub: Source[HelloReply, NotUsed]) = 23 | MergeHub.source[HelloRequest] 24 | .map(request => HelloReply(request.request)) 25 | .toMat(BroadcastHub.sink[HelloReply])(Keep.both) 26 | .run() 27 | //#service-request-reply 28 | 29 | override def sayHello(request: HelloRequest): Future[HelloReply] = { 30 | Future.successful(HelloReply(request.request)) 31 | } 32 | } 33 | //#service-stream 34 | //#service-request-reply 35 | -------------------------------------------------------------------------------- /cpp_asio_grpc_bench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | project( 4 | cpp_asio_grpc_bench 5 | DESCRIPTION "Benchmark for asio-grpc" 6 | HOMEPAGE_URL https://github.com/Tradias/asio-grpc 7 | LANGUAGES CXX) 8 | 9 | include(FindPkgConfig) 10 | 11 | pkg_check_modules(grpc++_unsecure REQUIRED IMPORTED_TARGET grpc++_unsecure) 12 | pkg_check_modules(protobuf REQUIRED IMPORTED_TARGET protobuf) 13 | find_package(Boost REQUIRED COMPONENTS coroutine) 14 | 15 | add_executable(${PROJECT_NAME}) 16 | 17 | target_sources( 18 | ${PROJECT_NAME} 19 | PRIVATE main.cpp "${CMAKE_CURRENT_LIST_DIR}/gen/helloworld.pb.cc" 20 | "${CMAKE_CURRENT_LIST_DIR}/gen/helloworld.grpc.pb.cc") 21 | 22 | target_link_libraries( 23 | ${PROJECT_NAME} PRIVATE PkgConfig::grpc++_unsecure PkgConfig::protobuf 24 | Boost::headers Boost::coroutine) 25 | 26 | target_include_directories(${PROJECT_NAME} 27 | PRIVATE "${CMAKE_CURRENT_LIST_DIR}/gen") 28 | 29 | target_compile_options(${PROJECT_NAME} PRIVATE -flto) 30 | 31 | target_compile_definitions(${PROJECT_NAME} PRIVATE BOOST_ASIO_NO_DEPRECATED) 32 | 33 | target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17) 34 | 35 | install(TARGETS ${PROJECT_NAME}) 36 | -------------------------------------------------------------------------------- /rust_tonic_st_bench/src/main.rs: -------------------------------------------------------------------------------- 1 | use tonic::{transport::Server, Request, Response, Status}; 2 | 3 | use hello_world::greeter_server::{Greeter, GreeterServer}; 4 | use hello_world::{HelloReply, HelloRequest}; 5 | 6 | #[global_allocator] 7 | static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; 8 | 9 | pub mod hello_world { 10 | tonic::include_proto!("helloworld"); 11 | } 12 | 13 | #[derive(Default)] 14 | pub struct MyGreeter {} 15 | 16 | #[tonic::async_trait] 17 | impl Greeter for MyGreeter { 18 | async fn say_hello( 19 | &self, 20 | request: Request, 21 | ) -> Result, Status> { 22 | let reply = hello_world::HelloReply { 23 | response: request.into_inner().request, 24 | }; 25 | Ok(Response::new(reply)) 26 | } 27 | } 28 | 29 | #[tokio::main(flavor = "current_thread")] 30 | async fn main() -> Result<(), Box> { 31 | let addr = "0.0.0.0:50051".parse().unwrap(); 32 | let greeter = MyGreeter::default(); 33 | 34 | println!("GreeterServer listening on {}", addr); 35 | 36 | Server::builder() 37 | .add_service(GreeterServer::new(greeter)) 38 | .serve(addr) 39 | .await?; 40 | 41 | Ok(()) 42 | } 43 | -------------------------------------------------------------------------------- /swift_grpc_bench/Sources/Server/GreeterProvider.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, gRPC Authors All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import GRPC 17 | import HelloWorldModel 18 | import NIO 19 | 20 | class GreeterProvider: Helloworld_GreeterProvider { 21 | var interceptors: Helloworld_GreeterServerInterceptorFactoryProtocol? { nil } 22 | 23 | func sayHello( 24 | request: Helloworld_HelloRequest, 25 | context: StatusOnlyCallContext 26 | ) -> EventLoopFuture { 27 | let response = Helloworld_HelloReply.with { 28 | $0.response = request.request 29 | } 30 | return context.eventLoop.makeSucceededFuture(response) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/issue_bench.yml: -------------------------------------------------------------------------------- 1 | name: Run benchmarks 2 | 3 | on: 4 | issues: 5 | types: [opened] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | if: startsWith(github.event.issue.title, 'RUN BENCHMARK') 11 | steps: 12 | - name: Accept the task 13 | uses: peter-evans/create-or-update-comment@v4 14 | with: 15 | issue-number: ${{ github.event.issue.number }} 16 | body: | 17 | Serving the benchmark. I will update the issue when it's finished. 18 | - uses: actions/checkout@v4 19 | - name: Build images 20 | run: ./build.sh 21 | - name: Run tests 22 | id: run_bench 23 | run: | 24 | ./bench.sh | tee bench.results 25 | REPORT="$(cat bench.results)" 26 | REPORT="${REPORT//'%'/'%25'}" 27 | REPORT="${REPORT//$'\n'/'%0A'}" 28 | REPORT="${REPORT//$'\r'/'%0D'}" 29 | echo "::set-output name=results::$REPORT" 30 | env: 31 | GRPC_BENCHMARK_DURATION: ${{github.event.issue.body}} 32 | - name: Close Issue 33 | uses: peter-evans/close-issue@v3 34 | with: 35 | comment: | 36 | Here you go! 37 | ``` 38 | ${{ steps.run_bench.outputs.results }} 39 | ``` 40 | 41 | -------------------------------------------------------------------------------- /erlang_grpcbox_bench/src/erlang_grpcbox_bench_sup.erl: -------------------------------------------------------------------------------- 1 | %%%------------------------------------------------------------------- 2 | %% @doc erlang_grpcbox_bench top level supervisor. 3 | %% @end 4 | %%%------------------------------------------------------------------- 5 | -module(erlang_grpcbox_bench_sup). 6 | -behaviour(supervisor). 7 | 8 | -export([start_link/0]). 9 | -export([init/1]). 10 | 11 | -define(SERVER, ?MODULE). 12 | 13 | start_link() -> 14 | supervisor:start_link({local, ?SERVER}, ?MODULE, []). 15 | 16 | %% sup_flags() = #{strategy => strategy(), % optional 17 | %% intensity => non_neg_integer(), % optional 18 | %% period => pos_integer()} % optional 19 | %% child_spec() = #{id => child_id(), % mandatory 20 | %% start => mfargs(), % mandatory 21 | %% restart => restart(), % optional 22 | %% shutdown => shutdown(), % optional 23 | %% type => worker(), % optional 24 | %% modules => modules()} % optional 25 | init([]) -> 26 | SupFlags = #{strategy => one_for_all, 27 | intensity => 0, 28 | period => 1}, 29 | ChildSpecs = [], 30 | {ok, {SupFlags, ChildSpecs}}. 31 | 32 | %% internal functions 33 | -------------------------------------------------------------------------------- /erlang_grpcbox_bench/rebar.lock: -------------------------------------------------------------------------------- 1 | {"1.2.0", 2 | [{<<"acceptor_pool">>,{pkg,<<"acceptor_pool">>,<<"1.0.0">>},1}, 3 | {<<"chatterbox">>, 4 | {git,"https://github.com/tsloughter/chatterbox.git", 5 | {ref,"73d5bf2355bfb520440cfb4458030ecec09f36e6"}}, 6 | 0}, 7 | {<<"ctx">>,{pkg,<<"ctx">>,<<"0.6.0">>},1}, 8 | {<<"gproc">>,{pkg,<<"gproc">>,<<"0.9.1">>},1}, 9 | {<<"grpcbox">>, 10 | {git,"https://github.com/tsloughter/grpcbox.git", 11 | {ref,"da0ab5864bc403cc66765a8751d811f379cf1e92"}}, 12 | 0}, 13 | {<<"hpack">>,{pkg,<<"hpack_erl">>,<<"0.3.0">>},1}]}. 14 | [ 15 | {pkg_hash,[ 16 | {<<"acceptor_pool">>, <<"43C20D2ACAE35F0C2BCD64F9D2BDE267E459F0F3FD23DAB26485BF518C281B21">>}, 17 | {<<"ctx">>, <<"8FF88B70E6400C4DF90142E7F130625B82086077A45364A78D208ED3ED53C7FE">>}, 18 | {<<"gproc">>, <<"F1DF0364423539CF0B80E8201C8B1839E229E5F9B3CCB944C5834626998F5B8C">>}, 19 | {<<"hpack">>, <<"2461899CC4AB6A0EF8E970C1661C5FC6A52D3C25580BC6DD204F84CE94669926">>}]}, 20 | {pkg_hash_ext,[ 21 | {<<"acceptor_pool">>, <<"0CBCD83FDC8B9AD2EEE2067EF8B91A14858A5883CB7CD800E6FCD5803E158788">>}, 22 | {<<"ctx">>, <<"A14ED2D1B67723DBEBBE423B28D7615EB0BDCBA6FF28F2D1F1B0A7E1D4AA5FC2">>}, 23 | {<<"gproc">>, <<"905088E32E72127ED9466F0BAC0D8E65704CA5E73EE5A62CB073C3117916D507">>}, 24 | {<<"hpack">>, <<"D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0">>}]} 25 | ]. 26 | -------------------------------------------------------------------------------- /java_vertx_grpc_bench/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'application' 3 | id "com.google.protobuf" version "0.8.19" 4 | id "com.github.johnrengelman.shadow" version "7.1.2" 5 | } 6 | 7 | repositories { 8 | mavenCentral() 9 | } 10 | 11 | def grpcVersion = '1.58.0' // CURRENT_GRPC_VERSION 12 | def protobufVersion = '3.21.6' 13 | def protocVersion = protobufVersion 14 | 15 | dependencies { 16 | implementation 'io.vertx:vertx-grpc-server:4.4.4' 17 | implementation "io.grpc:grpc-protobuf:${grpcVersion}" 18 | implementation "io.grpc:grpc-stub:${grpcVersion}" 19 | implementation "com.google.protobuf:protobuf-java-util:${protobufVersion}" 20 | compileOnly "org.apache.tomcat:annotations-api:6.0.53" 21 | runtimeOnly "io.grpc:grpc-netty-shaded:${grpcVersion}" 22 | } 23 | 24 | protobuf { 25 | protoc { artifact = "com.google.protobuf:protoc:${protocVersion}" } 26 | plugins { 27 | grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" } 28 | } 29 | generateProtoTasks { 30 | all()*.plugins { grpc {} } 31 | } 32 | } 33 | 34 | sourceSets { 35 | main { 36 | java { 37 | srcDirs 'build/generated/source/proto/main/grpc' 38 | srcDirs 'build/generated/source/proto/main/java' 39 | } 40 | } 41 | } 42 | 43 | application { 44 | mainClass = 'vertx.Main' 45 | } 46 | -------------------------------------------------------------------------------- /python_grpc_bench/server.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 gRPC authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | """The Python implementation of the GRPC helloworld.Greeter server.""" 15 | 16 | from concurrent import futures 17 | 18 | import grpc 19 | 20 | import helloworld_pb2 21 | import helloworld_pb2_grpc 22 | 23 | 24 | class Greeter(helloworld_pb2_grpc.GreeterServicer): 25 | 26 | def SayHello(self, request, context): 27 | return helloworld_pb2.HelloReply(response=request.request) 28 | 29 | 30 | def serve(): 31 | server = grpc.server(futures.ThreadPoolExecutor(max_workers=1)) 32 | helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) 33 | server.add_insecure_port('[::]:50051') 34 | server.start() 35 | server.wait_for_termination() 36 | 37 | 38 | if __name__ == '__main__': 39 | serve() 40 | -------------------------------------------------------------------------------- /lua_grpc_st_onhold/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9-rc 2 | 3 | WORKDIR /app 4 | RUN pip install conan 5 | RUN apt update && apt install -y cmake 6 | 7 | COPY lua_grpc_st_bench/conanfile.txt /app/conanfile.txt 8 | COPY proto/helloworld/helloworld.proto /app/helloworld.proto 9 | 10 | RUN conan remote add remote_bintray_conan-community https://api.bintray.com/conan/conan-community/conan 11 | RUN conan remote add remote_bintray_bincrafters https://api.bintray.com/conan/bincrafters/public-conan 12 | RUN conan remote add remote_bintray_inexorgame https://api.bintray.com/conan/inexorgame/inexor-conan 13 | RUN conan remote add remote_bintray_conan https://api.bintray.com/conan/conan/conan-transit 14 | RUN conan remote add remote_bintray_jinq0123 https://api.bintray.com/conan/jinq0123/test 15 | 16 | RUN conan install lua-cpp/5.3.4@jinq0123/testing --build=missing 17 | RUN conan install luapbintf/0.1@jinq0123/testing --build=missing 18 | RUN conan install grpc-lua/0.1@jinq0123/testing --build=missing 19 | 20 | COPY lua_grpc_st_bench /app 21 | 22 | RUN cp $(find / -name 'lua-cpp' -executable -type f | head -n 1) . 23 | RUN cp $(find / -name 'libluapbintf.so' -type f | head -n 1) /app/luapbintf.so 24 | RUN cp $(find / -name 'libgrpc_lua.so' -type f | head -n 1) /app/grpc_lua.so 25 | RUN cp $(find / -name 'liblua-cpp.so' -type f | head -n 1) . 26 | 27 | RUN git clone https://github.com/jinq0123/grpc-lua.git 28 | 29 | ENTRYPOINT [ "/app/lua-cpp", "greeter_server.lua" ] 30 | -------------------------------------------------------------------------------- /swift_grpc_bench/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.2 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "Server", 8 | products: [ 9 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 10 | .executable( 11 | name: "Server", 12 | targets: ["Server"]), 13 | // Model for the HelloWorld example 14 | ], 15 | dependencies: [ 16 | // Dependencies declare other packages that this package depends on. 17 | // .package(url: /* package url */, from: "1.0.0"), 18 | .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.24.2") 19 | ], 20 | targets: [ 21 | .target( 22 | name: "HelloWorldModel", 23 | dependencies: [ 24 | .product(name: "GRPC", package: "grpc-swift"), 25 | ], 26 | path: "Sources/Model" 27 | ), 28 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 29 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 30 | .target( 31 | name: "Server", 32 | dependencies: [.product(name: "GRPC", package: "grpc-swift"), "HelloWorldModel"]), 33 | ] 34 | ) 35 | -------------------------------------------------------------------------------- /rust_pajamax_bench/src/helloworld.rs: -------------------------------------------------------------------------------- 1 | // The usage of pajamax is very simplar to tonic. 2 | // You may compare this to tonic's [hellowold server] 3 | // (https://github.com/hyperium/tonic/blob/master/examples/src/helloworld/server.rs) 4 | // example. 5 | 6 | use pajamax::status::Status; 7 | 8 | use helloworld::{Greeter, GreeterServer}; 9 | use helloworld::{HelloReply, HelloRequest}; 10 | 11 | // import the generated code from .proto 12 | mod helloworld { 13 | pajamax::include_proto!("helloworld"); 14 | } 15 | 16 | // define your business context 17 | #[derive(Clone)] 18 | struct MyGreeter(); 19 | 20 | // `Greeter` trait defines all methods in gRPC server 21 | impl Greeter for MyGreeter { 22 | // there are 3 difference compared to tonic's method handler: 23 | // - `fn` but not `async fn` 24 | // - `HelloRequest` but not `Request` 25 | // - `HelloReply` but not `Response` 26 | fn say_hello(&mut self, req: HelloRequest) -> Result { 27 | let reply = HelloReply { 28 | response: req.request, 29 | }; 30 | Ok(reply) 31 | } 32 | } 33 | 34 | fn main() { 35 | let addr = "0.0.0.0:50051"; 36 | let greeter = MyGreeter(); 37 | 38 | println!("GreeterServer listening on {}", addr); 39 | 40 | // start the server 41 | // By now we have not support configurations and multiple service, 42 | // so this API is simpler than tonic's. 43 | pajamax::serve_local(GreeterServer::new(greeter), addr).unwrap(); 44 | } 45 | -------------------------------------------------------------------------------- /java_openj9_grpc_gencon_bench/populate_scc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ "$VERBOSE" != "true" ]; then 3 | exec &>/dev/null 4 | fi 5 | 6 | set -Eeox pipefail 7 | 8 | SCC_SIZE="64m" # Default size of the SCC layer. 9 | ITERATIONS=2 # Number of iterations to run to populate it. 10 | 11 | SCC="-Xshareclasses:name=grcp,cacheDir=/app/.classCache" 12 | 13 | OPENJ9_JAVA_OPTIONS="${JAVA_OPTS[@]} $SCC" 14 | CREATE_LAYER="$OPENJ9_JAVA_OPTIONS,createLayer,groupAccess" 15 | DESTROY_LAYER="$OPENJ9_JAVA_OPTIONS,destroy" 16 | PRINT_LAYER_STATS="$OPENJ9_JAVA_OPTIONS,printTopLayerStats" 17 | 18 | OLD_UMASK=`umask` 19 | umask 002 # 002 is required to provide group rw permission to the cache when `-Xshareclasses:groupAccess` options is used 20 | 21 | # Explicity create a class cache layer for this image layer here rather than allowing 22 | # `server start` to do it, which will lead to problems because multiple JVMs will be started. 23 | java $CREATE_LAYER -Xscmx$SCC_SIZE -version 24 | 25 | # Populate the newly created class cache layer. 26 | set +e 27 | for ((i=0; i<$ITERATIONS; i++)) 28 | do 29 | /app/build/install/examples/bin/hello-world-server & 30 | # this would be much beneficial 31 | #/app/build/install/examples/bin/hello-world-client & 32 | pkill java 33 | done 34 | set -e 35 | 36 | # restore umask 37 | umask ${OLD_UMASK} 38 | 39 | # Tell the user how full the final layer is. 40 | FULL=`( java $PRINT_LAYER_STATS || true ) 2>&1 | awk '/^Cache is [0-9.]*% .*full/ {print substr($3, 1, length($3)-1)}'` 41 | echo "SCC layer is $FULL% full." 42 | -------------------------------------------------------------------------------- /python_async_grpc_bench/server.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 gRPC authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | """The Python AsyncIO implementation of the GRPC helloworld.Greeter server.""" 15 | 16 | import asyncio 17 | 18 | import grpc 19 | import helloworld_pb2 20 | import helloworld_pb2_grpc 21 | 22 | 23 | class Greeter(helloworld_pb2_grpc.GreeterServicer): 24 | 25 | async def SayHello( 26 | self, request: helloworld_pb2.HelloRequest, 27 | context: grpc.aio.ServicerContext) -> helloworld_pb2.HelloReply: 28 | return helloworld_pb2.HelloReply(response=request.request) 29 | 30 | 31 | async def serve() -> None: 32 | server = grpc.aio.server() 33 | helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) 34 | listen_addr = '[::]:50051' 35 | server.add_insecure_port(listen_addr) 36 | await server.start() 37 | await server.wait_for_termination() 38 | 39 | 40 | if __name__ == '__main__': 41 | asyncio.run(serve()) 42 | -------------------------------------------------------------------------------- /scenarios/string_100B/helloworld.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 gRPC authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | option go_package = "proto/helloworld"; 18 | option java_multiple_files = true; 19 | option java_package = "io.grpc.examples.helloworld"; 20 | option java_outer_classname = "HelloWorldProto"; 21 | option objc_class_prefix = "HLW"; 22 | 23 | package helloworld; 24 | 25 | // The greeting service definition. 26 | service Greeter { 27 | // Sends a greeting 28 | rpc SayHello (HelloRequest) returns (HelloReply) {} 29 | } 30 | 31 | // The actual message exchanged by the client and the server. 32 | // NOTE: When creating a custom scenario plese edit only this message. 33 | message Hello { 34 | string name = 1; 35 | } 36 | 37 | // The request message from the client. 38 | message HelloRequest { 39 | Hello request = 1; 40 | } 41 | 42 | // The response message from the server. 43 | message HelloReply { 44 | Hello response = 1; 45 | } 46 | -------------------------------------------------------------------------------- /scenarios/string_10B/helloworld.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 gRPC authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | option go_package = "proto/helloworld"; 18 | option java_multiple_files = true; 19 | option java_package = "io.grpc.examples.helloworld"; 20 | option java_outer_classname = "HelloWorldProto"; 21 | option objc_class_prefix = "HLW"; 22 | 23 | package helloworld; 24 | 25 | // The greeting service definition. 26 | service Greeter { 27 | // Sends a greeting 28 | rpc SayHello (HelloRequest) returns (HelloReply) {} 29 | } 30 | 31 | // The actual message exchanged by the client and the server. 32 | // NOTE: When creating a custom scenario plese edit only this message. 33 | message Hello { 34 | string name = 1; 35 | } 36 | 37 | // The request message from the client. 38 | message HelloRequest { 39 | Hello request = 1; 40 | } 41 | 42 | // The response message from the server. 43 | message HelloReply { 44 | Hello response = 1; 45 | } 46 | -------------------------------------------------------------------------------- /scenarios/string_10kB/helloworld.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 gRPC authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | option go_package = "proto/helloworld"; 18 | option java_multiple_files = true; 19 | option java_package = "io.grpc.examples.helloworld"; 20 | option java_outer_classname = "HelloWorldProto"; 21 | option objc_class_prefix = "HLW"; 22 | 23 | package helloworld; 24 | 25 | // The greeting service definition. 26 | service Greeter { 27 | // Sends a greeting 28 | rpc SayHello (HelloRequest) returns (HelloReply) {} 29 | } 30 | 31 | // The actual message exchanged by the client and the server. 32 | // NOTE: When creating a custom scenario plese edit only this message. 33 | message Hello { 34 | string name = 1; 35 | } 36 | 37 | // The request message from the client. 38 | message HelloRequest { 39 | Hello request = 1; 40 | } 41 | 42 | // The response message from the server. 43 | message HelloReply { 44 | Hello response = 1; 45 | } 46 | -------------------------------------------------------------------------------- /scenarios/string_1kB/helloworld.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 gRPC authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | option go_package = "proto/helloworld"; 18 | option java_multiple_files = true; 19 | option java_package = "io.grpc.examples.helloworld"; 20 | option java_outer_classname = "HelloWorldProto"; 21 | option objc_class_prefix = "HLW"; 22 | 23 | package helloworld; 24 | 25 | // The greeting service definition. 26 | service Greeter { 27 | // Sends a greeting 28 | rpc SayHello (HelloRequest) returns (HelloReply) {} 29 | } 30 | 31 | // The actual message exchanged by the client and the server. 32 | // NOTE: When creating a custom scenario plese edit only this message. 33 | message Hello { 34 | string name = 1; 35 | } 36 | 37 | // The request message from the client. 38 | message HelloRequest { 39 | Hello request = 1; 40 | } 41 | 42 | // The response message from the server. 43 | message HelloReply { 44 | Hello response = 1; 45 | } 46 | -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.github.johnrengelman.shadow") version "7.0.0" 3 | id("io.micronaut.application") version "3.5.3" 4 | id("com.google.protobuf") version "0.8.19" 5 | } 6 | 7 | version = "0.1" 8 | group = "com.example" 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | micronaut { 15 | processing { 16 | incremental(true) 17 | annotations("com.example.*") 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation("io.micronaut:micronaut-runtime") 23 | implementation("io.micronaut.grpc:micronaut-grpc-runtime") 24 | implementation("javax.annotation:javax.annotation-api") 25 | implementation("io.grpc:grpc-protobuf:1.49.0") 26 | implementation("io.grpc:grpc-stub:1.49.0") 27 | runtimeOnly("ch.qos.logback:logback-classic") 28 | implementation("io.micronaut:micronaut-validation") 29 | } 30 | 31 | 32 | application { 33 | mainClass.set("helloworld.Application") 34 | } 35 | 36 | java { 37 | sourceCompatibility = JavaVersion.toVersion("11") 38 | targetCompatibility = JavaVersion.toVersion("11") 39 | } 40 | 41 | sourceSets { 42 | main { 43 | java { 44 | srcDirs("build/generated/source/proto/main/grpc") 45 | srcDirs("build/generated/source/proto/main/java") 46 | } 47 | } 48 | } 49 | 50 | protobuf { 51 | protoc { artifact = "com.google.protobuf:protoc:3.21.5" } 52 | plugins { 53 | grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.49.0" } 54 | } 55 | generateProtoTasks { 56 | all()*.plugins { grpc {} } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /go_grpc_bench/example/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2015 gRPC authors. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | // Package main implements a server for Greeter service. 20 | package main 21 | 22 | import ( 23 | "context" 24 | "log" 25 | "net" 26 | 27 | _ "go.uber.org/automaxprocs" 28 | "google.golang.org/grpc" 29 | pb "local/proto/helloworld" 30 | ) 31 | 32 | const ( 33 | port = ":50051" 34 | ) 35 | 36 | // server is used to implement helloworld.GreeterServer. 37 | type server struct { 38 | pb.UnimplementedGreeterServer 39 | } 40 | 41 | // SayHello implements helloworld.GreeterServer 42 | func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { 43 | return &pb.HelloReply{Response: in.GetRequest()}, nil 44 | } 45 | 46 | func main() { 47 | lis, err := net.Listen("tcp", port) 48 | if err != nil { 49 | log.Fatalf("failed to listen: %v", err) 50 | } 51 | s := grpc.NewServer() 52 | pb.RegisterGreeterServer(s, &server{}) 53 | if err := s.Serve(lis); err != nil { 54 | log.Fatalf("failed to serve: %v", err) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /dotnet_grpc_bench/GreeterServer/Program.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2019 The gRPC Authors 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using GreeterServer; 20 | using GreeterServer.Services; 21 | using Microsoft.AspNetCore.Server.Kestrel.Core; 22 | 23 | var builder = WebApplication.CreateBuilder(args); 24 | 25 | builder.WebHost.ConfigureKestrel(options => 26 | { 27 | options.AddServerHeader = false; 28 | options.ListenAnyIP(50051, listenOptions => 29 | { 30 | listenOptions.Protocols = HttpProtocols.Http2; 31 | }); 32 | }); 33 | 34 | builder.Logging.ClearProviders(); 35 | 36 | builder.Services.AddGrpc(o => o.IgnoreUnknownServices = true); 37 | builder.Services.Configure(c => c.SuppressCheckForUnhandledSecurityMetadata = true); 38 | builder.Services.AddSingleton(); 39 | 40 | var app = builder.Build(); 41 | 42 | app.Lifetime.ApplicationStarted.Register(() => Console.WriteLine("Application started.")); 43 | app.UseMiddleware(); 44 | app.MapGrpcService(); 45 | 46 | app.Run(); -------------------------------------------------------------------------------- /scala_akka_bench/build.sbt: -------------------------------------------------------------------------------- 1 | name := "akka-grpc-quickstart-scala" 2 | 3 | version := "1.0" 4 | 5 | scalaVersion := "2.13.15" 6 | 7 | run / fork := true 8 | 9 | val akkaVersion = "2.8.2" 10 | val akkaHttpVersion = "10.5.2" 11 | 12 | enablePlugins(AkkaGrpcPlugin) 13 | 14 | // to get latest versions 15 | resolvers += "Sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots" 16 | 17 | libraryDependencies ++= Seq( 18 | "ch.qos.logback" % "logback-classic" % "1.5.16", 19 | "com.typesafe.akka" %% "akka-actor-typed" % akkaVersion, 20 | "com.typesafe.akka" %% "akka-http" % akkaHttpVersion, 21 | "com.typesafe.akka" %% "akka-http-core" % akkaHttpVersion, 22 | "com.typesafe.akka" %% "akka-parsing" % akkaHttpVersion, 23 | "com.typesafe.akka" %% "akka-stream" % akkaVersion, 24 | "com.typesafe.akka" %% "akka-discovery" % akkaVersion, 25 | "com.typesafe.akka" %% "akka-pki" % akkaVersion, 26 | "com.typesafe.akka" %% "akka-slf4j" % akkaVersion, 27 | "com.typesafe.akka" %% "akka-actor-testkit-typed" % akkaVersion % Test, 28 | "com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion % Test, 29 | "org.scalatest" %% "scalatest" % "3.2.19" % Test 30 | ) 31 | 32 | // Akka and Google provided proto files seem to differ a bit so we need to choose 33 | // (doesn't seem to be important) 34 | assembly / assemblyMergeStrategy := { 35 | case PathList(ps @ _*) if ps.last endsWith ".proto" => MergeStrategy.first 36 | case PathList("module-info.class") => MergeStrategy.last 37 | case path if path.endsWith("/module-info.class") => MergeStrategy.last 38 | case x => 39 | val oldStrategy = (assembly / assemblyMergeStrategy).value 40 | oldStrategy(x) 41 | } 42 | -------------------------------------------------------------------------------- /rust_thruster_st_bench/src/main.rs: -------------------------------------------------------------------------------- 1 | use dotenv::dotenv; 2 | use log::info; 3 | use std::env; 4 | use thruster::{ 5 | context::hyper_request::HyperRequest, m, middleware_fn, App, MiddlewareNext, MiddlewareResult, 6 | ThrusterServer, 7 | }; 8 | use thruster_grpc::{ 9 | context::{generate_context, ProtoContext, ProtoContextExt}, 10 | server::ProtoServer, 11 | }; 12 | 13 | #[global_allocator] 14 | static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; 15 | 16 | mod hello_world { 17 | include!(concat!(env!("OUT_DIR"), "/helloworld.rs")); 18 | } 19 | 20 | type Ctx = ProtoContext<()>; 21 | 22 | #[middleware_fn] 23 | pub async fn say_hello(mut context: Ctx, _next: MiddlewareNext) -> MiddlewareResult { 24 | let hello_world_request = context 25 | .get_proto::() 26 | .await 27 | .unwrap(); 28 | 29 | context 30 | .proto(hello_world::HelloReply { 31 | response: hello_world_request.request, 32 | }) 33 | .await; 34 | 35 | Ok(context) 36 | } 37 | 38 | #[tokio::main(flavor = "current_thread")] 39 | async fn main() { 40 | let _ = dotenv(); 41 | 42 | env_logger::init(); 43 | 44 | let host = env::var("HOST").unwrap_or_else(|_| "0.0.0.0".to_string()); 45 | let port = env::var("PORT").unwrap_or_else(|_| "50051".to_string()); 46 | 47 | info!("Starting server at {}:{}!", host, port); 48 | 49 | let app = App::::create(generate_context, ()) 50 | .post("/helloworld.Greeter/SayHello", m![say_hello]); 51 | 52 | ProtoServer::new(app) 53 | .build(&host, port.parse::().unwrap()) 54 | .await; 55 | } 56 | -------------------------------------------------------------------------------- /java_aot_bench/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.github.johnrengelman.shadow") version "7.0.0" 3 | id("io.micronaut.application") version "3.5.3" 4 | id("com.google.protobuf") version "0.8.19" 5 | } 6 | 7 | version = "0.1" 8 | group = "com.example" 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | micronaut { 15 | testRuntime("junit5") 16 | processing { 17 | incremental(true) 18 | annotations("com.example.*") 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation("io.micronaut:micronaut-runtime") 24 | implementation("io.micronaut.grpc:micronaut-grpc-runtime") 25 | implementation("javax.annotation:javax.annotation-api") 26 | implementation("io.grpc:grpc-protobuf:1.49.0") 27 | implementation("io.grpc:grpc-stub:1.49.0") 28 | runtimeOnly("ch.qos.logback:logback-classic") 29 | implementation("io.micronaut:micronaut-validation") 30 | testImplementation("io.micronaut:micronaut-http-client") 31 | } 32 | 33 | 34 | application { 35 | mainClass.set("helloworld.Application") 36 | } 37 | 38 | java { 39 | sourceCompatibility = JavaVersion.toVersion("11") 40 | targetCompatibility = JavaVersion.toVersion("11") 41 | } 42 | 43 | sourceSets { 44 | main { 45 | java { 46 | srcDirs("build/generated/source/proto/main/grpc") 47 | srcDirs("build/generated/source/proto/main/java") 48 | } 49 | } 50 | } 51 | 52 | protobuf { 53 | protoc { artifact = "com.google.protobuf:protoc:3.21.5" } 54 | plugins { 55 | grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.49.0" } 56 | } 57 | generateProtoTasks { 58 | all()*.plugins { grpc {} } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /scala_pekko_bench/build.sbt: -------------------------------------------------------------------------------- 1 | name := "pekko-grpc-quickstart-scala" 2 | 3 | version := "1.0" 4 | 5 | scalaVersion := "2.13.17" 6 | 7 | run / fork := true 8 | 9 | val pekkoVersion = "1.2.1" 10 | val pekkoHttpVersion = "1.3.0" 11 | 12 | enablePlugins(PekkoGrpcPlugin) 13 | 14 | // to get latest versions 15 | resolvers += "Sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots" 16 | 17 | libraryDependencies ++= Seq( 18 | "ch.qos.logback" % "logback-classic" % "1.5.16", 19 | "org.apache.pekko" %% "pekko-actor-typed" % pekkoVersion, 20 | "org.apache.pekko" %% "pekko-http" % pekkoHttpVersion, 21 | "org.apache.pekko" %% "pekko-http-core" % pekkoHttpVersion, 22 | "org.apache.pekko" %% "pekko-parsing" % pekkoHttpVersion, 23 | "org.apache.pekko" %% "pekko-stream" % pekkoVersion, 24 | "org.apache.pekko" %% "pekko-discovery" % pekkoVersion, 25 | "org.apache.pekko" %% "pekko-pki" % pekkoVersion, 26 | "org.apache.pekko" %% "pekko-slf4j" % pekkoVersion, 27 | "org.apache.pekko" %% "pekko-actor-testkit-typed" % pekkoVersion % Test, 28 | "org.apache.pekko" %% "pekko-stream-testkit" % pekkoVersion % Test, 29 | "org.scalatest" %% "scalatest" % "3.2.19" % Test 30 | ) 31 | 32 | // pekko and Google provided proto files seem to differ a bit so we need to choose 33 | // (doesn't seem to be important) 34 | assembly / assemblyMergeStrategy := { 35 | case PathList(ps @ _*) if ps.last endsWith ".proto" => MergeStrategy.first 36 | case PathList("module-info.class") => MergeStrategy.last 37 | case path if path.endsWith("/module-info.class") => MergeStrategy.last 38 | case x => 39 | val oldStrategy = (assembly / assemblyMergeStrategy).value 40 | oldStrategy(x) 41 | } 42 | -------------------------------------------------------------------------------- /cpp_asio_grpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcc:15.2.0 2 | 3 | RUN apt-get update && apt-get install -y \ 4 | wget \ 5 | make \ 6 | libprotobuf-dev \ 7 | libgrpc++-dev \ 8 | protobuf-compiler \ 9 | protobuf-compiler-grpc \ 10 | libboost-dev \ 11 | libboost-coroutine-dev \ 12 | libjemalloc-dev 13 | 14 | WORKDIR /app 15 | 16 | ARG CMAKE_VERSION=3.21.2 17 | RUN wget --no-verbose https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-linux-x86_64.sh \ 18 | && chmod +x ./cmake-${CMAKE_VERSION}-linux-x86_64.sh \ 19 | && ./cmake-${CMAKE_VERSION}-linux-x86_64.sh --skip-license --prefix=/usr 20 | 21 | ARG ASIO_GRPC_VERSION=1.0.0 22 | RUN wget --no-verbose https://github.com/Tradias/asio-grpc/archive/refs/tags/v${ASIO_GRPC_VERSION}.tar.gz \ 23 | && tar zxf v${ASIO_GRPC_VERSION}.tar.gz -C /app \ 24 | && cd asio-grpc-${ASIO_GRPC_VERSION} \ 25 | && mkdir build \ 26 | && cd build \ 27 | && cmake .. \ 28 | && cmake --build . --target install 29 | 30 | COPY proto /app/proto 31 | RUN mkdir gen \ 32 | && protoc --proto_path=/app/proto/helloworld --cpp_out=gen helloworld.proto \ 33 | && protoc --proto_path=/app/proto/helloworld --grpc_out=gen --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` helloworld.proto 34 | 35 | COPY cpp_asio_grpc_bench /app 36 | RUN mkdir build \ 37 | && cd build \ 38 | && cmake \ 39 | -DCMAKE_BUILD_TYPE=Release \ 40 | -DCMAKE_INSTALL_PREFIX=/app/out \ 41 | -DCMAKE_C_FLAGS="-ljemalloc" \ 42 | -DCMAKE_CXX_FLAGS="-ljemalloc" \ 43 | .. \ 44 | && cmake --build . --config=Release --parallel=3 --target install 45 | 46 | EXPOSE 50051 47 | 48 | ENTRYPOINT ["/app/out/bin/cpp_asio_grpc_bench"] 49 | -------------------------------------------------------------------------------- /swift_grpc_bench/Sources/Server/main.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, gRPC Authors All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import Foundation 17 | import GRPC 18 | import HelloWorldModel 19 | import NIO 20 | import Logging 21 | 22 | // Quieten the logs. 23 | LoggingSystem.bootstrap { 24 | var handler = StreamLogHandler.standardOutput(label: $0) 25 | handler.logLevel = .critical 26 | return handler 27 | } 28 | 29 | let numberOfThreads = ProcessInfo.processInfo.environment["GRPC_SERVER_CPUS"].flatMap(Int.init) ?? 1 30 | let group = MultiThreadedEventLoopGroup(numberOfThreads: numberOfThreads) 31 | defer { 32 | try! group.syncShutdownGracefully() 33 | } 34 | 35 | // Start the server and print its address once it has started. 36 | let server = Server.insecure(group: group) 37 | .withServiceProviders([GreeterProvider()]) 38 | .bind(host: "0.0.0.0", port: 50051) 39 | 40 | server.map { 41 | $0.channel.localAddress 42 | }.whenSuccess { address in 43 | print("server started on port \(address!.port!)") 44 | } 45 | 46 | // Wait on the server's `onClose` future to stop the program from exiting. 47 | _ = try server.flatMap { 48 | $0.onClose 49 | }.wait() 50 | -------------------------------------------------------------------------------- /scala_zio_bench/src/main/scala/com/example/helloworld/GreeterServer.scala: -------------------------------------------------------------------------------- 1 | package com.example.helloworld 2 | 3 | import scalapb.zio_grpc.{Server, ServerLayer, ServerMain, ServiceList} 4 | import zio.ZLayer 5 | 6 | import java.util.concurrent.Executors 7 | 8 | object GreeterServer extends ServerMain { 9 | def services: ServiceList[Any] = ServiceList.add(GreeterImpl) 10 | 11 | // Default port is 9000 12 | override def port = 50051 13 | 14 | override def serverLive: ZLayer[Any, Throwable, Server] = { 15 | val sb = builder 16 | 17 | /** 18 | * Allow customization of the Executor with two environment variables: 19 | * 20 | *

21 | *

    22 | *
  • JVM_EXECUTOR_TYPE: direct, workStealing, single, fixed, cached
  • 23 | *
  • GRPC_SERVER_CPUS: integer value.
  • 24 | *
25 | *

26 | * 27 | * The number of Executor Threads will default to the number of 28 | * availableProcessors(). Only the workStealing and fixed executors will use 29 | * this value. 30 | */ 31 | val threads = System.getenv("GRPC_SERVER_CPUS") 32 | var i_threads = Runtime.getRuntime.availableProcessors 33 | if (threads != null && !threads.isEmpty) i_threads = threads.toInt 34 | val value = System.getenv.getOrDefault("JVM_EXECUTOR_TYPE", "workStealing") 35 | value match { 36 | case "direct" => sb.directExecutor 37 | case "single" => sb.executor(Executors.newSingleThreadExecutor) 38 | case "fixed" => sb.executor(Executors.newFixedThreadPool(i_threads)) 39 | case "workStealing" => sb.executor(Executors.newWorkStealingPool(i_threads)) 40 | case "cached" => sb.executor(Executors.newCachedThreadPool) 41 | } 42 | 43 | ServerLayer.fromServiceList(sb, services) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /rust_tonic_mt_bench/src/main.rs: -------------------------------------------------------------------------------- 1 | use tonic::{transport::Server, Request, Response, Status}; 2 | 3 | use hello_world::greeter_server::{Greeter, GreeterServer}; 4 | use hello_world::{HelloReply, HelloRequest}; 5 | 6 | #[global_allocator] 7 | static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; 8 | 9 | 10 | pub mod hello_world { 11 | tonic::include_proto!("helloworld"); 12 | } 13 | 14 | #[derive(Default)] 15 | pub struct MyGreeter {} 16 | 17 | #[tonic::async_trait] 18 | impl Greeter for MyGreeter { 19 | async fn say_hello( 20 | &self, 21 | request: Request, 22 | ) -> Result, Status> { 23 | let reply = hello_world::HelloReply { 24 | response: request.into_inner().request, 25 | }; 26 | Ok(Response::new(reply)) 27 | } 28 | } 29 | 30 | fn main() -> Result<(), Box> { 31 | let cpus = std::env::var("GRPC_SERVER_CPUS") 32 | .map(|v| v.parse().unwrap()) 33 | .unwrap_or(1); 34 | 35 | println!("Running with {} threads", cpus); 36 | 37 | // Esentially the same as tokio::main, but with number of threads set to 38 | // avoid thrashing when cggroup limits are applied by Docker. 39 | tokio::runtime::Builder::new_multi_thread() 40 | .worker_threads(cpus) 41 | .enable_all() 42 | .build() 43 | .unwrap() 44 | .block_on(serve()) 45 | } 46 | 47 | async fn serve() -> Result<(), Box> { 48 | let addr = "0.0.0.0:50051".parse().unwrap(); 49 | let greeter = MyGreeter::default(); 50 | 51 | println!("GreeterServer listening on {}", addr); 52 | 53 | Server::builder() 54 | .add_service(GreeterServer::new(greeter)) 55 | .serve(addr) 56 | .await?; 57 | 58 | Ok(()) 59 | } 60 | -------------------------------------------------------------------------------- /scala_pekko_bench/src/main/scala/com/example/helloworld/GreeterServer.scala: -------------------------------------------------------------------------------- 1 | package io.grpc.examples.helloworld 2 | 3 | //#import 4 | import org.apache.pekko.actor.typed.ActorSystem 5 | import org.apache.pekko.actor.typed.scaladsl.Behaviors 6 | import org.apache.pekko.actor.typed.scaladsl.adapter._ 7 | import org.apache.pekko.http.scaladsl.{Http, HttpConnectionContext} 8 | import org.apache.pekko.http.scaladsl.model.{HttpRequest, HttpResponse} 9 | import org.apache.pekko.stream.SystemMaterializer 10 | 11 | import scala.concurrent.{ExecutionContext, Future} 12 | //#import 13 | 14 | 15 | //#server 16 | object GreeterServer { 17 | def main(args: Array[String]): Unit = { 18 | val system = ActorSystem[Nothing](Behaviors.empty, "GreeterServer") 19 | new GreeterServer()(system).run() 20 | } 21 | } 22 | 23 | class GreeterServer(implicit system: ActorSystem[_]) { 24 | 25 | def run(): Future[Http.ServerBinding] = { 26 | implicit val ec: ExecutionContext = system.executionContext 27 | 28 | val service: HttpRequest => Future[HttpResponse] = 29 | GreeterHandler(new GreeterServiceImpl(system)) 30 | 31 | println(s"Parallel: ${system.settings.config.getString("pekko.actor.default-dispatcher.fork-join-executor.parallelism-max")} GRPC_SERVER_CPUS: ${sys.env.get("GRPC_SERVER_CPUS")}") 32 | 33 | // Pekko HTTP 10.1 requires adapters to accept the new actors APIs 34 | val bound = Http()(system.toClassic).bindAndHandleAsync( 35 | service, 36 | interface = "0.0.0.0", 37 | port = 50051, 38 | connectionContext = HttpConnectionContext() 39 | )(SystemMaterializer(system).materializer) 40 | 41 | bound.foreach { binding => 42 | println(s"gRPC server bound to: ${binding.localAddress}") 43 | } 44 | 45 | bound 46 | } 47 | //#server 48 | 49 | } 50 | //#server 51 | -------------------------------------------------------------------------------- /java_armeria_bench/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'application' 3 | id 'com.google.protobuf' version '0.8.19' 4 | id 'idea' 5 | } 6 | 7 | repositories { 8 | maven { // The google mirror is less flaky than mavenCentral() 9 | url "https://maven-central.storage-download.googleapis.com/repos/central/data/" } 10 | mavenCentral() 11 | mavenLocal() 12 | } 13 | 14 | sourceCompatibility = 17 15 | targetCompatibility = 17 16 | 17 | 18 | def armeriaVersion = '1.20.3' 19 | def grpcVersion = '1.58.0' 20 | def protocVersion = '3.21.5' 21 | 22 | dependencies { 23 | implementation "com.linecorp.armeria:armeria:${armeriaVersion}" 24 | implementation "com.linecorp.armeria:armeria-grpc:${armeriaVersion}" 25 | compileOnly 'javax.annotation:javax.annotation-api:1.3.2' 26 | } 27 | 28 | protobuf { 29 | protoc { artifact = "com.google.protobuf:protoc:${protocVersion}" } 30 | plugins { 31 | grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" } 32 | } 33 | generateProtoTasks { 34 | all()*.plugins { grpc {} } 35 | } 36 | } 37 | 38 | // Inform IDEs like IntelliJ IDEA, Eclipse or NetBeans about the generated code. 39 | sourceSets { 40 | main { 41 | java { 42 | srcDirs 'build/generated/source/proto/main/grpc' 43 | srcDirs 'build/generated/source/proto/main/java' 44 | } 45 | } 46 | } 47 | 48 | startScripts.enabled = false 49 | 50 | task helloWorldServer(type: CreateStartScripts) { 51 | mainClassName = 'com.linecorp.armeria.examples.helloworld.HelloWorldServer' 52 | applicationName = 'hello-world-server' 53 | outputDir = new File(project.buildDir, 'tmp') 54 | classpath = startScripts.classpath 55 | } 56 | 57 | applicationDistribution.into('bin') { 58 | from(helloWorldServer) 59 | fileMode = 0755 60 | } 61 | -------------------------------------------------------------------------------- /node_grpcjs_st_bench/greeter_server.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2015 gRPC authors. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | var PROTO_PATH = __dirname + '/proto/helloworld/helloworld.proto'; 20 | 21 | var grpc = require('@grpc/grpc-js'); 22 | var protoLoader = require('@grpc/proto-loader'); 23 | var packageDefinition = protoLoader.loadSync( 24 | PROTO_PATH, 25 | {keepCase: true, 26 | longs: String, 27 | enums: String, 28 | defaults: true, 29 | oneofs: true 30 | }); 31 | var hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld; 32 | 33 | /** 34 | * Implements the SayHello RPC method. 35 | */ 36 | function sayHello(call, callback) { 37 | callback(null, {response: call.request.request}); 38 | } 39 | 40 | /** 41 | * Starts an RPC server that receives requests for the Greeter service at the 42 | * sample server port 43 | */ 44 | function main() { 45 | var server = new grpc.Server(); 46 | server.addService(hello_proto.Greeter.service, {sayHello: sayHello}); 47 | server.bindAsync( 48 | '0.0.0.0:50051', 49 | grpc.ServerCredentials.createInsecure(), 50 | (err, port) => { 51 | process.stdout.write("Server started on 50051"); 52 | server.start(); 53 | } 54 | ); 55 | } 56 | 57 | main(); 58 | -------------------------------------------------------------------------------- /go_vtgrpc_bench/example/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2015 gRPC authors. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | // Package main implements a server for Greeter service. 20 | package main 21 | 22 | import ( 23 | "context" 24 | "log" 25 | "net" 26 | 27 | _ "go.uber.org/automaxprocs" 28 | 29 | "google.golang.org/grpc" 30 | vtgrpc "github.com/planetscale/vtprotobuf/codec/grpc" 31 | "google.golang.org/grpc/encoding" 32 | _ "google.golang.org/grpc/encoding/proto" 33 | pb "local/proto/helloworld" 34 | ) 35 | 36 | const ( 37 | port = ":50051" 38 | ) 39 | 40 | // server is used to implement helloworld.GreeterServer. 41 | type server struct { 42 | pb.UnimplementedGreeterServer 43 | } 44 | 45 | // SayHello implements helloworld.GreeterServer 46 | func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { 47 | return &pb.HelloReply{Response: in.GetRequest()}, nil 48 | } 49 | 50 | func main() { 51 | lis, err := net.Listen("tcp", port) 52 | if err != nil { 53 | log.Fatalf("failed to listen: %v", err) 54 | } 55 | encoding.RegisterCodec(vtgrpc.Codec{}) 56 | s := grpc.NewServer() 57 | pb.RegisterGreeterServer(s, &server{}) 58 | if err := s.Serve(lis); err != nil { 59 | log.Fatalf("failed to serve: %v", err) 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /dotnet_grpc_bench/GreeterServer/ServiceProvidersMiddleware.cs: -------------------------------------------------------------------------------- 1 | #region Copyright notice and license 2 | 3 | // Copyright 2019 The gRPC Authors 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #endregion 18 | 19 | using Microsoft.AspNetCore.Http.Features; 20 | 21 | namespace GreeterServer; 22 | 23 | public class ServiceProvidersMiddleware 24 | { 25 | private readonly ServiceProvidersFeature _serviceProvidersFeature; 26 | private readonly RequestDelegate _next; 27 | 28 | public ServiceProvidersMiddleware(RequestDelegate next, IServiceProvider serviceProvider) 29 | { 30 | _serviceProvidersFeature = new ServiceProvidersFeature(serviceProvider); 31 | _next = next; 32 | } 33 | 34 | public Task InvokeAsync(HttpContext context) 35 | { 36 | // Configure request to use application services to avoid creating a request scope 37 | context.Features.Set(_serviceProvidersFeature); 38 | return _next(context); 39 | } 40 | 41 | private class ServiceProvidersFeature : IServiceProvidersFeature 42 | { 43 | public ServiceProvidersFeature(IServiceProvider requestServices) 44 | { 45 | RequestServices = requestServices; 46 | } 47 | 48 | public IServiceProvider RequestServices { get; set; } 49 | } 50 | } -------------------------------------------------------------------------------- /go_connect_bench/go.sum: -------------------------------------------------------------------------------- 1 | connectrpc.com/connect v1.16.1 h1:rOdrK/RTI/7TVnn3JsVxt3n028MlTRwmK5Q4heSpjis= 2 | connectrpc.com/connect v1.16.1/go.mod h1:XpZAduBQUySsb4/KO5JffORVkDI4B6/EYPi7N8xpNZw= 3 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 4 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 6 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 7 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 8 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 9 | github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= 10 | github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= 11 | github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= 12 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 13 | go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= 14 | go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= 15 | golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= 16 | golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= 17 | golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= 18 | golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= 19 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 20 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 21 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 22 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 23 | -------------------------------------------------------------------------------- /ruby_grpc_bench/server.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Copyright 2015 gRPC authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Sample gRPC server that implements the Greeter::Helloworld service. 18 | # 19 | # Usage: $ path/to/greeter_server.rb 20 | 21 | this_dir = File.expand_path(__dir__) 22 | lib_dir = File.join(this_dir, 'lib') 23 | $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) 24 | 25 | require 'grpc' 26 | require 'helloworld_services_pb' 27 | 28 | # GreeterServer is simple server that implements the Helloworld Greeter server. 29 | class GreeterServer < Helloworld::Greeter::Service 30 | # say_hello implements the SayHello rpc method. 31 | def say_hello(hello_req, _unused_call) 32 | Helloworld::HelloReply.new(response: hello_req.request) 33 | end 34 | end 35 | 36 | # main starts an RpcServer that receives requests to GreeterServer at the sample 37 | # server port. 38 | def main 39 | s = GRPC::RpcServer.new 40 | s.add_http2_port('0.0.0.0:50051', :this_port_is_insecure) 41 | puts 'Listening on 50051' 42 | s.handle(GreeterServer) 43 | # Runs the server with SIGHUP, SIGINT and SIGQUIT signal handlers to 44 | # gracefully shutdown. 45 | # User could also choose to run server via call to run_till_terminated 46 | s.run_till_terminated_or_interrupted([1, 'int', 'SIGQUIT']) 47 | end 48 | 49 | main 50 | -------------------------------------------------------------------------------- /d_grpc_bench/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | FROM buildpack-deps:bookworm AS builder 4 | 5 | RUN set -eux; \ 6 | wget -O ldc2-1.40.1-linux-x86_64.tar.xz https://github.com/ldc-developers/ldc/releases/download/v1.40.1/ldc2-1.40.1-linux-x86_64.tar.xz; \ 7 | echo "085a593dba4b1385ec03e7521aa97356e5a7d9f6194303eccb3c1e35935c69d8 *ldc2-1.40.1-linux-x86_64.tar.xz" | sha256sum -c -; \ 8 | tar --strip-components=1 -C /usr/local -Jxf ldc2-1.40.1-linux-x86_64.tar.xz; \ 9 | rm ldc2-1.40.1-linux-x86_64.tar.xz 10 | 11 | RUN set -eux; \ 12 | apt-get update; \ 13 | apt-get install -y --no-install-recommends \ 14 | protobuf-compiler \ 15 | git \ 16 | cmake \ 17 | g++; \ 18 | rm -fr /var/lib/apt/lists/* 19 | 20 | # Building the protocol buffer compiler for D 21 | RUN dub build protobuf:protoc-gen-d 22 | 23 | WORKDIR /app 24 | RUN git clone https://github.com/huntlabs/grpc-dlang && \ 25 | cd grpc-dlang && \ 26 | git checkout cce7a8fd14563292adcd562e65afdcc10b9ce3f2 && \ 27 | git submodule update --init --depth=1 28 | 29 | # Building the gRPC plugin for D 30 | RUN mkdir -p /app/grpc-dlang/compiler/build 31 | WORKDIR /app/grpc-dlang/compiler/build 32 | RUN cmake -Dprotobuf_BUILD_TESTS=OFF .. && make -j4 33 | RUN cp deps/protobuf/protoc* /usr/local/bin 34 | RUN cp grpc_dlang_plugin /usr/local/bin 35 | 36 | COPY proto /app/proto 37 | COPY d_grpc_bench /app 38 | WORKDIR /app 39 | RUN protoc --plugin=$(find / -name 'protoc-gen-d' -type f | head -n 1) --d_out=/app/source --proto_path=/app/proto/helloworld helloworld.proto 40 | RUN protoc --plugin=protoc-gen-grpc=/usr/local/bin/grpc_dlang_plugin --grpc_out=/app/source/helloworld --proto_path=/app/proto/helloworld helloworld.proto 41 | 42 | RUN dub build -b release 43 | 44 | FROM debian:bookworm-slim AS final 45 | WORKDIR /app 46 | COPY --from=builder /app/server . 47 | ENTRYPOINT [ "/app/server" ] 48 | -------------------------------------------------------------------------------- /rust_thruster_mt_bench/src/main.rs: -------------------------------------------------------------------------------- 1 | use dotenv::dotenv; 2 | use log::info; 3 | use std::env; 4 | use thruster::{ 5 | context::hyper_request::HyperRequest, m, middleware_fn, App, MiddlewareNext, MiddlewareResult, 6 | ThrusterServer, 7 | }; 8 | use thruster_grpc::{ 9 | context::{generate_context, ProtoContext, ProtoContextExt}, 10 | server::ProtoServer, 11 | }; 12 | 13 | #[global_allocator] 14 | static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; 15 | 16 | mod hello_world { 17 | include!(concat!(env!("OUT_DIR"), "/helloworld.rs")); 18 | } 19 | 20 | type Ctx = ProtoContext<()>; 21 | 22 | #[middleware_fn] 23 | pub async fn say_hello(mut context: Ctx, _next: MiddlewareNext) -> MiddlewareResult { 24 | let hello_world_request = context 25 | .get_proto::() 26 | .await 27 | .unwrap(); 28 | 29 | context 30 | .proto(hello_world::HelloReply { 31 | response: hello_world_request.request, 32 | }) 33 | .await; 34 | 35 | Ok(context) 36 | } 37 | 38 | fn main() { 39 | let _ = dotenv(); 40 | 41 | env_logger::init(); 42 | 43 | let host = env::var("HOST").unwrap_or_else(|_| "0.0.0.0".to_string()); 44 | let port = env::var("PORT").unwrap_or_else(|_| "50051".to_string()); 45 | 46 | info!("Starting server at {}:{}!", host, port); 47 | 48 | let app = App::::create(generate_context, ()) 49 | .post("/helloworld.Greeter/SayHello", m![say_hello]); 50 | 51 | let cpus = std::env::var("GRPC_SERVER_CPUS") 52 | .map(|v| v.parse().unwrap()) 53 | .unwrap_or(1); 54 | 55 | info!("Running with {} threads", cpus); 56 | 57 | tokio::runtime::Builder::new_multi_thread() 58 | .worker_threads(cpus) 59 | .enable_all() 60 | .build() 61 | .unwrap() 62 | .block_on(ProtoServer::new(app).build(&host, port.parse::().unwrap())) 63 | } 64 | -------------------------------------------------------------------------------- /dart_grpc_onhold/bin/server.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018, the gRPC project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | /// Dart implementation of the gRPC helloworld.Greeter server. 17 | import 'dart:io'; 18 | import 'dart:isolate'; 19 | 20 | import 'package:grpc/grpc.dart'; 21 | 22 | import 'package:helloworld/src/generated/helloworld.pb.dart'; 23 | import 'package:helloworld/src/generated/helloworld.pbgrpc.dart'; 24 | 25 | class GreeterService extends GreeterServiceBase { 26 | @override 27 | Future sayHello(ServiceCall call, HelloRequest request) async { 28 | return HelloReply()..response = request.request; 29 | } 30 | } 31 | 32 | Future main(List args) async { 33 | Map env = Platform.environment; 34 | final cpus = int.tryParse(env["GRPC_SERVER_CPUS"] ?? '1') ?? 1; 35 | 36 | if (cpus > 1) { 37 | for (var serve = 0; serve < cpus; serve++) { 38 | Isolate.spawn(_startServer, []); 39 | } 40 | } 41 | // Bind one server in current Isolate 42 | _startServer(); 43 | 44 | print('Server listening on port 50051...'); 45 | await ProcessSignal.sigterm.watch().first; 46 | } 47 | 48 | void _startServer([List? args]) async { 49 | final server = Server([GreeterService()]); 50 | await server.serve( 51 | address: InternetAddress.anyIPv4, port: 50051, shared: true); 52 | } 53 | -------------------------------------------------------------------------------- /scenarios/complex_proto/helloworld.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 gRPC authors. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | option go_package = "proto/helloworld"; 18 | option java_multiple_files = true; 19 | option java_package = "io.grpc.examples.helloworld"; 20 | option java_outer_classname = "HelloWorldProto"; 21 | option objc_class_prefix = "HLW"; 22 | 23 | package helloworld; 24 | 25 | // The greeting service definition. 26 | service Greeter { 27 | // Sends a greeting 28 | rpc SayHello (HelloRequest) returns (HelloReply) {} 29 | } 30 | 31 | // The actual message exchanged by the client and the server. 32 | // NOTE: When creating a custom scenario plese edit only this message. 33 | message Hello { 34 | string name = 1; 35 | double d = 2; 36 | float f = 3; 37 | bool b = 4; 38 | int32 n = 5; 39 | int64 l = 6; 40 | oneof choice { 41 | string c1 = 7; 42 | bool c2 = 8; 43 | } 44 | message Pet { 45 | enum Color { 46 | BLACK = 0; 47 | WHITE = 1; 48 | BLUE = 2; 49 | RED = 3; 50 | YELLOW = 4; 51 | GREEN = 5; 52 | } 53 | string name = 1; 54 | Color color = 2; 55 | } 56 | repeated Pet pets = 9; 57 | } 58 | 59 | // The request message from the client. 60 | message HelloRequest { 61 | Hello request = 1; 62 | } 63 | 64 | // The response message from the server. 65 | message HelloReply { 66 | Hello response = 1; 67 | } 68 | -------------------------------------------------------------------------------- /java_micronaut_bench/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.github.johnrengelman.shadow") version "7.0.0" 3 | id("io.micronaut.application") version "4.0.0" 4 | id("com.google.protobuf") version "0.8.15" 5 | id 'idea' 6 | } 7 | 8 | version = "0.1" 9 | group = "com.example" 10 | 11 | repositories { 12 | maven { url "https://s01.oss.sonatype.org/content/repositories/snapshots/" 13 | mavenContent { snapshotsOnly() } 14 | } 15 | mavenCentral() 16 | } 17 | 18 | micronaut { 19 | processing { 20 | incremental(true) 21 | annotations("com.example.*") 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation("io.micronaut:micronaut-context") 27 | implementation 'javax.inject:javax.inject:1' 28 | implementation("io.micronaut.grpc:micronaut-grpc-runtime") 29 | implementation("io.micronaut.grpc:micronaut-grpc-server-runtime") 30 | implementation("io.micronaut.discovery:micronaut-discovery-client") 31 | implementation("javax.annotation:javax.annotation-api") 32 | implementation("io.grpc:grpc-protobuf:1.56.1") 33 | implementation("io.grpc:grpc-stub:1.56.1") 34 | // implementation("io.micronaut.platform:micronaut-platform:4.0.0") 35 | implementation 'io.micronaut:micronaut-inject' 36 | runtimeOnly("ch.qos.logback:logback-classic") 37 | } 38 | 39 | 40 | application { 41 | mainClass.set("helloworld.Application") 42 | } 43 | 44 | java { 45 | sourceCompatibility = JavaVersion.toVersion("17") 46 | targetCompatibility = JavaVersion.toVersion("17") 47 | } 48 | 49 | sourceSets { 50 | main { 51 | java { 52 | srcDirs("build/generated/source/proto/main/grpc") 53 | srcDirs("build/generated/source/proto/main/java") 54 | } 55 | } 56 | } 57 | 58 | protobuf { 59 | protoc { artifact = "com.google.protobuf:protoc:3.23.4" } 60 | plugins { 61 | grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.56.1" } 62 | } 63 | generateProtoTasks { 64 | all()*.plugins { grpc {} } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /rust_grpcio_bench/src/main.rs: -------------------------------------------------------------------------------- 1 | mod proto; 2 | 3 | use std::io::Read; 4 | use std::sync::Arc; 5 | use std::{io, thread}; 6 | 7 | use futures::channel::oneshot; 8 | use futures::executor::block_on; 9 | use futures::prelude::*; 10 | use grpcio::{ChannelBuilder, Environment, RpcContext, ServerBuilder, ServerCredentials, UnarySink}; 11 | 12 | use crate::proto::gen::helloworld::{HelloReply, HelloRequest}; 13 | use crate::proto::gen::helloworld_grpc::{create_greeter, Greeter}; 14 | 15 | #[global_allocator] 16 | static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; 17 | 18 | #[derive(Clone)] 19 | struct GreeterService; 20 | 21 | impl Greeter for GreeterService { 22 | fn say_hello(&mut self, ctx: RpcContext<'_>, mut req: HelloRequest, sink: UnarySink) { 23 | let mut resp = HelloReply::default(); 24 | resp.set_response(req.take_request()); 25 | let f = sink 26 | .success(resp) 27 | .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e)) 28 | .map(|_| ()); 29 | ctx.spawn(f) 30 | } 31 | } 32 | 33 | fn main() { 34 | let cpus = std::env::var("GRPC_SERVER_CPUS") 35 | .unwrap_or("1".to_string()) 36 | .parse() 37 | .unwrap(); 38 | let env = Arc::new(Environment::new(cpus)); 39 | let service = create_greeter(GreeterService); 40 | let ch_builder = ChannelBuilder::new(env.clone()); 41 | 42 | let addr = "0.0.0.0:50051"; 43 | let mut server = ServerBuilder::new(env) 44 | .register_service(service) 45 | .channel_args(ch_builder.build_args()) 46 | .build() 47 | .unwrap(); 48 | server 49 | .add_listening_port(addr, ServerCredentials::insecure()) 50 | .unwrap(); 51 | 52 | server.start(); 53 | println!("listening on {addr} ({cpus} cpus)"); 54 | let (tx, rx) = oneshot::channel(); 55 | thread::spawn(move || { 56 | println!("Press ENTER to exit..."); 57 | let _ = io::stdin().read(&mut [0]).unwrap(); 58 | tx.send(()) 59 | }); 60 | let _ = block_on(rx); 61 | let _ = block_on(server.shutdown()); 62 | } 63 | -------------------------------------------------------------------------------- /elixir_grpc_bench_onhold/mix.lock: -------------------------------------------------------------------------------- 1 | %{ 2 | cowboy: 3 | {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", 4 | [:make, :rebar3], 5 | [ 6 | {:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, 7 | {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]} 8 | ], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, 9 | cowlib: 10 | {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", 11 | [:make, :rebar3], [], "hexpm", 12 | "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, 13 | dialyxir: 14 | {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", 15 | [:mix], [], "hexpm", "6c32a70ed5d452c6650916555b1f96c79af5fc4bf286997f8b15f213de786f73"}, 16 | grpc: 17 | {:hex, :grpc, "0.5.0", "a44cb306625a52fa31a2189ce91b40d24e82569568f0cc214c1e1e0faf54f58a", 18 | [:mix], 19 | [ 20 | {:cowboy, "~> 2.9", [hex: :cowboy, repo: "hexpm", optional: false]}, 21 | {:cowlib, "~> 2.11", [hex: :cowlib, repo: "hexpm", optional: false]}, 22 | {:gun, "~> 2.0.1", [hex: :grpc_gun, repo: "hexpm", optional: false]} 23 | ], "hexpm", "17b98593fdb1a65be7b2722821266627b3f2fba29bbbd7d0945389427c0d0d5f"}, 24 | gun: 25 | {:hex, :grpc_gun, "2.0.1", "221b792df3a93e8fead96f697cbaf920120deacced85c6cd3329d2e67f0871f8", 26 | [:rebar3], [{:cowlib, "~> 2.11", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", 27 | "795a65eb9d0ba16697e6b0e1886009ce024799e43bb42753f0c59b029f592831"}, 28 | protobuf: 29 | {:hex, :protobuf, "0.10.0", 30 | "4e8e3cf64c5be203b329f88bb8b916cb8d00fb3a12b2ac1f545463ae963c869f", [:mix], 31 | [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", 32 | "4ae21a386142357aa3d31ccf5f7d290f03f3fa6f209755f6e87fc2c58c147893"}, 33 | ranch: 34 | {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", 35 | [:make, :rebar3], [], "hexpm", 36 | "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"} 37 | } 38 | -------------------------------------------------------------------------------- /scala_fs2_bench/src/main/scala/com/example/helloworld/GreeterServer.scala: -------------------------------------------------------------------------------- 1 | package io.grpc.examples.helloworld 2 | 3 | import cats.effect._ 4 | import fs2.grpc.syntax.all._ 5 | import io.grpc.examples.helloworld.helloworld.GreeterFs2Grpc 6 | import io.grpc.{ServerBuilder, ServerServiceDefinition} 7 | 8 | import java.util.concurrent.Executors 9 | 10 | 11 | object GreeterServer extends IOApp { 12 | 13 | def run(args: List[String]): IO[ExitCode] = { 14 | val service: Resource[IO, ServerServiceDefinition] = 15 | GreeterFs2Grpc.bindServiceResource[IO](new GreeterServiceImpl()) 16 | 17 | def serverBuilder: ServerBuilder[_] = { 18 | val sb = ServerBuilder.forPort(50051) 19 | 20 | /** 21 | * Allow customization of the Executor with two environment variables: 22 | * 23 | *

24 | *

    25 | *
  • JVM_EXECUTOR_TYPE: direct, workStealing, single, fixed, cached
  • 26 | *
  • GRPC_SERVER_CPUS: integer value.
  • 27 | *
28 | *

29 | * 30 | * The number of Executor Threads will default to the number of 31 | * availableProcessors(). Only the workStealing and fixed executors will use 32 | * this value. 33 | */ 34 | val threads = System.getenv("GRPC_SERVER_CPUS") 35 | var i_threads = Runtime.getRuntime.availableProcessors 36 | if (threads != null && !threads.isEmpty) i_threads = threads.toInt 37 | val value = System.getenv.getOrDefault("JVM_EXECUTOR_TYPE", "workStealing") 38 | value match { 39 | case "direct" => sb.directExecutor 40 | case "single" => sb.executor(Executors.newSingleThreadExecutor) 41 | case "fixed" => sb.executor(Executors.newFixedThreadPool(i_threads)) 42 | case "workStealing" => sb.executor(Executors.newWorkStealingPool(i_threads)) 43 | case "cached" => sb.executor(Executors.newCachedThreadPool) 44 | } 45 | sb 46 | } 47 | 48 | def run(service: ServerServiceDefinition) = serverBuilder 49 | .addService(service) 50 | .resource[IO] 51 | .evalMap(server => IO(server.start())) 52 | .useForever 53 | 54 | service.use(run) 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /java_vertx_grpc_bench/src/main/java/vertx/Main.java: -------------------------------------------------------------------------------- 1 | package vertx; 2 | 3 | import io.grpc.examples.helloworld.GreeterGrpc; 4 | import io.grpc.examples.helloworld.Hello; 5 | import io.grpc.examples.helloworld.HelloReply; 6 | import io.grpc.examples.helloworld.HelloRequest; 7 | import io.vertx.core.AbstractVerticle; 8 | import io.vertx.core.DeploymentOptions; 9 | import io.vertx.core.Promise; 10 | import io.vertx.core.Vertx; 11 | import io.vertx.core.http.HttpServer; 12 | import io.vertx.grpc.server.GrpcServer; 13 | import io.vertx.grpc.server.GrpcServerResponse; 14 | 15 | public class Main { 16 | public static void main(String[] args) { 17 | Vertx vertx = Vertx.vertx(); 18 | DeploymentOptions deploymentOptions = new DeploymentOptions(); 19 | int cores = Runtime.getRuntime().availableProcessors(); 20 | String GRPC_SERVER_CPUS = System.getenv("GRPC_SERVER_CPUS"); 21 | if (GRPC_SERVER_CPUS != null && GRPC_SERVER_CPUS.length() > 0) { 22 | cores = Integer.parseInt(GRPC_SERVER_CPUS); 23 | } 24 | deploymentOptions.setInstances(cores); 25 | vertx.deployVerticle(ServerVerticle::new, deploymentOptions); 26 | System.out.println("Deploy vertical instances:"+cores); 27 | } 28 | 29 | static class ServerVerticle extends AbstractVerticle { 30 | @Override 31 | public void start(Promise startPromise) throws Exception { 32 | GrpcServer grpcServer = GrpcServer.server(vertx); 33 | grpcServer.callHandler(GreeterGrpc.getSayHelloMethod(), request -> { 34 | request.handler(helloRequest -> { 35 | GrpcServerResponse response = request.response(); 36 | Hello hello = helloRequest.getRequest(); 37 | HelloReply reply = HelloReply.newBuilder().setResponse(hello).build(); 38 | response.end(reply); 39 | }); 40 | }); 41 | HttpServer httpServer = vertx.createHttpServer(); 42 | httpServer.requestHandler(grpcServer).listen(50051).andThen(u -> { 43 | System.out.println("deployed: " + deploymentID()); 44 | startPromise.complete(); 45 | }); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /erlang_grpcbox_bench/rebar.config: -------------------------------------------------------------------------------- 1 | {profiles, [{prod, [{relx, [{dev_mode, false} 2 | ,{include_erts, true} 3 | ,{include_src, false} 4 | ]} 5 | ]} 6 | ]}. 7 | 8 | {erl_opts, [debug_info 9 | ,warnings_as_errors 10 | ,warn_unused_vars 11 | ,{i, "src"} 12 | ]}. 13 | 14 | {xref_checks, [undefined_function_calls 15 | ,undefined_functions 16 | %% ,exports_not_used 17 | ,locals_not_used 18 | ,deprecated_function_calls 19 | ,deprecated_functions 20 | ]}. 21 | {xref_ignores, [helloworld_pb 22 | ]}. 23 | 24 | {deps, [{grpcbox, {git, "https://github.com/tsloughter/grpcbox.git", {branch, "main"}}} 25 | ,{chatterbox, {git, "https://github.com/tsloughter/chatterbox.git", {branch, "master"}}} 26 | ]}. 27 | 28 | {grpc, [{protos, "../proto/helloworld"} 29 | %% https://hexdocs.pm/gpb/gpb_compile.html 30 | ,{gpb_opts, [{module_name_suffix, "_pb"} 31 | ,strings_as_binaries 32 | ,type_specs 33 | ,{verify, always} 34 | ,report 35 | ]} 36 | ]}. 37 | 38 | %% {project_plugins, [grpcbox_plugin TODO(fenollp): replace whence https://github.com/tsloughter/grpcbox_plugin/pull/16#issuecomment-1008303451 39 | {project_plugins, [{grpcbox_plugin, {git, "https://github.com/tsloughter/grpcbox_plugin.git", {branch, "master"}}} 40 | ]}. 41 | 42 | {shell, [{apps, [erlang_grpcbox_bench]} 43 | ,{config, "config/sys.config"} 44 | ]}. 45 | 46 | {relx, [{release, {erlang_grpcbox_bench, "1.0.0"}, [erlang_grpcbox_bench]} 47 | ,{dev_mode, true} 48 | ,{include_erts, false} 49 | %% ,{vm_args, "config/vm.args"} 50 | ,{sys_config, "config/sys.config"} 51 | ]}. 52 | 53 | {xref_checks, [undefined_function_calls 54 | ,undefined_functions 55 | %% ,exports_not_used 56 | ,locals_not_used 57 | ,deprecated_function_calls 58 | ,deprecated_functions 59 | ]}. 60 | {xref_ignores, [helloworld_pb 61 | ]}. 62 | -------------------------------------------------------------------------------- /scala_akka_bench/src/main/scala/com/example/helloworld/GreeterServer.scala: -------------------------------------------------------------------------------- 1 | package io.grpc.examples.helloworld 2 | 3 | //#import 4 | 5 | 6 | import java.io.File 7 | import java.nio.file.Files 8 | import java.security.KeyStore 9 | import java.security.SecureRandom 10 | import java.security.cert.Certificate 11 | import java.security.cert.CertificateFactory 12 | 13 | import scala.io.Source 14 | 15 | import akka.actor.typed.ActorSystem 16 | import akka.actor.typed.scaladsl.Behaviors 17 | import akka.actor.typed.scaladsl.adapter._ 18 | import akka.http.scaladsl.ConnectionContext 19 | import akka.http.scaladsl.Http 20 | import akka.http.scaladsl.HttpConnectionContext 21 | import akka.http.scaladsl.model.HttpRequest 22 | import akka.http.scaladsl.model.HttpResponse 23 | import akka.pki.pem.DERPrivateKeyLoader 24 | import akka.pki.pem.PEMDecoder 25 | import akka.stream.SystemMaterializer 26 | import com.typesafe.config.ConfigFactory 27 | import javax.net.ssl.KeyManagerFactory 28 | import javax.net.ssl.SSLContext 29 | 30 | import scala.concurrent.ExecutionContext 31 | import scala.concurrent.Future 32 | //#import 33 | 34 | 35 | //#server 36 | object GreeterServer { 37 | def main(args: Array[String]): Unit = { 38 | val system = ActorSystem[Nothing](Behaviors.empty, "GreeterServer") 39 | new GreeterServer()(system).run() 40 | } 41 | } 42 | 43 | class GreeterServer(implicit system: ActorSystem[_]) { 44 | 45 | def run(): Future[Http.ServerBinding] = { 46 | implicit val ec: ExecutionContext = system.executionContext 47 | 48 | val service: HttpRequest => Future[HttpResponse] = 49 | GreeterHandler(new GreeterServiceImpl(system)) 50 | 51 | println(s"Parallel: ${system.settings.config.getString("akka.actor.default-dispatcher.fork-join-executor.parallelism-max")} GRPC_SERVER_CPUS: ${sys.env.get("GRPC_SERVER_CPUS")}") 52 | 53 | // Akka HTTP 10.1 requires adapters to accept the new actors APIs 54 | val bound = Http()(system.toClassic).bindAndHandleAsync( 55 | service, 56 | interface = "0.0.0.0", 57 | port = 50051, 58 | connectionContext = HttpConnectionContext() 59 | )(SystemMaterializer(system).materializer) 60 | 61 | bound.foreach { binding => 62 | println(s"gRPC server bound to: ${binding.localAddress}") 63 | } 64 | 65 | bound 66 | } 67 | //#server 68 | 69 | } 70 | //#server 71 | -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/src/main/java/helloworld/ServerBuilderListener.java: -------------------------------------------------------------------------------- 1 | package helloworld; 2 | 3 | import io.grpc.ServerBuilder; 4 | import io.micronaut.context.event.BeanCreatedEvent; 5 | import io.micronaut.context.event.BeanCreatedEventListener; 6 | 7 | import javax.inject.Singleton; 8 | 9 | import java.io.IOException; 10 | import java.util.concurrent.TimeUnit; 11 | import java.util.logging.Logger; 12 | import java.util.concurrent.Executors; 13 | 14 | @Singleton 15 | public class ServerBuilderListener implements BeanCreatedEventListener> { 16 | @Override 17 | public ServerBuilder onCreated(BeanCreatedEvent> event) { 18 | final ServerBuilder builder = event.getBean(); 19 | builder.maxInboundMessageSize(1024); 20 | configureExecutor(builder); 21 | return builder; 22 | } 23 | 24 | /** 25 | * Allow customization of the Executor with two environment variables: 26 | * 27 | *

28 | *

    29 | *
  • JVM_EXECUTOR_TYPE: direct, workStealing, single, fixed, cached
  • 30 | *
  • GRPC_SERVER_CPUS: integer value.
  • 31 | *
32 | *

33 | * 34 | * The number of Executor Threads will default to the number of 35 | * availableProcessors(). Only the workStealing and fixed executors will use 36 | * this value. 37 | */ 38 | private ServerBuilder configureExecutor(ServerBuilder sb) { 39 | var threads = System.getenv("GRPC_SERVER_CPUS"); 40 | var i_threads = Runtime.getRuntime().availableProcessors(); 41 | if (threads != null && !threads.isEmpty()) { 42 | i_threads = Integer.parseInt(threads); 43 | } 44 | 45 | var value = System.getenv().getOrDefault("JVM_EXECUTOR_TYPE", "workStealing"); 46 | switch (value) { 47 | case "direct": 48 | sb = sb.directExecutor(); 49 | break; 50 | case "single": 51 | sb = sb.executor(Executors.newSingleThreadExecutor()); 52 | break; 53 | case "fixed": 54 | sb = sb.executor(Executors.newFixedThreadPool(i_threads)); 55 | break; 56 | case "workStealing": 57 | sb = sb.executor(Executors.newWorkStealingPool(i_threads)); 58 | break; 59 | case "cached": 60 | sb = sb.executor(Executors.newCachedThreadPool()); 61 | break; 62 | } 63 | 64 | return sb; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /kotlin_grpc_bench/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.google.protobuf.gradle.generateProtoTasks 2 | import com.google.protobuf.gradle.id 3 | import com.google.protobuf.gradle.ofSourceSet 4 | import com.google.protobuf.gradle.plugins 5 | import com.google.protobuf.gradle.protobuf 6 | import com.google.protobuf.gradle.protoc 7 | 8 | val grpcVersion = "1.58.0" 9 | val grpcKotlinVersion = "1.3.0" 10 | val protobufVersion = "3.21.5" 11 | val coroutinesVersion = "1.6.4" 12 | 13 | plugins { 14 | application 15 | kotlin("jvm") version "1.7.10" 16 | id("com.google.protobuf") version "0.8.19" 17 | id("org.jlleitschuh.gradle.ktlint") version "11.0.0" 18 | } 19 | 20 | repositories { 21 | mavenLocal() 22 | google() 23 | mavenCentral() 24 | } 25 | 26 | dependencies { 27 | implementation(kotlin("stdlib")) 28 | implementation("javax.annotation:javax.annotation-api:1.3.2") 29 | implementation("com.google.protobuf:protobuf-java-util:$protobufVersion") 30 | implementation("io.grpc:grpc-protobuf:$grpcVersion") 31 | implementation("io.grpc:grpc-stub:$grpcVersion") 32 | implementation("io.grpc:grpc-kotlin-stub:$grpcKotlinVersion") 33 | implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") 34 | runtimeOnly("io.grpc:grpc-netty-shaded:$grpcVersion") 35 | } 36 | 37 | protobuf { 38 | protoc { 39 | artifact = "com.google.protobuf:protoc:$protobufVersion" 40 | } 41 | plugins { 42 | id("grpc"){ 43 | artifact = "io.grpc:protoc-gen-grpc-java:1.49.0@exe" 44 | } 45 | id("grpckt") { 46 | artifact = "io.grpc:protoc-gen-grpc-kotlin:1.3.0:jdk8@jar" 47 | } 48 | } 49 | generateProtoTasks { 50 | ofSourceSet("main").forEach { 51 | it.plugins { 52 | id("grpc") 53 | id("grpckt") 54 | } 55 | } 56 | } 57 | } 58 | 59 | java { 60 | sourceCompatibility = JavaVersion.VERSION_11 61 | } 62 | 63 | application { 64 | mainClass.set("io.grpc.examples.helloworld.HelloWorldServerKt") 65 | } 66 | 67 | tasks.register("HelloWorldServer") { 68 | dependsOn("classes") 69 | classpath = sourceSets["main"].runtimeClasspath 70 | mainClass.set("io.grpc.examples.helloworld.HelloWorldServerKt") 71 | } 72 | 73 | val helloWorldServerStartScripts = tasks.register("helloWorldServerStartScripts") { 74 | mainClass.set("io.grpc.examples.helloworld.HelloWorldServerKt") 75 | applicationName = "hello-world-server" 76 | outputDir = tasks.named("startScripts").get().outputDir 77 | classpath = tasks.named("startScripts").get().classpath 78 | } 79 | 80 | tasks.named("startScripts") { 81 | dependsOn(helloWorldServerStartScripts) 82 | } 83 | -------------------------------------------------------------------------------- /analyze/results_analyze.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | if ARGV.empty? 4 | puts 'You need to provide report directory path!' 5 | exit 1 6 | end 7 | 8 | report_directory = ARGV[0] 9 | unless Dir.exist? report_directory 10 | puts "Report directory [#{report_directory}] does not exist." 11 | exit 1 12 | end 13 | 14 | results = Hash.new { |hash, key| hash[key] = {} } 15 | Dir.glob("#{report_directory}/*.report").each do |file| 16 | name = File.basename(file).split(/_bench.report/).first 17 | results[name][:total_time] = File.read(file).scan(/Total:\s*((?:\d|\.)+)/)[0][0].to_f 18 | results[name][:ok_responses] = begin 19 | File.read(file).scan(/\[OK\]\s*(\d+)/)[0][0].to_f 20 | rescue StandardError 21 | 0 22 | end 23 | results[name][:avg_resp_time] = File.read(file).scan(/\s*Average:\s*(.*\w)/)[0][0] 24 | results[name][:_90pct] = File.read(file).scan(/\s*90 % in \s*(.*\w)/)[0][0] 25 | results[name][:_95pct] = File.read(file).scan(/\s*95 % in \s*(.*\w)/)[0][0] 26 | results[name][:_99pct] = File.read(file).scan(/\s*99 % in \s*(.*\w)/)[0][0] 27 | results[name][:req_per_s] = results[name][:ok_responses] / results[name][:total_time] 28 | end 29 | 30 | Dir.glob("#{report_directory}/*.stats").each do |file| 31 | name = File.basename(file).split(/_bench.stats/).first 32 | stats = File 33 | .read(file) 34 | .scan(/([0-9.]+)%\s+([0-9.]+)(\w+)/)[0..-2] # ignore the last sample, not very reliable 35 | .map { |cpu, memory, mem_unit| [cpu.to_f, memory.to_f * (mem_unit == 'GiB' ? 1024 : 1)] } 36 | .reject { |cpu, _mem| cpu < 1 } 37 | .transpose 38 | 39 | results[name][:avg_mem_unit] = 'MiB' 40 | 41 | if stats[0].nil? 42 | puts "Warning: no stats for #{file}" 43 | results[name][:avg_cpu] = 0 44 | results[name][:avg_mem] = 0 45 | else 46 | results[name][:avg_cpu] = stats[0].sum / stats[0].length 47 | results[name][:avg_mem] = stats[1].sum / stats[1].length 48 | end 49 | end 50 | 51 | make_horizontal_line = -> { puts '-' * 137 } 52 | make_data_line = lambda do |*args| 53 | puts "| #{args[0].to_s.ljust(27)} |" \ 54 | "#{args[1].to_s.rjust(8)} |" \ 55 | "#{args[2].to_s.rjust(15)} |" \ 56 | "#{args[3].to_s.rjust(15)} |" \ 57 | "#{args[4].to_s.rjust(15)} |" \ 58 | "#{args[5].to_s.rjust(15)} |" \ 59 | "#{args[6].to_s.rjust(9)} |" \ 60 | "#{args[7].to_s.rjust(14)} |" 61 | end 62 | make_horizontal_line[] 63 | make_data_line['name', 'req/s', 'avg. latency', '90 % in', '95 % in', '99 % in', 'avg. cpu', 'avg. memory'] 64 | make_horizontal_line[] 65 | results.sort_by { |_k, v| v[:req_per_s] }.reverse_each do |name, result| 66 | make_data_line[name, 67 | result[:req_per_s].round(0), 68 | result[:avg_resp_time], 69 | result[:_90pct], 70 | result[:_95pct], 71 | result[:_99pct], 72 | "#{result[:avg_cpu].round(2)}%", 73 | "#{result[:avg_mem].round(2)} #{result[:avg_mem_unit]}"] 74 | end 75 | make_horizontal_line[] 76 | -------------------------------------------------------------------------------- /kotlin_grpc_bench/src/main/kotlin/io/grpc/examples/helloworld/HelloWorldServer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 gRPC authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.grpc.examples.helloworld 18 | 19 | import io.grpc.Server 20 | import io.grpc.ServerBuilder 21 | 22 | import java.io.IOException 23 | import java.util.concurrent.TimeUnit 24 | import java.util.logging.Logger 25 | import java.util.concurrent.Executors 26 | 27 | class HelloWorldServer(val port: Int) { 28 | val server: Server 29 | 30 | init { 31 | val threads = System.getenv("GRPC_SERVER_CPUS") 32 | var i_threads = Runtime.getRuntime().availableProcessors() 33 | if (threads != null && !threads.isEmpty()) { 34 | i_threads = Integer.parseInt(threads) 35 | } 36 | 37 | var sb = ServerBuilder.forPort(port) 38 | .addService(HelloWorldService()) 39 | 40 | val value = System.getenv().getOrDefault("JVM_EXECUTOR_TYPE", "workStealing") 41 | when (value) { 42 | "direct" -> sb = sb.directExecutor() 43 | "single" -> sb = sb.executor(Executors.newSingleThreadExecutor()) 44 | "fixed" -> sb = sb.executor(Executors.newFixedThreadPool(i_threads)) 45 | "workStealing" -> sb = sb.executor(Executors.newWorkStealingPool(i_threads)) 46 | "cached" -> sb = sb.executor(Executors.newCachedThreadPool()) 47 | } 48 | 49 | server = sb.build() 50 | } 51 | 52 | fun start() { 53 | server.start() 54 | println("Server started, listening on $port") 55 | Runtime.getRuntime().addShutdownHook( 56 | Thread { 57 | println("*** shutting down gRPC server since JVM is shutting down") 58 | this@HelloWorldServer.stop() 59 | println("*** server shut down") 60 | } 61 | ) 62 | } 63 | 64 | private fun stop() { 65 | server.shutdown() 66 | } 67 | 68 | fun blockUntilShutdown() { 69 | server.awaitTermination() 70 | } 71 | 72 | private class HelloWorldService : GreeterGrpcKt.GreeterCoroutineImplBase() { 73 | override suspend fun sayHello(request: HelloRequest) = HelloReply 74 | .newBuilder() 75 | .setResponse(request.getRequest()) 76 | .build() 77 | } 78 | } 79 | 80 | fun main() { 81 | val port = 50051 82 | val server = HelloWorldServer(port) 83 | server.start() 84 | server.blockUntilShutdown() 85 | } 86 | -------------------------------------------------------------------------------- /java_micronaut_workstealing_bench/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if %ERRORLEVEL% equ 0 goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if %ERRORLEVEL% equ 0 goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | set EXIT_CODE=%ERRORLEVEL% 84 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 85 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 86 | exit /b %EXIT_CODE% 87 | 88 | :mainEnd 89 | if "%OS%"=="Windows_NT" endlocal 90 | 91 | :omega 92 | -------------------------------------------------------------------------------- /java_aot_bench/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if %ERRORLEVEL% equ 0 goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if %ERRORLEVEL% equ 0 goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | set EXIT_CODE=%ERRORLEVEL% 84 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 85 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 86 | exit /b %EXIT_CODE% 87 | 88 | :mainEnd 89 | if "%OS%"=="Windows_NT" endlocal 90 | 91 | :omega 92 | -------------------------------------------------------------------------------- /kotlin_grpc_bench/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if %ERRORLEVEL% equ 0 goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if %ERRORLEVEL% equ 0 goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | set EXIT_CODE=%ERRORLEVEL% 84 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 85 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 86 | exit /b %EXIT_CODE% 87 | 88 | :mainEnd 89 | if "%OS%"=="Windows_NT" endlocal 90 | 91 | :omega 92 | --------------------------------------------------------------------------------