Skip to content

Conversation

@bengl
Copy link
Contributor

@bengl bengl commented Jan 15, 2026

What does this PR do?

A brief description of the change being made with this pull request.

Motivation

What inspired you to submit this pull request?

Additional Notes

Anything else we should know when reviewing?

How to test the change?

Describe here in detail how the change can be validated.

@pr-commenter
Copy link

pr-commenter bot commented Jan 15, 2026

Benchmarks

Comparison

Benchmark execution time: 2026-01-29 20:06:32

Comparing candidate commit 210da31 in PR branch bengl/change-buffer with baseline commit 488418a in branch main.

Found 8 performance improvements and 13 performance regressions! Performance is the same for 36 metrics, 2 unstable metrics.

scenario:benching deserializing traces from msgpack to their internal representation

  • 🟥 execution_time [+13.349ms; +14.063ms] or [+27.337%; +28.799%]

scenario:benching serializing traces from their internal representation to msgpack

  • 🟩 execution_time [-754.823µs; -742.892µs] or [-5.157%; -5.076%]

scenario:credit_card/is_card_number/37828224631000521389798

  • 🟥 execution_time [+8.016µs; +8.059µs] or [+17.774%; +17.868%]
  • 🟥 throughput [-3364253.738op/s; -3343640.569op/s] or [-15.173%; -15.080%]

scenario:credit_card/is_card_number/x371413321323331

  • 🟥 execution_time [+399.309ns; +402.407ns] or [+6.614%; +6.665%]
  • 🟥 throughput [-10355108.680op/s; -10272410.230op/s] or [-6.252%; -6.202%]

scenario:credit_card/is_card_number_no_luhn/ 378282246310005

  • 🟥 execution_time [+5.893µs; +5.953µs] or [+11.111%; +11.224%]
  • 🟥 throughput [-1902548.735op/s; -1885181.919op/s] or [-10.090%; -9.998%]

scenario:credit_card/is_card_number_no_luhn/378282246310005

  • 🟥 execution_time [+5.788µs; +5.844µs] or [+11.619%; +11.732%]
  • 🟥 throughput [-2107712.645op/s; -2089345.211op/s] or [-10.500%; -10.408%]

scenario:credit_card/is_card_number_no_luhn/37828224631000521389798

  • 🟥 execution_time [+7.942µs; +7.988µs] or [+17.584%; +17.684%]
  • 🟥 throughput [-3330168.668op/s; -3308038.067op/s] or [-15.042%; -14.942%]

scenario:credit_card/is_card_number_no_luhn/x371413321323331

  • 🟥 execution_time [+401.175ns; +403.343ns] or [+6.647%; +6.683%]
  • 🟥 throughput [-10380472.604op/s; -10323564.929op/s] or [-6.265%; -6.231%]

scenario:normalization/normalize_name/normalize_name/Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Lo...

  • 🟩 execution_time [-19.865µs; -19.743µs] or [-9.655%; -9.595%]
  • 🟩 throughput [+516099.379op/s; +519119.532op/s] or [+10.619%; +10.681%]

scenario:normalization/normalize_name/normalize_name/bad-name

  • 🟩 throughput [+2221085.374op/s; +2333241.931op/s] or [+4.149%; +4.358%]

scenario:normalization/normalize_service/normalize_service/A0000000000000000000000000000000000000000000000000...

  • 🟩 execution_time [-41.717µs; -41.235µs] or [-7.769%; -7.679%]
  • 🟩 throughput [+155002.448op/s; +156738.886op/s] or [+8.323%; +8.417%]

scenario:normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters

  • 🟩 execution_time [-22.240µs; -22.176µs] or [-11.714%; -11.681%]
  • 🟩 throughput [+696729.826op/s; +698745.355op/s] or [+13.228%; +13.266%]

Candidate

Candidate benchmark details

Group 1

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
single_flag_killswitch/rules-based execution_time 186.698ns 189.184ns ± 2.060ns 188.785ns ± 1.448ns 190.400ns 193.668ns 195.585ns 196.512ns 4.09% 1.136 1.117 1.09% 0.146ns 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
single_flag_killswitch/rules-based execution_time [188.899ns; 189.470ns] or [-0.151%; +0.151%] None None None

Group 2

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
benching string interning on wordpress profile execution_time 161.644µs 162.114µs ± 0.303µs 162.035µs ± 0.156µs 162.260µs 162.712µs 162.980µs 163.352µs 0.81% 1.206 1.515 0.19% 0.021µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
benching string interning on wordpress profile execution_time [162.072µs; 162.157µs] or [-0.026%; +0.026%] None None None

Group 3

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
write only interface execution_time 1.210µs 3.118µs ± 1.375µs 2.965µs ± 0.026µs 2.990µs 3.117µs 13.529µs 14.574µs 391.48% 7.551 57.329 44.00% 0.097µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
write only interface execution_time [2.927µs; 3.308µs] or [-6.113%; +6.113%] None None None

