| David Reiss | ea2cba8 | 2009-03-30 21:35:00 +0000 | [diff] [blame] | 1 | # |
| 2 | # Licensed to the Apache Software Foundation (ASF) under one |
| 3 | # or more contributor license agreements. See the NOTICE file |
| 4 | # distributed with this work for additional information |
| 5 | # regarding copyright ownership. The ASF licenses this file |
| 6 | # to you under the Apache License, Version 2.0 (the |
| 7 | # "License"); you may not use this file except in compliance |
| 8 | # with the License. You may obtain a copy of the License at |
| 9 | # |
| 10 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | # |
| 12 | # Unless required by applicable law or agreed to in writing, |
| 13 | # software distributed under the License is distributed on an |
| 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | # KIND, either express or implied. See the License for the |
| 16 | # specific language governing permissions and limitations |
| 17 | # under the License. |
| 18 | # |
| 19 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 20 | THRIFT_BENCHMARK_SKIP_NATIVE = ENV.fetch('THRIFT_BENCHMARK_SKIP_NATIVE', '').match?(/\A(?:1|true|yes|on)\z/i) |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 21 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 22 | lib_path = File.expand_path('../../../lib/rb/lib', __dir__) |
| 23 | ext_path = File.expand_path('../../../lib/rb/ext', __dir__) |
| 24 | |
| 25 | $LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path) |
| 26 | |
| 27 | if THRIFT_BENCHMARK_SKIP_NATIVE |
| 28 | $LOAD_PATH.delete(ext_path) |
| 29 | else |
| 30 | $LOAD_PATH.unshift ext_path unless $LOAD_PATH.include?(ext_path) |
| 31 | end |
| 32 | |
| 33 | if THRIFT_BENCHMARK_SKIP_NATIVE |
| 34 | File.open(File::NULL, 'w') do |null_stdout| |
| 35 | original_stdout = $stdout |
| 36 | $stdout = null_stdout |
| 37 | begin |
| 38 | require 'thrift' |
| 39 | ensure |
| 40 | $stdout = original_stdout |
| 41 | end |
| 42 | end |
| 43 | else |
| 44 | require 'thrift' |
| 45 | end |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 46 | |
| 47 | require 'benchmark' |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 48 | require 'json' |
| 49 | require 'optparse' |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 50 | |
| 51 | # require 'ruby-debug' |
| 52 | # require 'ruby-prof' |
| 53 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 54 | require File.expand_path('../fixtures/structs', __dir__) |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 55 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 56 | module ProtocolBenchmark |
| 57 | DEFAULT_LARGE_RUNS = 1 |
| 58 | DEFAULT_SMALL_RUNS = 10_000 |
| 59 | ALL_SCENARIO_IDS = %w[ |
| 60 | rb-bin-write-large rb-bin-read-large c-bin-write-large c-bin-read-large |
| 61 | rb-cmp-write-large rb-cmp-read-large rb-json-write-large rb-json-read-large |
| 62 | rb-bin-write-small rb-bin-read-small c-bin-write-small c-bin-read-small |
| 63 | rb-cmp-write-small rb-cmp-read-small rb-json-write-small rb-json-read-small |
| 64 | hdr-bin-write-small hdr-bin-read-small hdr-cmp-write-small hdr-cmp-read-small |
| 65 | hdr-zlib-write-small hdr-zlib-read-small |
| 66 | ].freeze |
| 67 | NATIVE_SCENARIO_IDS = %w[ |
| 68 | c-bin-write-large c-bin-read-large c-bin-write-small c-bin-read-small |
| 69 | ].freeze |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 70 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 71 | module_function |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 72 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 73 | def parse_run_options(argv = ARGV, env: ENV) |
| 74 | options = { |
| 75 | large_runs: env.fetch('THRIFT_BENCHMARK_LARGE_RUNS', DEFAULT_LARGE_RUNS), |
| 76 | small_runs: env.fetch('THRIFT_BENCHMARK_SMALL_RUNS', DEFAULT_SMALL_RUNS), |
| 77 | scenarios: env['THRIFT_BENCHMARK_SCENARIOS'], |
| 78 | json: false |
| 79 | } |
| Dmytro Shteflyuk | 67bfb29 | 2026-01-28 11:23:50 -0500 | [diff] [blame] | 80 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 81 | OptionParser.new do |parser| |
| 82 | parser.on('--large-runs N', Integer) { |value| options[:large_runs] = value } |
| 83 | parser.on('--small-runs N', Integer) { |value| options[:small_runs] = value } |
| 84 | parser.on('--scenarios IDS', String) { |value| options[:scenarios] = value } |
| 85 | parser.on('--json') { options[:json] = true } |
| 86 | end.parse!(argv.dup) |
| Dmytro Shteflyuk | 67bfb29 | 2026-01-28 11:23:50 -0500 | [diff] [blame] | 87 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 88 | { |
| 89 | large_runs: normalize_run_count(options[:large_runs], 'large runs'), |
| 90 | small_runs: normalize_run_count(options[:small_runs], 'small runs'), |
| 91 | scenarios: normalize_scenarios(options[:scenarios]), |
| 92 | json: options[:json] |
| 93 | } |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 94 | end |
| Dmytro Shteflyuk | f5c80a4 | 2026-03-08 19:09:43 -0400 | [diff] [blame] | 95 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 96 | def normalize_run_count(value, name) |
| 97 | count = value.is_a?(String) ? Integer(value, 10) : Integer(value) |
| 98 | raise ArgumentError, "#{name} must be >= 1" if count < 1 |
| 99 | |
| 100 | count |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 101 | end |
| Dmytro Shteflyuk | f5c80a4 | 2026-03-08 19:09:43 -0400 | [diff] [blame] | 102 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 103 | def large_run_label(count) |
| 104 | count == 1 ? 'once' : "#{count} times" |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 105 | end |
| Dmytro Shteflyuk | f5c80a4 | 2026-03-08 19:09:43 -0400 | [diff] [blame] | 106 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 107 | def normalize_scenarios(value) |
| 108 | return nil if value.nil? |
| 109 | |
| 110 | scenario_ids = value.split(/[\s,]+/).filter_map do |scenario_id| |
| 111 | normalized = scenario_id.strip |
| 112 | normalized unless normalized.empty? |
| 113 | end |
| 114 | |
| 115 | scenario_ids.empty? ? nil : scenario_ids.uniq |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 116 | end |
| Dmytro Shteflyuk | f5c80a4 | 2026-03-08 19:09:43 -0400 | [diff] [blame] | 117 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 118 | def binary_protocol_builder(accelerated: false) |
| 119 | protocol_class = |
| 120 | if accelerated && native_available? |
| 121 | Thrift::BinaryProtocolAccelerated |
| 122 | else |
| 123 | Thrift::BinaryProtocol |
| 124 | end |
| 125 | |
| 126 | lambda do |buffer = nil| |
| 127 | transport = Thrift::MemoryBufferTransport.new(buffer) |
| 128 | [transport, protocol_class.new(transport)] |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 129 | end |
| 130 | end |
| Dmytro Shteflyuk | f5c80a4 | 2026-03-08 19:09:43 -0400 | [diff] [blame] | 131 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 132 | def compact_protocol_builder |
| 133 | lambda do |buffer = nil| |
| 134 | transport = Thrift::MemoryBufferTransport.new(buffer) |
| 135 | [transport, Thrift::CompactProtocol.new(transport)] |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 136 | end |
| 137 | end |
| Dmytro Shteflyuk | f5c80a4 | 2026-03-08 19:09:43 -0400 | [diff] [blame] | 138 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 139 | def json_protocol_builder |
| 140 | lambda do |buffer = nil| |
| 141 | transport = Thrift::MemoryBufferTransport.new(buffer) |
| 142 | [transport, Thrift::JsonProtocol.new(transport)] |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 143 | end |
| 144 | end |
| Dmytro Shteflyuk | f5c80a4 | 2026-03-08 19:09:43 -0400 | [diff] [blame] | 145 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 146 | def header_protocol_builder(default_protocol:, zlib: false) |
| 147 | lambda do |buffer = nil| |
| 148 | transport = Thrift::MemoryBufferTransport.new(buffer) |
| 149 | protocol = Thrift::HeaderProtocol.new(transport, nil, default_protocol) |
| 150 | protocol.add_transform(Thrift::HeaderTransformID::ZLIB) if zlib |
| 151 | [transport, protocol] |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 152 | end |
| 153 | end |
| Dmytro Shteflyuk | 67bfb29 | 2026-01-28 11:23:50 -0500 | [diff] [blame] | 154 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 155 | def serialize(builder, value, count: 1) |
| 156 | transport, protocol = builder.call |
| 157 | |
| 158 | count.times do |
| 159 | value.write(protocol) |
| 160 | flush(protocol) |
| 161 | end |
| 162 | |
| 163 | transport.read(transport.available) |
| 164 | end |
| 165 | |
| 166 | def deserialize(builder, struct_class, payload, count: 1) |
| 167 | _transport, protocol = builder.call(payload.dup) |
| 168 | value = nil |
| 169 | |
| 170 | count.times do |
| 171 | value = struct_class.new |
| 172 | value.read(protocol) |
| 173 | end |
| 174 | |
| 175 | value |
| 176 | end |
| 177 | |
| 178 | def write(builder, value, count: 1) |
| 179 | _transport, protocol = builder.call |
| 180 | |
| 181 | count.times do |
| 182 | value.write(protocol) |
| 183 | flush(protocol) |
| Dmytro Shteflyuk | 67bfb29 | 2026-01-28 11:23:50 -0500 | [diff] [blame] | 184 | end |
| 185 | end |
| 186 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 187 | def flush(protocol) |
| 188 | protocol.trans.flush if protocol.trans.is_a?(Thrift::HeaderTransport) |
| 189 | end |
| 190 | |
| 191 | def build_sample_structs |
| 192 | ooe = Fixtures::Structs::OneOfEach.new |
| 193 | ooe.im_true = true |
| 194 | ooe.im_false = false |
| 195 | ooe.a_bite = -42 |
| 196 | ooe.integer16 = 27_000 |
| 197 | ooe.integer32 = 1 << 24 |
| 198 | ooe.integer64 = 6000 * 1000 * 1000 |
| 199 | ooe.double_precision = Math::PI |
| 200 | ooe.some_characters = 'Debug THIS!' |
| 201 | ooe.zomg_unicode = "\u00D7\n\a\t" |
| 202 | |
| 203 | n1 = Fixtures::Structs::Nested1.new |
| 204 | n1.a_list = [ooe, ooe, ooe, ooe] |
| 205 | n1.i32_map = {1234 => ooe, 46_345 => ooe, -34_264 => ooe} |
| 206 | n1.i64_map = {43_534_986_783_945 => ooe, -32_434_639_875_122 => ooe} |
| 207 | n1.dbl_map = {324.65469834 => ooe, -9_458_672_340.49868 => ooe} |
| 208 | n1.str_map = {'sdoperuix' => ooe, 'pwoerxclmn' => ooe} |
| 209 | |
| 210 | n2 = Fixtures::Structs::Nested2.new |
| 211 | n2.a_list = [n1, n1, n1, n1, n1] |
| 212 | n2.i32_map = {398_345 => n1, -2345 => n1, 12_312 => n1} |
| 213 | n2.i64_map = {2_349_843_765_934 => n1, -123_234_985_495 => n1, 0 => n1} |
| 214 | n2.dbl_map = {23_345_345.38927834 => n1, -1_232_349.5489345 => n1, -234_984_574.23498726 => n1} |
| 215 | n2.str_map = {'' => n1, 'sdflkertpioux' => n1, 'sdfwepwdcjpoi' => n1} |
| 216 | |
| 217 | n3 = Fixtures::Structs::Nested3.new |
| 218 | n3.a_list = [n2, n2, n2, n2, n2] |
| 219 | n3.i32_map = {398_345 => n2, -2345 => n2, 12_312 => n2} |
| 220 | n3.i64_map = {2_349_843_765_934 => n2, -123_234_985_495 => n2, 0 => n2} |
| 221 | n3.dbl_map = {23_345_345.38927834 => n2, -1_232_349.5489345 => n2, -234_984_574.23498726 => n2} |
| 222 | n3.str_map = {'' => n2, 'sdflkertpioux' => n2, 'sdfwepwdcjpoi' => n2} |
| 223 | |
| 224 | n4 = Fixtures::Structs::Nested4.new |
| 225 | n4.a_list = [n3] |
| 226 | n4.i32_map = {-2345 => n3} |
| 227 | n4.i64_map = {2_349_843_765_934 => n3} |
| 228 | n4.dbl_map = {-1_232_349.5489345 => n3} |
| 229 | n4.str_map = {'' => n3} |
| 230 | |
| 231 | [ooe, n4] |
| 232 | end |
| 233 | |
| 234 | def scenario(id, label, &job) |
| 235 | {id: id, label: label, job: job} |
| 236 | end |
| 237 | |
| 238 | def native_available? |
| 239 | Thrift.const_defined?(:BinaryProtocolAccelerated, false) |
| 240 | end |
| 241 | |
| 242 | def with_scenario_selected(requested_ids, *ids) |
| 243 | selected = requested_ids.nil? || ids.any? { |id| requested_ids.include?(id) } |
| 244 | return false unless selected |
| 245 | return true unless block_given? |
| 246 | |
| 247 | yield |
| 248 | end |
| 249 | |
| 250 | def select_scenarios(scenarios, requested_ids, native_available:) |
| 251 | return scenarios if requested_ids.nil? |
| 252 | |
| 253 | unknown_ids = requested_ids - ALL_SCENARIO_IDS |
| 254 | raise ArgumentError, "unknown scenarios: #{unknown_ids.join(', ')}" if unknown_ids.any? |
| 255 | |
| 256 | unavailable_native_ids = requested_ids & NATIVE_SCENARIO_IDS unless native_available |
| 257 | if unavailable_native_ids&.any? |
| 258 | raise ArgumentError, "native-only scenarios unavailable without thrift_native: #{unavailable_native_ids.join(', ')}" |
| 259 | end |
| 260 | |
| 261 | scenarios.select { |entry| requested_ids.include?(entry[:id]) } |
| 262 | end |
| 263 | |
| 264 | def build_scenarios(large_runs:, small_runs:, scenario_ids: nil) |
| 265 | unknown_ids = scenario_ids ? scenario_ids - ALL_SCENARIO_IDS : [] |
| 266 | raise ArgumentError, "unknown scenarios: #{unknown_ids.join(', ')}" if unknown_ids.any? |
| 267 | |
| 268 | one_of_each, nested4 = build_sample_structs |
| 269 | |
| 270 | ruby_binary = binary_protocol_builder |
| 271 | ruby_compact = compact_protocol_builder |
| 272 | ruby_json = json_protocol_builder |
| 273 | accelerated_binary = binary_protocol_builder(accelerated: true) |
| 274 | header_binary = header_protocol_builder(default_protocol: Thrift::HeaderSubprotocolID::BINARY) |
| 275 | header_compact = header_protocol_builder(default_protocol: Thrift::HeaderSubprotocolID::COMPACT) |
| 276 | header_zlib = header_protocol_builder(default_protocol: Thrift::HeaderSubprotocolID::BINARY, zlib: true) |
| 277 | |
| 278 | native_available = native_available? |
| 279 | unavailable_native_ids = native_available ? [] : (scenario_ids || []) & NATIVE_SCENARIO_IDS |
| 280 | if unavailable_native_ids.any? |
| 281 | raise ArgumentError, "native-only scenarios unavailable without thrift_native: #{unavailable_native_ids.join(', ')}" |
| 282 | end |
| 283 | |
| 284 | native_scenarios = [] |
| 285 | |
| 286 | ruby_large_payload = with_scenario_selected(scenario_ids, 'rb-bin-read-large') { serialize(ruby_binary, nested4, count: large_runs) } |
| 287 | ruby_small_payload = with_scenario_selected(scenario_ids, 'rb-bin-read-small') { serialize(ruby_binary, one_of_each, count: small_runs) } |
| 288 | compact_large_payload = with_scenario_selected(scenario_ids, 'rb-cmp-read-large') { serialize(ruby_compact, nested4, count: large_runs) } |
| 289 | compact_small_payload = with_scenario_selected(scenario_ids, 'rb-cmp-read-small') { serialize(ruby_compact, one_of_each, count: small_runs) } |
| 290 | json_large_payload = with_scenario_selected(scenario_ids, 'rb-json-read-large') { serialize(ruby_json, nested4, count: large_runs) } |
| 291 | json_small_payload = with_scenario_selected(scenario_ids, 'rb-json-read-small') { serialize(ruby_json, one_of_each, count: small_runs) } |
| 292 | header_binary_payload = with_scenario_selected(scenario_ids, 'hdr-bin-read-small') { serialize(header_binary, one_of_each, count: small_runs) } |
| 293 | header_compact_payload = with_scenario_selected(scenario_ids, 'hdr-cmp-read-small') { serialize(header_compact, one_of_each, count: small_runs) } |
| 294 | header_zlib_payload = with_scenario_selected(scenario_ids, 'hdr-zlib-read-small') { serialize(header_zlib, one_of_each, count: small_runs) } |
| 295 | |
| 296 | if native_available |
| 297 | accelerated_large_payload = with_scenario_selected(scenario_ids, 'c-bin-read-large') { serialize(accelerated_binary, nested4, count: large_runs) } |
| 298 | accelerated_small_payload = with_scenario_selected(scenario_ids, 'c-bin-read-small') { serialize(accelerated_binary, one_of_each, count: small_runs) } |
| 299 | |
| 300 | native_scenarios = [ |
| 301 | scenario('c-bin-write-large', "c binary write large (1MB) structure #{large_run_label(large_runs)}") { write(accelerated_binary, nested4, count: large_runs) }, |
| 302 | scenario('c-bin-read-large', "c binary read large (1MB) structure #{large_run_label(large_runs)}") { deserialize(accelerated_binary, Fixtures::Structs::Nested4, accelerated_large_payload, count: large_runs) }, |
| 303 | scenario('c-bin-write-small', "c binary write #{small_runs} small structures") { write(accelerated_binary, one_of_each, count: small_runs) }, |
| 304 | scenario('c-bin-read-small', "c binary read #{small_runs} small structures") { deserialize(accelerated_binary, Fixtures::Structs::OneOfEach, accelerated_small_payload, count: small_runs) } |
| 305 | ] |
| 306 | elsif !THRIFT_BENCHMARK_SKIP_NATIVE && with_scenario_selected(scenario_ids, *NATIVE_SCENARIO_IDS) |
| 307 | warn 'Skipping accelerated binary protocol benchmarks: thrift_native extension is unavailable.' |
| 308 | end |
| 309 | |
| 310 | scenario_list = [ |
| 311 | scenario('rb-bin-write-large', "ruby binary write large (1MB) structure #{large_run_label(large_runs)}") { write(ruby_binary, nested4, count: large_runs) }, |
| 312 | scenario('rb-bin-read-large', "ruby binary read large (1MB) structure #{large_run_label(large_runs)}") { deserialize(ruby_binary, Fixtures::Structs::Nested4, ruby_large_payload, count: large_runs) }, |
| 313 | *native_scenarios.first(2), |
| 314 | scenario('rb-cmp-write-large', "ruby compact write large (1MB) structure #{large_run_label(large_runs)}") { write(ruby_compact, nested4, count: large_runs) }, |
| 315 | scenario('rb-cmp-read-large', "ruby compact read large (1MB) structure #{large_run_label(large_runs)}") { deserialize(ruby_compact, Fixtures::Structs::Nested4, compact_large_payload, count: large_runs) }, |
| 316 | scenario('rb-json-write-large', "ruby json write large (1MB) structure #{large_run_label(large_runs)}") { write(ruby_json, nested4, count: large_runs) }, |
| 317 | scenario('rb-json-read-large', "ruby json read large (1MB) structure #{large_run_label(large_runs)}") { deserialize(ruby_json, Fixtures::Structs::Nested4, json_large_payload, count: large_runs) }, |
| 318 | scenario('rb-bin-write-small', "ruby binary write #{small_runs} small structures") { write(ruby_binary, one_of_each, count: small_runs) }, |
| 319 | scenario('rb-bin-read-small', "ruby binary read #{small_runs} small structures") { deserialize(ruby_binary, Fixtures::Structs::OneOfEach, ruby_small_payload, count: small_runs) }, |
| 320 | *native_scenarios.drop(2), |
| 321 | scenario('rb-cmp-write-small', "ruby compact write #{small_runs} small structures") { write(ruby_compact, one_of_each, count: small_runs) }, |
| 322 | scenario('rb-cmp-read-small', "ruby compact read #{small_runs} small structures") { deserialize(ruby_compact, Fixtures::Structs::OneOfEach, compact_small_payload, count: small_runs) }, |
| 323 | scenario('rb-json-write-small', "ruby json write #{small_runs} small structures") { write(ruby_json, one_of_each, count: small_runs) }, |
| 324 | scenario('rb-json-read-small', "ruby json read #{small_runs} small structures") { deserialize(ruby_json, Fixtures::Structs::OneOfEach, json_small_payload, count: small_runs) }, |
| 325 | scenario('hdr-bin-write-small', "header binary write #{small_runs} small structures") { write(header_binary, one_of_each, count: small_runs) }, |
| 326 | scenario('hdr-bin-read-small', "header binary read #{small_runs} small structures") { deserialize(header_binary, Fixtures::Structs::OneOfEach, header_binary_payload, count: small_runs) }, |
| 327 | scenario('hdr-cmp-write-small', "header compact write #{small_runs} small structures") { write(header_compact, one_of_each, count: small_runs) }, |
| 328 | scenario('hdr-cmp-read-small', "header compact read #{small_runs} small structures") { deserialize(header_compact, Fixtures::Structs::OneOfEach, header_compact_payload, count: small_runs) }, |
| 329 | scenario('hdr-zlib-write-small', "header zlib write #{small_runs} small structures") { write(header_zlib, one_of_each, count: small_runs) }, |
| 330 | scenario('hdr-zlib-read-small', "header zlib read #{small_runs} small structures") { deserialize(header_zlib, Fixtures::Structs::OneOfEach, header_zlib_payload, count: small_runs) } |
| 331 | ] |
| 332 | |
| 333 | select_scenarios(scenario_list, scenario_ids, native_available: native_available) |
| 334 | end |
| 335 | |
| 336 | def measure_job(job, label: '') |
| 337 | result = Benchmark.measure(label, &job) |
| 338 | { |
| 339 | user: result.utime, |
| 340 | system: result.stime, |
| 341 | total: result.total, |
| 342 | real: result.real |
| 343 | } |
| 344 | end |
| 345 | |
| 346 | def warm_up_scenarios(scenarios) |
| 347 | scenarios.each { |entry| measure_job(entry[:job]) } |
| 348 | end |
| 349 | |
| 350 | def benchmark_scenarios(scenarios) |
| 351 | scenarios.map do |entry| |
| 352 | GC.start |
| 353 | { |
| 354 | id: entry[:id], |
| 355 | label: entry[:label], |
| 356 | benchmark: measure_job(entry[:job], label: entry[:label]) |
| 357 | } |
| Dmytro Shteflyuk | 67bfb29 | 2026-01-28 11:23:50 -0500 | [diff] [blame] | 358 | end |
| 359 | end |
| 360 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 361 | def run(large_runs: DEFAULT_LARGE_RUNS, small_runs: DEFAULT_SMALL_RUNS, scenarios: nil, json: false) |
| 362 | scenario_list = build_scenarios(large_runs: large_runs, small_runs: small_runs, scenario_ids: scenarios) |
| 363 | |
| 364 | if json |
| 365 | warm_up_scenarios(scenario_list) |
| 366 | |
| 367 | puts JSON.generate( |
| 368 | config: { |
| 369 | large_runs: large_runs, |
| 370 | small_runs: small_runs, |
| 371 | scenarios: scenario_list.map { |entry| entry[:id] }, |
| 372 | skip_native: THRIFT_BENCHMARK_SKIP_NATIVE, |
| 373 | native_available: native_available? |
| 374 | }, |
| 375 | results: benchmark_scenarios(scenario_list) |
| 376 | ) |
| 377 | return |
| 378 | end |
| 379 | |
| 380 | Benchmark.bmbm do |x| |
| 381 | scenario_list.each do |entry| |
| 382 | x.report(entry[:label], &entry[:job]) |
| 383 | end |
| Dmytro Shteflyuk | 67bfb29 | 2026-01-28 11:23:50 -0500 | [diff] [blame] | 384 | end |
| 385 | end |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 386 | end |
| Dmytro Shteflyuk | 67bfb29 | 2026-01-28 11:23:50 -0500 | [diff] [blame] | 387 | |
| Dmytro Shteflyuk | 82754d2 | 2026-03-27 12:39:51 -0400 | [diff] [blame^] | 388 | if $PROGRAM_NAME == __FILE__ |
| 389 | begin |
| 390 | ProtocolBenchmark.run(**ProtocolBenchmark.parse_run_options) |
| 391 | rescue OptionParser::ParseError, ArgumentError => e |
| 392 | warn e.message |
| 393 | exit 1 |
| Dmytro Shteflyuk | 67bfb29 | 2026-01-28 11:23:50 -0500 | [diff] [blame] | 394 | end |
| Kevin Clark | 4bd8916 | 2008-07-08 00:47:49 +0000 | [diff] [blame] | 395 | end |