|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +require "benchmark_driver" |
| 4 | + |
| 5 | +# This is the benchmark to measure the impact of promoting some HTTP headers |
| 6 | +# to Env fields. That should reduce the payload size as well as improve the rack env building |
| 7 | +# speed. |
| 8 | + |
| 9 | +protobuf = <<~CODE |
| 10 | + require "google/protobuf" |
| 11 | +
|
| 12 | + Google::Protobuf::DescriptorPool.generated_pool.build do |
| 13 | + add_file("rpc-bench.proto", syntax: :proto3) do |
| 14 | + add_message "anycable_bench.Env" do |
| 15 | + optional :path, :string, 1 |
| 16 | + map :headers, :string, :string, 2 |
| 17 | + end |
| 18 | + end |
| 19 | +
|
| 20 | + add_file("rpc-bench.proto", syntax: :proto3) do |
| 21 | + add_message "anycable_bench.FlatEnv" do |
| 22 | + optional :path, :string, 1 |
| 23 | + optional :query, :string, 2 |
| 24 | + optional :host, :string, 3 |
| 25 | + optional :port, :string, 4 |
| 26 | + optional :scheme, :string, 5 |
| 27 | + optional :cookie, :string, 6 |
| 28 | + optional :origin, :string, 7 |
| 29 | + optional :remote_addr, :string, 8 |
| 30 | + map :headers, :string, :string, 9 |
| 31 | + end |
| 32 | + end |
| 33 | + end |
| 34 | +
|
| 35 | + Env = Google::Protobuf::DescriptorPool.generated_pool.lookup("anycable_bench.Env").msgclass |
| 36 | + FlatEnv = Google::Protobuf::DescriptorPool.generated_pool.lookup("anycable_bench.FlatEnv").msgclass |
| 37 | +
|
| 38 | + message = Env.new( |
| 39 | + path: "/cable?token=secret", |
| 40 | + headers: { |
| 41 | + "cookie" => "session_id=123456;", |
| 42 | + "remote_addr" => "192.1.1.42", |
| 43 | + "origin" => "anycable.io", |
| 44 | + "x-api-token" => "api-token-2020" |
| 45 | + } |
| 46 | + ) |
| 47 | +
|
| 48 | + payload = Env.encode(message) |
| 49 | +
|
| 50 | + message2 = FlatEnv.new( |
| 51 | + path: "/cable", |
| 52 | + query: "?token=secret", |
| 53 | + port: "80", |
| 54 | + scheme: "ws://", |
| 55 | + host: "ws.anycable.io", |
| 56 | + cookie: "session_id=123456;", |
| 57 | + origin: "anycable.io", |
| 58 | + remote_addr: "192.1.1.42", |
| 59 | + headers: { |
| 60 | + "x-api-token" => "api-token-2020" |
| 61 | + } |
| 62 | + ) |
| 63 | +
|
| 64 | + payload2 = FlatEnv.encode(message2) |
| 65 | +
|
| 66 | + def build_rack(rpc_env) |
| 67 | + uri = URI.parse(rpc_env.path) |
| 68 | +
|
| 69 | + env = {} |
| 70 | + env.merge!( |
| 71 | + "PATH_INFO" => uri.path, |
| 72 | + "QUERY_STRING" => uri.query, |
| 73 | + "SERVER_NAME" => uri.host, |
| 74 | + "SERVER_PORT" => uri.port.to_s, |
| 75 | + "HTTP_HOST" => uri.host, |
| 76 | + "REMOTE_ADDR" => rpc_env.headers.delete("remote_addr"), |
| 77 | + "rack.url_scheme" => uri.scheme |
| 78 | + ) |
| 79 | +
|
| 80 | + env.merge!(build_headers(rpc_env.headers)) |
| 81 | + end |
| 82 | +
|
| 83 | + def build_rack2(rpc_env) |
| 84 | + env = {} |
| 85 | + env.merge!( |
| 86 | + "PATH_INFO" => rpc_env.path, |
| 87 | + "QUERY_STRING" => rpc_env.query, |
| 88 | + "SERVER_NAME" => rpc_env.host, |
| 89 | + "SERVER_PORT" => rpc_env.port, |
| 90 | + "HTTP_HOST" => rpc_env.host, |
| 91 | + "REMOTE_ADDR" => rpc_env.remote_addr, |
| 92 | + "rack.url_scheme" => rpc_env.scheme |
| 93 | + ) |
| 94 | +
|
| 95 | + env.merge!(build_headers(rpc_env.headers)) |
| 96 | + end |
| 97 | +
|
| 98 | + def build_headers(headers) |
| 99 | + headers.each_with_object({}) do |(k, v), obj| |
| 100 | + k = k.upcase |
| 101 | + k.tr!("-", "_") |
| 102 | + obj["HTTP_\#{k}"] = v |
| 103 | + end |
| 104 | + end |
| 105 | +CODE |
| 106 | + |
| 107 | +Benchmark.driver do |x| |
| 108 | + x.prelude %( |
| 109 | + #{protobuf} |
| 110 | + ) |
| 111 | + |
| 112 | + x.report "#decode (baseline)", %{ |
| 113 | + Env.decode(payload) |
| 114 | + } |
| 115 | + |
| 116 | + x.report "#decode (flatten)", %{ |
| 117 | + FlatEnv.decode(payload2) |
| 118 | + } |
| 119 | +end |
| 120 | + |
| 121 | +Benchmark.driver do |x| |
| 122 | + x.prelude %( |
| 123 | + #{protobuf} |
| 124 | + ) |
| 125 | + |
| 126 | + x.report "#build_rack (baseline)", %( |
| 127 | + build_rack message |
| 128 | + ) |
| 129 | + |
| 130 | + x.report "#build_rack (flatten)", %( |
| 131 | + build_rack2 message2 |
| 132 | + ) |
| 133 | +end |
| 134 | + |
| 135 | +Benchmark.driver do |x| |
| 136 | + x.prelude %( |
| 137 | + #{protobuf} |
| 138 | + ) |
| 139 | + |
| 140 | + x.report "#decode + #build_rack (baseline)", %{ |
| 141 | + build_rack Env.decode(payload) |
| 142 | + } |
| 143 | + |
| 144 | + x.report "#decode + #build_rack (flatten)", %{ |
| 145 | + build_rack2 FlatEnv.decode(payload2) |
| 146 | + } |
| 147 | +end |
0 commit comments