Group 4

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
normalization/normalize_name/normalize_name/Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Lo... execution_time 185.589µs 185.949µs ± 0.188µs 185.925µs ± 0.127µs 186.065µs 186.289µs 186.448µs 186.623µs 0.38% 0.577 0.498 0.10% 0.013µs 1 200
normalization/normalize_name/normalize_name/Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Lo... throughput 5358398.548op/s 5377811.199op/s ± 5423.387op/s 5378500.973op/s ± 3658.791op/s 5381139.933op/s 5386298.194op/s 5387447.910op/s 5388248.148op/s 0.18% -0.571 0.485 0.10% 383.491op/s 1 200
normalization/normalize_name/normalize_name/bad-name execution_time 17.808µs 17.918µs ± 0.122µs 17.906µs ± 0.029µs 17.935µs 18.004µs 18.106µs 19.490µs 8.85% 10.800 136.231 0.68% 0.009µs 1 200
normalization/normalize_name/normalize_name/bad-name throughput 51308230.530op/s 55813428.796op/s ± 354709.857op/s 55848591.312op/s ± 89379.269op/s 55934918.110op/s 56039240.707op/s 56145236.502op/s 56154590.284op/s 0.55% -10.358 128.579 0.63% 25081.775op/s 1 200
normalization/normalize_name/normalize_name/good execution_time 10.417µs 10.497µs ± 0.032µs 10.496µs ± 0.023µs 10.520µs 10.553µs 10.572µs 10.607µs 1.06% 0.262 0.212 0.31% 0.002µs 1 200
normalization/normalize_name/normalize_name/good throughput 94273700.300op/s 95262095.201op/s ± 291118.470op/s 95271688.043op/s ± 211187.933op/s 95479883.932op/s 95718948.511op/s 95861216.329op/s 95993340.554op/s 0.76% -0.243 0.185 0.30% 20585.184op/s 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
normalization/normalize_name/normalize_name/Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Lo... execution_time [185.923µs; 185.975µs] or [-0.014%; +0.014%] None None None
normalization/normalize_name/normalize_name/Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Lo... throughput [5377059.569op/s; 5378562.828op/s] or [-0.014%; +0.014%] None None None
normalization/normalize_name/normalize_name/bad-name execution_time [17.901µs; 17.935µs] or [-0.094%; +0.094%] None None None
normalization/normalize_name/normalize_name/bad-name throughput [55764269.421op/s; 55862588.170op/s] or [-0.088%; +0.088%] None None None
normalization/normalize_name/normalize_name/good execution_time [10.493µs; 10.502µs] or [-0.042%; +0.042%] None None None
normalization/normalize_name/normalize_name/good throughput [95221748.981op/s; 95302441.421op/s] or [-0.042%; +0.042%] None None None

Group 5

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
benching deserializing traces from msgpack to their internal representation execution_time 62.119ms 62.538ms ± 2.353ms 62.232ms ± 0.048ms 62.281ms 62.468ms 81.203ms 82.103ms 31.93% 7.962 61.549 3.75% 0.166ms 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
benching deserializing traces from msgpack to their internal representation execution_time [62.212ms; 62.864ms] or [-0.521%; +0.521%] None None None

Group 6

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
profile_add_sample2_frames_x1000 execution_time 534.257µs 535.138µs ± 0.354µs 535.111µs ± 0.238µs 535.372µs 535.699µs 536.191µs 536.331µs 0.23% 0.488 0.546 0.07% 0.025µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
profile_add_sample2_frames_x1000 execution_time [535.089µs; 535.187µs] or [-0.009%; +0.009%] None None None

Group 7

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
sdk_test_data/rules-based execution_time 145.203µs 146.958µs ± 1.860µs 146.656µs ± 0.564µs 147.244µs 148.901µs 153.751µs 165.789µs 13.05% 6.362 55.405 1.26% 0.132µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
sdk_test_data/rules-based execution_time [146.701µs; 147.216µs] or [-0.175%; +0.175%] None None None

Group 8

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
concentrator/add_spans_to_concentrator execution_time 10.686ms 10.719ms ± 0.016ms 10.718ms ± 0.010ms 10.728ms 10.742ms 10.762ms 10.804ms 0.80% 1.456 5.329 0.15% 0.001ms 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
concentrator/add_spans_to_concentrator execution_time [10.717ms; 10.721ms] or [-0.021%; +0.021%] None None None

Group 9

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
tags/replace_trace_tags execution_time 2.427µs 2.455µs ± 0.020µs 2.452µs ± 0.008µs 2.459µs 2.514µs 2.522µs 2.528µs 3.12% 2.018 4.219 0.81% 0.001µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
tags/replace_trace_tags execution_time [2.452µs; 2.457µs] or [-0.113%; +0.113%] None None None

Group 10

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
redis/obfuscate_redis_string execution_time 35.035µs 35.641µs ± 1.043µs 35.159µs ± 0.068µs 35.291µs 37.867µs 37.917µs 38.983µs 10.87% 1.708 1.041 2.92% 0.074µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
redis/obfuscate_redis_string execution_time [35.496µs; 35.785µs] or [-0.405%; +0.405%] None None None

Group 11

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
receiver_entry_point/report/2597 execution_time 9.670ms 9.929ms ± 0.058ms 9.930ms ± 0.026ms 9.954ms 10.029ms 10.079ms 10.109ms 1.80% -0.132 2.831 0.58% 0.004ms 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
receiver_entry_point/report/2597 execution_time [9.921ms; 9.937ms] or [-0.081%; +0.081%] None None None

Group 12

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
sql/obfuscate_sql_string execution_time 88.958µs 89.136µs ± 0.142µs 89.115µs ± 0.048µs 89.169µs 89.289µs 89.570µs 90.603µs 1.67% 6.030 56.622 0.16% 0.010µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
sql/obfuscate_sql_string execution_time [89.116µs; 89.156µs] or [-0.022%; +0.022%] None None None

Group 13

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
profile_add_sample_frames_x1000 execution_time 3.994ms 4.000ms ± 0.007ms 3.999ms ± 0.002ms 4.001ms 4.004ms 4.014ms 4.085ms 2.15% 9.590 112.884 0.17% 0.000ms 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
profile_add_sample_frames_x1000 execution_time [3.999ms; 4.001ms] or [-0.024%; +0.024%] None None None

Group 14

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
ip_address/quantize_peer_ip_address_benchmark execution_time 4.952µs 5.034µs ± 0.043µs 5.014µs ± 0.023µs 5.074µs 5.109µs 5.110µs 5.114µs 2.01% 0.467 -1.079 0.84% 0.003µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
ip_address/quantize_peer_ip_address_benchmark execution_time [5.028µs; 5.039µs] or [-0.117%; +0.117%] None None None

Group 15

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
two way interface execution_time 17.772µs 25.095µs ± 9.457µs 18.146µs ± 0.226µs 33.459µs 41.930µs 42.747µs 70.090µs 286.27% 1.147 1.437 37.59% 0.669µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
two way interface execution_time [23.784µs; 26.405µs] or [-5.223%; +5.223%] None None None

Group 16

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
normalization/normalize_service/normalize_service/A0000000000000000000000000000000000000000000000000... execution_time 494.480µs 495.508µs ± 0.886µs 495.408µs ± 0.274µs 495.742µs 496.183µs 496.456µs 506.573µs 2.25% 9.793 119.850 0.18% 0.063µs 1 200
normalization/normalize_service/normalize_service/A0000000000000000000000000000000000000000000000000... throughput 1974048.717op/s 2018136.498op/s ± 3547.886op/s 2018540.293op/s ± 1116.634op/s 2019552.182op/s 2020780.291op/s 2021644.731op/s 2022326.030op/s 0.19% -9.655 117.550 0.18% 250.873op/s 1 200
normalization/normalize_service/normalize_service/Data🐨dog🐶 繋がっ⛰てて execution_time 370.196µs 370.954µs ± 0.923µs 370.860µs ± 0.183µs 371.047µs 371.396µs 372.179µs 379.898µs 2.44% 8.430 76.878 0.25% 0.065µs 1 200
normalization/normalize_service/normalize_service/Data🐨dog🐶 繋がっ⛰てて throughput 2632282.194op/s 2695767.095op/s ± 6569.312op/s 2696438.158op/s ± 1327.212op/s 2697615.906op/s 2699706.267op/s 2700448.804op/s 2701268.903op/s 0.18% -8.371 76.136 0.24% 464.520op/s 1 200
normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters execution_time 167.214µs 167.646µs ± 0.159µs 167.631µs ± 0.100µs 167.738µs 167.943µs 167.995µs 168.090µs 0.27% 0.173 0.006 0.09% 0.011µs 1 200
normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters throughput 5949188.946op/s 5964945.371op/s ± 5650.022op/s 5965472.125op/s ± 3549.990op/s 5968903.470op/s 5973258.168op/s 5979028.592op/s 5980358.001op/s 0.25% -0.168 0.006 0.09% 399.517op/s 1 200
normalization/normalize_service/normalize_service/[empty string] execution_time 37.061µs 37.254µs ± 0.069µs 37.250µs ± 0.045µs 37.298µs 37.373µs 37.409µs 37.438µs 0.50% 0.028 0.021 0.18% 0.005µs 1 200
normalization/normalize_service/normalize_service/[empty string] throughput 26710987.119op/s 26842698.476op/s ± 49547.110op/s 26845715.562op/s ± 32242.919op/s 26874421.138op/s 26922538.501op/s 26957408.068op/s 26982359.218op/s 0.51% -0.017 0.023 0.18% 3503.510op/s 1 200
normalization/normalize_service/normalize_service/test_ASCII execution_time 45.672µs 45.821µs ± 0.105µs 45.813µs ± 0.038µs 45.852µs 45.908µs 45.969µs 47.080µs 2.77% 8.547 99.926 0.23% 0.007µs 1 200
normalization/normalize_service/normalize_service/test_ASCII throughput 21240426.763op/s 21824120.230op/s ± 49256.440op/s 21827894.570op/s ± 18108.859op/s 21844839.145op/s 21868895.126op/s 21884792.926op/s 21895285.069op/s 0.31% -8.349 96.822 0.23% 3482.956op/s 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
normalization/normalize_service/normalize_service/A0000000000000000000000000000000000000000000000000... execution_time [495.385µs; 495.631µs] or [-0.025%; +0.025%] None None None
normalization/normalize_service/normalize_service/A0000000000000000000000000000000000000000000000000... throughput [2017644.795op/s; 2018628.201op/s] or [-0.024%; +0.024%] None None None
normalization/normalize_service/normalize_service/Data🐨dog🐶 繋がっ⛰てて execution_time [370.826µs; 371.082µs] or [-0.034%; +0.034%] None None None
normalization/normalize_service/normalize_service/Data🐨dog🐶 繋がっ⛰てて throughput [2694856.652op/s; 2696677.539op/s] or [-0.034%; +0.034%] None None None
normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters execution_time [167.624µs; 167.668µs] or [-0.013%; +0.013%] None None None
normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters throughput [5964162.332op/s; 5965728.410op/s] or [-0.013%; +0.013%] None None None
normalization/normalize_service/normalize_service/[empty string] execution_time [37.245µs; 37.264µs] or [-0.026%; +0.026%] None None None
normalization/normalize_service/normalize_service/[empty string] throughput [26835831.723op/s; 26849565.229op/s] or [-0.026%; +0.026%] None None None
normalization/normalize_service/normalize_service/test_ASCII execution_time [45.806µs; 45.836µs] or [-0.032%; +0.032%] None None None
normalization/normalize_service/normalize_service/test_ASCII throughput [21817293.761op/s; 21830946.699op/s] or [-0.031%; +0.031%] None None None

Group 17

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
credit_card/is_card_number/ execution_time 3.898µs 3.915µs ± 0.003µs 3.915µs ± 0.002µs 3.917µs 3.920µs 3.922µs 3.923µs 0.20% -0.654 5.225 0.07% 0.000µs 1 200
credit_card/is_card_number/ throughput 254922453.767op/s 255437073.669op/s ± 186691.593op/s 255441700.894op/s ± 104326.500op/s 255541959.955op/s 255724267.325op/s 255789404.391op/s 256532204.886op/s 0.43% 0.669 5.302 0.07% 13201.089op/s 1 200
credit_card/is_card_number/ 3782-8224-6310-005 execution_time 76.711µs 78.437µs ± 0.776µs 78.398µs ± 0.479µs 78.902µs 79.712µs 80.443µs 80.985µs 3.30% 0.349 0.102 0.99% 0.055µs 1 200
credit_card/is_card_number/ 3782-8224-6310-005 throughput 12347902.540op/s 12750362.485op/s ± 125792.633op/s 12755453.492op/s ± 77916.019op/s 12831146.983op/s 12941930.474op/s 13006962.159op/s 13035956.018op/s 2.20% -0.291 0.026 0.98% 8894.882op/s 1 200
credit_card/is_card_number/ 378282246310005 execution_time 70.657µs 72.027µs ± 0.782µs 71.980µs ± 0.524µs 72.517µs 73.440µs 73.896µs 74.566µs 3.59% 0.459 0.170 1.08% 0.055µs 1 200
credit_card/is_card_number/ 378282246310005 throughput 13410982.924op/s 13885267.312op/s ± 150107.743op/s 13892715.835op/s ± 101103.129op/s 13987345.679op/s 14123699.450op/s 14136815.620op/s 14152822.174op/s 1.87% -0.397 0.060 1.08% 10614.220op/s 1 200
credit_card/is_card_number/37828224631 execution_time 3.898µs 3.915µs ± 0.003µs 3.915µs ± 0.002µs 3.917µs 3.920µs 3.921µs 3.922µs 0.16% -1.341 9.405 0.07% 0.000µs 1 200
credit_card/is_card_number/37828224631 throughput 254991165.130op/s 255399666.016op/s ± 171250.328op/s 255405921.230op/s ± 104420.811op/s 255499374.041op/s 255620517.421op/s 255708809.158op/s 256569175.066op/s 0.46% 1.361 9.553 0.07% 12109.227op/s 1 200
credit_card/is_card_number/378282246310005 execution_time 67.240µs 68.620µs ± 0.703µs 68.547µs ± 0.474µs 69.030µs 69.925µs 70.260µs 71.051µs 3.65% 0.561 0.115 1.02% 0.050µs 1 200
credit_card/is_card_number/378282246310005 throughput 14074357.918op/s 14574579.248op/s ± 148426.112op/s 14588610.731op/s ± 100945.232op/s 14684960.205op/s 14792369.292op/s 14847721.977op/s 14872065.097op/s 1.94% -0.507 0.018 1.02% 10495.311op/s 1 200
credit_card/is_card_number/37828224631000521389798 execution_time 53.060µs 53.139µs ± 0.036µs 53.139µs ± 0.024µs 53.159µs 53.206µs 53.233µs 53.252µs 0.21% 0.497 0.238 0.07% 0.003µs 1 200
credit_card/is_card_number/37828224631000521389798 throughput 18778682.202op/s 18818725.353op/s ± 12705.647op/s 18818562.670op/s ± 8381.221op/s 18828324.335op/s 18837957.939op/s 18841183.466op/s 18846521.112op/s 0.15% -0.493 0.232 0.07% 898.425op/s 1 200
credit_card/is_card_number/x371413321323331 execution_time 6.428µs 6.438µs ± 0.005µs 6.438µs ± 0.003µs 6.441µs 6.446µs 6.448µs 6.449µs 0.18% 0.094 -0.601 0.07% 0.000µs 1 200
credit_card/is_card_number/x371413321323331 throughput 155056890.114op/s 155326546.070op/s ± 114074.402op/s 155329348.457op/s ± 78366.550op/s 155405835.495op/s 155510073.918op/s 155543592.090op/s 155568184.765op/s 0.15% -0.091 -0.603 0.07% 8066.278op/s 1 200
credit_card/is_card_number_no_luhn/ execution_time 3.897µs 3.916µs ± 0.003µs 3.916µs ± 0.002µs 3.918µs 3.920µs 3.922µs 3.927µs 0.27% -0.952 6.744 0.08% 0.000µs 1 200
credit_card/is_card_number_no_luhn/ throughput 254677392.024op/s 255365804.663op/s ± 199004.147op/s 255358480.333op/s ± 116942.931op/s 255475384.947op/s 255668489.381op/s 255747819.749op/s 256602904.946op/s 0.49% 0.970 6.848 0.08% 14071.718op/s 1 200
credit_card/is_card_number_no_luhn/ 3782-8224-6310-005 execution_time 64.915µs 65.187µs ± 0.187µs 65.133µs ± 0.082µs 65.265µs 65.533µs 65.857µs 66.086µs 1.46% 1.783 4.216 0.29% 0.013µs 1 200
credit_card/is_card_number_no_luhn/ 3782-8224-6310-005 throughput 15131765.250op/s 15340609.723op/s ± 43726.316op/s 15353317.471op/s ± 19445.068op/s 15369537.193op/s 15386156.077op/s 15398416.014op/s 15404666.073op/s 0.33% -1.758 4.082 0.28% 3091.917op/s 1 200
credit_card/is_card_number_no_luhn/ 378282246310005 execution_time 58.633µs 58.960µs ± 0.214µs 58.908µs ± 0.115µs 59.066µs 59.338µs 59.715µs 59.748µs 1.43% 1.336 2.101 0.36% 0.015µs 1 200
credit_card/is_card_number_no_luhn/ 378282246310005 throughput 16736922.360op/s 16960986.040op/s ± 61272.049op/s 16975679.795op/s ± 33089.641op/s 17002673.671op/s 17035169.978op/s 17050126.177op/s 17055168.353op/s 0.47% -1.311 2.010 0.36% 4332.588op/s 1 200
credit_card/is_card_number_no_luhn/37828224631 execution_time 3.897µs 3.915µs ± 0.004µs 3.915µs ± 0.001µs 3.916µs 3.920µs 3.928µs 3.938µs 0.60% 1.797 13.380 0.10% 0.000µs 1 200
credit_card/is_card_number_no_luhn/37828224631 throughput 253904300.546op/s 255422407.889op/s ± 243704.378op/s 255438967.216op/s ± 97284.720op/s 255538553.004op/s 255713235.929op/s 255751674.603op/s 256587151.775op/s 0.45% -1.762 13.254 0.10% 17232.502op/s 1 200
credit_card/is_card_number_no_luhn/378282246310005 execution_time 55.253µs 55.631µs ± 0.200µs 55.567µs ± 0.089µs 55.731µs 56.022µs 56.278µs 56.367µs 1.44% 1.260 1.611 0.36% 0.014µs 1 200
credit_card/is_card_number_no_luhn/378282246310005 throughput 17740913.474op/s 17975727.592op/s ± 64281.231op/s 17996299.963op/s ± 28903.778op/s 18020015.733op/s 18046224.503op/s 18082008.339op/s 18098692.168op/s 0.57% -1.239 1.546 0.36% 4545.369op/s 1 200
credit_card/is_card_number_no_luhn/37828224631000521389798 execution_time 53.060µs 53.133µs ± 0.032µs 53.130µs ± 0.022µs 53.157µs 53.179µs 53.212µs 53.281µs 0.28% 0.481 1.530 0.06% 0.002µs 1 200
credit_card/is_card_number_no_luhn/37828224631000521389798 throughput 18768532.063op/s 18820628.985op/s ± 11240.327op/s 18821892.909op/s ± 7727.833op/s 18828635.237op/s 18837641.191op/s 18844396.501op/s 18846524.870op/s 0.13% -0.475 1.510 0.06% 794.811op/s 1 200
credit_card/is_card_number_no_luhn/x371413321323331 execution_time 6.428µs 6.438µs ± 0.005µs 6.438µs ± 0.002µs 6.440µs 6.445µs 6.447µs 6.469µs 0.49% 1.630 10.316 0.07% 0.000µs 1 200
credit_card/is_card_number_no_luhn/x371413321323331 throughput 154572911.266op/s 155327186.246op/s ± 109233.678op/s 155334045.165op/s ± 59265.153op/s 155392968.468op/s 155489406.410op/s 155553630.054op/s 155576875.350op/s 0.16% -1.609 10.156 0.07% 7723.987op/s 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
credit_card/is_card_number/ execution_time [3.914µs; 3.915µs] or [-0.010%; +0.010%] None None None
credit_card/is_card_number/ throughput [255411200.010op/s; 255462947.328op/s] or [-0.010%; +0.010%] None None None
credit_card/is_card_number/ 3782-8224-6310-005 execution_time [78.329µs; 78.544µs] or [-0.137%; +0.137%] None None None
credit_card/is_card_number/ 3782-8224-6310-005 throughput [12732928.836op/s; 12767796.134op/s] or [-0.137%; +0.137%] None None None
credit_card/is_card_number/ 378282246310005 execution_time [71.919µs; 72.136µs] or [-0.151%; +0.151%] None None None
credit_card/is_card_number/ 378282246310005 throughput [13864463.822op/s; 13906070.801op/s] or [-0.150%; +0.150%] None None None
credit_card/is_card_number/37828224631 execution_time [3.915µs; 3.916µs] or [-0.009%; +0.009%] None None None
credit_card/is_card_number/37828224631 throughput [255375932.368op/s; 255423399.665op/s] or [-0.009%; +0.009%] None None None
credit_card/is_card_number/378282246310005 execution_time [68.522µs; 68.717µs] or [-0.142%; +0.142%] None None None
credit_card/is_card_number/378282246310005 throughput [14554008.816op/s; 14595149.679op/s] or [-0.141%; +0.141%] None None None
credit_card/is_card_number/37828224631000521389798 execution_time [53.134µs; 53.144µs] or [-0.009%; +0.009%] None None None
credit_card/is_card_number/37828224631000521389798 throughput [18816964.473op/s; 18820486.234op/s] or [-0.009%; +0.009%] None None None
credit_card/is_card_number/x371413321323331 execution_time [6.437µs; 6.439µs] or [-0.010%; +0.010%] None None None
credit_card/is_card_number/x371413321323331 throughput [155310736.455op/s; 155342355.685op/s] or [-0.010%; +0.010%] None None None
credit_card/is_card_number_no_luhn/ execution_time [3.916µs; 3.916µs] or [-0.011%; +0.011%] None None None
credit_card/is_card_number_no_luhn/ throughput [255338224.602op/s; 255393384.723op/s] or [-0.011%; +0.011%] None None None
credit_card/is_card_number_no_luhn/ 3782-8224-6310-005 execution_time [65.161µs; 65.213µs] or [-0.040%; +0.040%] None None None
credit_card/is_card_number_no_luhn/ 3782-8224-6310-005 throughput [15334549.676op/s; 15346669.770op/s] or [-0.040%; +0.040%] None None None
credit_card/is_card_number_no_luhn/ 378282246310005 execution_time [58.930µs; 58.989µs] or [-0.050%; +0.050%] None None None
credit_card/is_card_number_no_luhn/ 378282246310005 throughput [16952494.323op/s; 16969477.757op/s] or [-0.050%; +0.050%] None None None
credit_card/is_card_number_no_luhn/37828224631 execution_time [3.915µs; 3.916µs] or [-0.013%; +0.013%] None None None
credit_card/is_card_number_no_luhn/37828224631 throughput [255388632.806op/s; 255456182.972op/s] or [-0.013%; +0.013%] None None None
credit_card/is_card_number_no_luhn/378282246310005 execution_time [55.604µs; 55.659µs] or [-0.050%; +0.050%] None None None
credit_card/is_card_number_no_luhn/378282246310005 throughput [17966818.832op/s; 17984636.352op/s] or [-0.050%; +0.050%] None None None
credit_card/is_card_number_no_luhn/37828224631000521389798 execution_time [53.129µs; 53.138µs] or [-0.008%; +0.008%] None None None
credit_card/is_card_number_no_luhn/37828224631000521389798 throughput [18819071.184op/s; 18822186.786op/s] or [-0.008%; +0.008%] None None None
credit_card/is_card_number_no_luhn/x371413321323331 execution_time [6.437µs; 6.439µs] or [-0.010%; +0.010%] None None None
credit_card/is_card_number_no_luhn/x371413321323331 throughput [155312047.509op/s; 155342324.983op/s] or [-0.010%; +0.010%] None None None

Group 18

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
normalization/normalize_trace/test_trace execution_time 239.118ns 253.532ns ± 16.889ns 244.427ns ± 3.730ns 267.167ns 282.490ns 304.402ns 310.384ns 26.98% 1.302 0.915 6.64% 1.194ns 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
normalization/normalize_trace/test_trace execution_time [251.191ns; 255.873ns] or [-0.923%; +0.923%] None None None

Group 19

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 210da31 1769716211 bengl/change-buffer
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
benching serializing traces from their internal representation to msgpack execution_time 13.832ms 13.887ms ± 0.028ms 13.881ms ± 0.012ms 13.896ms 13.927ms 13.992ms 14.061ms 1.29% 2.618 10.710 0.20% 0.002ms 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
benching serializing traces from their internal representation to msgpack execution_time [13.883ms; 13.891ms] or [-0.028%; +0.028%] None None None

Baseline

Omitted due to size.

@codecov-commenter
Copy link

codecov-commenter commented Jan 15, 2026

Codecov Report

❌ Patch coverage is 0% with 233 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.93%. Comparing base (51c8cb4) to head (5a6f809).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1453      +/-   ##
==========================================
- Coverage   71.29%   70.93%   -0.36%     
==========================================
  Files         416      418       +2     
  Lines       66872    67233     +361     
==========================================
+ Hits        47676    47694      +18     
- Misses      19196    19539     +343     
Components Coverage Δ
libdd-crashtracker 61.42% <ø> (+0.19%) ⬆️
libdd-crashtracker-ffi 16.74% <ø> (+1.66%) ⬆️
libdd-alloc 98.73% <ø> (ø)
libdd-data-pipeline 86.02% <ø> (+0.27%) ⬆️
libdd-data-pipeline-ffi 77.63% <ø> (+0.62%) ⬆️
libdd-common 80.84% <ø> (ø)
libdd-common-ffi 74.19% <ø> (ø)
libdd-telemetry 60.22% <ø> (-0.04%) ⬇️
libdd-telemetry-ffi 21.17% <ø> (ø)
libdd-dogstatsd-client 83.75% <ø> (ø)
datadog-ipc 82.62% <ø> (+<0.01%) ⬆️
libdd-profiling 80.67% <ø> (+0.01%) ⬆️
libdd-profiling-ffi 62.46% <ø> (ø)
datadog-sidecar 35.37% <ø> (-1.01%) ⬇️
datdog-sidecar-ffi 11.26% <ø> (-2.12%) ⬇️
spawn-worker 55.18% <ø> (ø)
libdd-tinybytes 92.44% <ø> (ø)
libdd-trace-normalization 82.33% <ø> (ø)
libdd-trace-obfuscation 94.17% <ø> (ø)
libdd-trace-protobuf 61.18% <ø> (ø)
libdd-trace-utils 86.90% <0.00%> (-3.00%) ⬇️
datadog-tracer-flare 59.74% <ø> (ø)
libdd-log 75.57% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bengl bengl force-pushed the bengl/change-buffer branch from ae7b0d1 to 4c76607 Compare January 16, 2026 20:19
@dd-octo-sts
Copy link

dd-octo-sts bot commented Jan 16, 2026

Artifact Size Benchmark Report

aarch64-alpine-linux-musl
Artifact Baseline Commit Change
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 8.00 MB 8.00 MB 0% (0 B) 👌
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.a 91.81 MB 91.81 MB 0% (0 B) 👌
aarch64-apple-darwin
Artifact Baseline Commit Change
/aarch64-apple-darwin/lib/libdatadog_profiling.a 63.03 MB 63.03 MB 0% (0 B) 👌
/aarch64-apple-darwin/lib/libdatadog_profiling.dylib 9.20 MB 9.20 MB 0% (0 B) 👌
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 106.16 MB 106.16 MB 0% (0 B) 👌
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.37 MB 10.37 MB 0% (0 B) 👌
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 24.71 MB 24.71 MB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 76.33 KB 76.33 KB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 164.56 MB 164.62 MB +.03% (+56.00 KB) 🔍
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 811.95 MB 812.19 MB +.02% (+246.42 KB) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 9.31 MB 9.31 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 76.33 KB 76.33 KB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 22.93 MB 22.93 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 48.32 MB 48.32 MB -0% (-84 B) 👌
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 20.82 MB 20.82 MB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 77.50 KB 77.50 KB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 168.40 MB 168.44 MB +.02% (+48.00 KB) 🔍
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 798.69 MB 798.93 MB +.03% (+245.74 KB) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 7.03 MB 7.03 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 77.50 KB 77.50 KB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 24.48 MB 24.48 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 44.00 MB 44.00 MB -0% (-80 B) 👌
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 79.91 MB 79.91 MB -0% (-160 B) 👌
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 9.51 MB 9.51 MB 0% (0 B) 👌
x86_64-apple-darwin
Artifact Baseline Commit Change
/x86_64-apple-darwin/lib/libdatadog_profiling.a 64.40 MB 64.40 MB -0% (-344 B) 👌
/x86_64-apple-darwin/lib/libdatadog_profiling.dylib 10.23 MB 10.23 MB 0% (0 B) 👌
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 99.86 MB 99.86 MB -0% (-168 B) 👌
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 11.08 MB 11.08 MB 0% (0 B) 👌

trace_span_counts: HashMap<u128, usize>,
tracer_service: T,
tracer_language: T,
pid: f64,
Copy link
Contributor

Choose a reason for hiding this comment

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

Aren't PIDs integers?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not in trace exporter's config 🤷


impl From<u64> for OpCode {
fn from(val: u64) -> Self {
unsafe { std::mem::transmute(val) }
Copy link
Contributor

Choose a reason for hiding this comment

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

This is UB if someone sends an invalid opcode. Could you use try_from instead?

Something like...

impl TryFrom<u64> for OpCode {
    type Error = anyhow::Error;
    fn try_from(val: u64) -> Result<Self, Self::Error> {
        match val {
            0 => Ok(OpCode::Create),
            ...
            _ => Err(anyhow!("invalid opcode: {}", val))
        }
    }
}

You'll need to update BufferedOperation::from_buf and flush_change_buffer to handle the Result, but both of those functions return Results anyway, so that shouldn't be a problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd like to keep the transmute and just bounds-check it in the try_from. SGTY?

Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any reason to do bound-check + transmute rather than exhaust matching?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The main reason is to avoid having all the OpCodes listed out in two places. Maybe I can macro that away? 🤔

use crate::span::{Span, SpanText};

#[derive(Clone, Copy)]
pub struct ChangeBuffer(*const u8);
Copy link
Contributor

@ekump ekump Jan 21, 2026

Choose a reason for hiding this comment

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

Instead of a raw pointer, can the buffer be &mut [u8]? If we can do that, I think you can move the unsafe code to the FFI layer / caller where it better belongs. The caller would need to do something like

let slice = unsafe { std::slice::from_raw_parts(ptr, len) };
let change_buffer = ChangeBuffer::new(slice); 

If we can do that, then we won't need the unsafe code in get_num_raw where every read has the potential for UB if we get the pointer math wrong. I think you'd also be able to get rid of the unsafe Send and Sync definitions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem is lifetimes. In napi.rs, the Buffer object we get from Node.js will have a lifetime as long as the function call. That said, the informal promise is that the Buffer will persist on the JS side forever, as good as 'static. Raw pointers allowed me to get around that.

I think I can take it a step further and convert that back to a slice with new ownership so that we can avoid all the unsafe. I'll give it a try.

.insert(T::from_static_str("_dd.rule_psr"), rule);
}
if let Some(rule) = trace.sampling_limit_decision {
span.metrics.insert(T::from_static_str("_dd.;_psr"), rule);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is _dd.;_psr correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct.

use crate::span::{Span, SpanText};

#[derive(Clone, Copy)]
pub struct ChangeBuffer(*const u8);
Copy link
Contributor

Choose a reason for hiding this comment

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

If you get into trouble with lifetimes using a slice from the managed side maybe you can add an length field. That way you can enclose all the unsafe operations to just the constructor and a handful of private helpers to turn it into a slice. Something like:

   pub struct ChangeBuffer {                                                                                                                                                                                                       
      ptr: *mut u8,                                                                                                                                                                                                               
      len: usize,                                                                                                                                                                                                                 
  }                                                                                                                                                                                                                               
                                                                                                                                                                                                                                  
  impl ChangeBuffer {                                                                                                                                                                                                                                                                                                                                                                      
      pub unsafe fn from_raw_parts(ptr: *const u8, len: usize) -> Self {                                                                                                                                                          
          Self { ptr: ptr as *mut u8, len }                                                                                                                                                                                       
      }                                                                                                                                                                                                                           
                                                                                                                                                                                                                                  
      fn as_slice(&self) -> &[u8] {                                                                                                                                                                                               
          unsafe { std::slice::from_raw_parts(self.ptr, self.len) }                                                                                                                                                               
      }                                                                                                                                                                                                                           
                                                                                                                                                                                                                                  
      fn as_mut_slice(&mut self) -> &mut [u8] {                                                                                                                                                                                   
          unsafe { std::slice::from_raw_parts_mut(self.ptr, self.len) }                                                                                                                                                           
      }                                                                                                                                                                                                                           
                                                                                                                                                                                                                                  
      pub fn read_u64(&self, offset: usize) -> Result<u64> {                                                                                                                                                                      
          let slice = self.as_slice();                                                                                                                                                                                            
          let bytes = slice.get(offset..offset + 8)                                                                                                                                                                               
              .context(format!("read_u64 out of bounds: offset={}, len={}", offset, self.len))?;                                                                                                                                  
          let array: [u8; 8] = bytes.try_into()                                                                                                                                                                                   
              .map_err(|_| anyhow!("failed to convert slice to [u8; 8]"))?;                                                                                                                                                       
          Ok(u64::from_le_bytes(array))                                                                                                                                                                                           
      }                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
      pub fn write_u64(&mut self, offset: usize, value: u64) -> Result<()> {                                                                                                                                                      
          let slice = self.as_mut_slice();                                                                                                                                                                                        
          let target = slice.get_mut(offset..offset + 8)                                                                                                                                                                          
              .context(format!("write_u64 out of bounds: offset={}, len={}", offset, self.len))?;                                                                                                                                 
          target.copy_from_slice(&value.to_le_bytes());                                                                                                                                                                           
          Ok(())                                                                                                                                                                                                                  
      }                                                                                                                                                                                                                           
                                                                                                                                                                                                                                  
      pub fn clear_count(&mut self) -> Result<()> {                                                                                                                                                                               
          self.write_u64(0, 0)                                                                                                                                                                                                    
              .context("failed to clear buffer count")                                                                                                                                                                            
      }  

#[derive(Clone, Copy)]
pub struct ChangeBuffer(*const u8);
unsafe impl Send for ChangeBuffer {}
unsafe impl Sync for ChangeBuffer {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you really have to implement Sync? Is this required by NapiRS? In that case I think it will be good to document the constraints and point out that synchronization must be provided externally.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IIRC napi.rs needed it, but for a reason that does not apply to our usage. I'll try again without.


impl From<u64> for OpCode {
fn from(val: u64) -> Self {
unsafe { std::mem::transmute(val) }
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any reason to do bound-check + transmute rather than exhaust matching?

@hoolioh
Copy link
Contributor

hoolioh commented Jan 27, 2026

This is more of a general comment. Since trace-utils is too crowded and we talked about refactoring it. Would it make sense to place this implmentation in a new crate? I don't say that I has to happen now. Maybe in a later PR when we split trace-utils.

}

#[derive(Default)]
pub struct ChangeBufferState<T: SpanText + Clone> {
Copy link
Contributor

Choose a reason for hiding this comment

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

If having a non-cryptogrhapic hasher is an option you can use FxHashMap from rustc-hash that way you can squeeze some performance from the lookups.

fn copy_in_chunk_tags(&self, span: &mut Span<T>) {
if let Some(trace) = self.traces.get(&span.trace_id) {
span.meta.reserve(trace.meta.len());
span.meta.extend(trace.meta.clone());
Copy link
Contributor

Choose a reason for hiding this comment

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

I belive that clone will create a temproray hashmap so in order to save that extra allocation it will probably better to iterate over the hashmap just cloning the elements rather than cloning the whole thing.

@github-actions
Copy link

github-actions bot commented Jan 29, 2026

📚 Documentation Check Results

⚠️ 278 documentation warning(s) found

📦 libdd-trace-utils - 278 warning(s)


Updated: 2026-01-29 19:51:15 UTC | Commit: 873c8a2 | missing-docs job results

@github-actions
Copy link

github-actions bot commented Jan 29, 2026

🔒 Cargo Deny Results

No issues found!

📦 libdd-trace-utils - ✅ No issues


Updated: 2026-01-29 19:54:31 UTC | Commit: 873c8a2 | dependency-check job results

@bengl bengl force-pushed the bengl/change-buffer branch from 5d9d55b to 210da31 Compare January 29, 2026 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants