Skip to content

feat(runtime): add shared runtime#1602

Open
VianneyRuhlmann wants to merge 40 commits intomainfrom
vianney/implement-shared-runtime
Open

feat(runtime): add shared runtime#1602
VianneyRuhlmann wants to merge 40 commits intomainfrom
vianney/implement-shared-runtime

Conversation

@VianneyRuhlmann
Copy link
Contributor

@VianneyRuhlmann VianneyRuhlmann commented Feb 18, 2026

What does this PR do?

Implementing the shared runtime

This PR introduces a shared runtime to be used across common components it offers two main features:

  • Provide access to a tokio runtime to call async code in blocking functions e.g. TraceExporter::send
  • Spawn background workers on the runtime which can be paused and restarted on forks
    The shared runtime runs the workers using the PausableWorker

Update to the Worker trait

This PR also refactors the Worker trait to make it execute a trigger-run loop. The worker can be paused between two calls to run but not within a run execution. This is the same tradeoff between fork-time impact and worker execution than the one in dd-trace-py. Some extra hooks where introduced to allow porting the existing workers to this new lifecycle (e.g. initial_trigger, shutdown).

Expose ffi

The shared runtime FFI exposes an pointer to the SharedRuntime which is wrapped in an Arc. The pointer used by the users is pointing directly at the runtime and the Arc is only materialized when the pointer is dropped.

Porting the existing workers

The update to the worker trait needs to be applied to existing workers (stats exporter, info fetcher, telemetry)

Stats exporter

The stats exporter doesn't need the cancellation token anymore as the flushing of remaining stats is handled in the shutdown hook. The trace exporter can trigger the flush by stopping the worker with the handle

Info fetcher

The info fetcher uses the on_pause hook to release the reference to the IoStack. This used to be done by the TraceExporter stop_worker but is now handled directly in the worker.

Telemetry worker

The telemetry worker required some refactor to fit in the new Worker trait. The main issue is that the trigger needs to save the next action to be used in the run function. This could be done by passing the return value of trigger to run but I'm not sure this will be a common pattern in workers. If this turns out to be we can reconsider it.

Losing telemetry payloads on shutdown

Currently when the telemetry worker is shut down all actions sent before the stop action are processed. With this refactor it's no longer the cases as the shutdown hook bypasses the actions queued. This is deemed acceptable since there's currently no way to know if an action has been posted before or after the stop, this means any action is already at risk of being ignored.

Using the shared runtime in TraceExporter

This PR also integrates the shared runtime in the Trace Exporter. We can now pass a SharedRuntime to the TraceExporter and the workers will be spawned on it. Fork hooks from the TraceExporter are removed as this is now handled by the SharedRuntime. The TraceExporter also uses the shared runtime to block on async code.

Motivation

Be able to share a common tokio runtime across components and manage fork-safety in a single place.

Additional Notes

This PR is a breaking change especially for language which register "fork-safety" hooks as this should now be handled in the SharedRuntime.

How to test the change?

Describe here in detail how the change can be validated.

@pr-commenter
Copy link

pr-commenter bot commented Feb 18, 2026

Benchmarks

Comparison

Benchmark execution time: 2026-03-23 10:04:07

Comparing candidate commit 0f91bb3 in PR branch vianney/implement-shared-runtime with baseline commit ed00b92 in branch main.

Found 7 performance improvements and 18 performance regressions! Performance is the same for 34 metrics, 1 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:benching deserializing traces from msgpack to their internal representation

  • 🟩 execution_time [-2.719ms; -2.196ms] or [-5.236%; -4.229%]

scenario:concentrator/add_spans_to_concentrator

  • 🟩 execution_time [-2.331ms; -2.325ms] or [-17.939%; -17.893%]

scenario:credit_card/is_card_number/ 3782-8224-6310-005

  • 🟥 execution_time [+4.159µs; +4.388µs] or [+5.493%; +5.795%]
  • 🟥 throughput [-726222.817op/s; -687203.843op/s] or [-5.498%; -5.203%]

scenario:credit_card/is_card_number/ 378282246310005

  • 🟥 execution_time [+4.495µs; +4.562µs] or [+6.542%; +6.639%]
  • 🟥 throughput [-905940.657op/s; -893369.532op/s] or [-6.225%; -6.139%]

scenario:credit_card/is_card_number/378282246310005

  • 🟥 execution_time [+5.397µs; +5.479µs] or [+8.322%; +8.449%]
  • 🟥 throughput [-1201260.479op/s; -1184205.307op/s] or [-7.791%; -7.680%]

scenario:credit_card/is_card_number/37828224631000521389798

  • 🟥 execution_time [+6.508µs; +6.547µs] or [+14.250%; +14.337%]
  • 🟥 throughput [-2747963.369op/s; -2729139.866op/s] or [-12.550%; -12.464%]

scenario:credit_card/is_card_number/x371413321323331

  • 🟩 execution_time [-612.638ns; -594.594ns] or [-9.519%; -9.239%]
  • 🟩 throughput [+15836261.717op/s; +16366589.903op/s] or [+10.192%; +10.534%]

scenario:credit_card/is_card_number_no_luhn/ 378282246310005

  • 🟥 execution_time [+3.276µs; +3.327µs] or [+6.038%; +6.132%]
  • 🟥 throughput [-1065513.012op/s; -1048901.258op/s] or [-5.781%; -5.691%]

scenario:credit_card/is_card_number_no_luhn/378282246310005

  • 🟥 execution_time [+4.375µs; +4.435µs] or [+8.682%; +8.799%]
  • 🟥 throughput [-1605155.624op/s; -1584513.420op/s] or [-8.089%; -7.985%]

scenario:credit_card/is_card_number_no_luhn/37828224631000521389798

  • 🟥 execution_time [+6.512µs; +6.532µs] or [+14.259%; +14.304%]
  • 🟥 throughput [-2741213.791op/s; -2731710.897op/s] or [-12.519%; -12.475%]

scenario:credit_card/is_card_number_no_luhn/x371413321323331

  • 🟩 execution_time [-619.255ns; -601.432ns] or [-9.620%; -9.343%]
  • 🟩 throughput [+16032147.451op/s; +16555643.219op/s] or [+10.320%; +10.657%]

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

  • 🟥 execution_time [+20.512µs; +20.640µs] or [+11.031%; +11.099%]
  • 🟥 throughput [-537361.613op/s; -534155.334op/s] or [-9.992%; -9.933%]

scenario:normalization/normalize_name/normalize_name/good

  • 🟥 execution_time [+697.722ns; +720.760ns] or [+6.868%; +7.095%]
  • 🟥 throughput [-6525409.947op/s; -6320898.800op/s] or [-6.629%; -6.421%]

scenario:write only interface

  • 🟩 execution_time [-2.560µs; -2.161µs] or [-46.109%; -38.933%]

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 0f91bb3 1774259263 vianney/implement-shared-runtime
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 144.931µs 147.071µs ± 3.175µs 146.653µs ± 0.447µs 147.136µs 148.510µs 156.309µs 184.376µs 25.72% 9.340 99.707 2.15% 0.225µ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.631µs; 147.511µs] or [-0.299%; +0.299%] None None None

Group 2

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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.170µs 3.191µs ± 1.437µs 2.985µs ± 0.029µs 3.014µs 3.648µs 13.934µs 14.959µs 401.22% 7.402 55.782 44.91% 0.102µ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.992µs; 3.390µs] or [-6.240%; +6.240%] None None None

Group 3

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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.426µs 25.373µs ± 10.278µs 17.831µs ± 0.191µs 34.879µs 44.727µs 52.916µs 73.674µs 313.19% 1.185 1.346 40.41% 0.727µ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.948µs; 26.797µs] or [-5.614%; +5.614%] None None None

Group 4

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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/2598 execution_time 3.402ms 3.434ms ± 0.024ms 3.427ms ± 0.009ms 3.439ms 3.492ms 3.509ms 3.522ms 2.75% 1.592 1.857 0.71% 0.002ms 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
receiver_entry_point/report/2598 execution_time [3.431ms; 3.438ms] or [-0.099%; +0.099%] None None None

Group 5

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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 33.307µs 33.698µs ± 0.689µs 33.396µs ± 0.029µs 33.439µs 35.019µs 35.089µs 38.017µs 13.84% 2.382 7.189 2.04% 0.049µ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 [33.603µs; 33.794µs] or [-0.283%; +0.283%] None None None

Group 6

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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.329µs 2.405µs ± 0.023µs 2.405µs ± 0.007µs 2.412µs 2.450µs 2.457µs 2.460µs 2.31% -0.772 3.136 0.95% 0.002µ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.402µs; 2.408µs] or [-0.131%; +0.131%] None None None

Group 7

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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 205.873µs 206.529µs ± 0.388µs 206.463µs ± 0.244µs 206.775µs 207.237µs 207.644µs 207.694µs 0.60% 0.730 0.407 0.19% 0.027µs 1 200
normalization/normalize_name/normalize_name/Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Lo... throughput 4814772.451op/s 4841957.448op/s ± 9094.993op/s 4843482.852op/s ± 5736.886op/s 4847993.935op/s 4855121.979op/s 4857120.349op/s 4857369.897op/s 0.29% -0.720 0.386 0.19% 643.113op/s 1 200
normalization/normalize_name/normalize_name/bad-name execution_time 18.572µs 18.686µs ± 0.085µs 18.662µs ± 0.024µs 18.687µs 18.881µs 18.971µs 19.059µs 2.12% 1.881 3.468 0.45% 0.006µs 1 200
normalization/normalize_name/normalize_name/bad-name throughput 52469769.853op/s 53516206.309op/s ± 241850.870op/s 53584727.456op/s ± 68451.582op/s 53647702.836op/s 53760308.032op/s 53811444.071op/s 53845651.895op/s 0.49% -1.855 3.350 0.45% 17101.439op/s 1 200
normalization/normalize_name/normalize_name/good execution_time 10.755µs 10.868µs ± 0.066µs 10.866µs ± 0.040µs 10.902µs 10.963µs 11.032µs 11.334µs 4.31% 1.892 11.078 0.61% 0.005µs 1 200
normalization/normalize_name/normalize_name/good throughput 88231530.312op/s 92017223.669op/s ± 552297.866op/s 92032869.384op/s ± 337163.893op/s 92396638.625op/s 92772413.524op/s 92948625.692op/s 92979151.377op/s 1.03% -1.727 9.688 0.60% 39053.357op/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 [206.475µs; 206.583µs] or [-0.026%; +0.026%] None None None
normalization/normalize_name/normalize_name/Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Lo... throughput [4840696.969op/s; 4843217.926op/s] or [-0.026%; +0.026%] None None None
normalization/normalize_name/normalize_name/bad-name execution_time [18.675µs; 18.698µs] or [-0.063%; +0.063%] None None None
normalization/normalize_name/normalize_name/bad-name throughput [53482688.105op/s; 53549724.514op/s] or [-0.063%; +0.063%] None None None
normalization/normalize_name/normalize_name/good execution_time [10.859µs; 10.877µs] or [-0.084%; +0.084%] None None None
normalization/normalize_name/normalize_name/good throughput [91940680.496op/s; 92093766.841op/s] or [-0.083%; +0.083%] None None None

Group 8

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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.893µs 3.912µs ± 0.003µs 3.912µs ± 0.002µs 3.914µs 3.916µs 3.917µs 3.918µs 0.15% -1.736 13.437 0.07% 0.000µs 1 200
credit_card/is_card_number/ throughput 255256364.439op/s 255633172.885op/s ± 169487.468op/s 255647860.622op/s ± 104743.766op/s 255731736.312op/s 255835156.437op/s 255887197.760op/s 256891798.119op/s 0.49% 1.761 13.653 0.07% 11984.574op/s 1 200
credit_card/is_card_number/ 3782-8224-6310-005 execution_time 79.440µs 79.988µs ± 0.333µs 79.923µs ± 0.224µs 80.183µs 80.616µs 80.818µs 81.367µs 1.81% 0.848 0.691 0.42% 0.024µs 1 200
credit_card/is_card_number/ 3782-8224-6310-005 throughput 12290020.091op/s 12502164.645op/s ± 51839.113op/s 12512016.541op/s ± 35177.219op/s 12542489.919op/s 12570537.941op/s 12579027.585op/s 12588182.738op/s 0.61% -0.824 0.608 0.41% 3665.579op/s 1 200
credit_card/is_card_number/ 378282246310005 execution_time 72.729µs 73.244µs ± 0.226µs 73.228µs ± 0.129µs 73.350µs 73.622µs 73.990µs 74.278µs 1.43% 1.119 3.156 0.31% 0.016µs 1 200
credit_card/is_card_number/ 378282246310005 throughput 13462858.479op/s 13653065.936op/s ± 41929.049op/s 13655905.779op/s ± 24024.882op/s 13682151.650op/s 13706611.430op/s 13733842.524op/s 13749654.126op/s 0.69% -1.083 3.011 0.31% 2964.831op/s 1 200
credit_card/is_card_number/37828224631 execution_time 3.890µs 3.912µs ± 0.003µs 3.911µs ± 0.001µs 3.913µs 3.917µs 3.920µs 3.925µs 0.35% -0.684 12.561 0.08% 0.000µs 1 200
credit_card/is_card_number/37828224631 throughput 254773465.339op/s 255630159.543op/s ± 209173.962op/s 255662481.545op/s ± 89916.058op/s 255735444.962op/s 255851653.511op/s 255944518.159op/s 257093963.470op/s 0.56% 0.718 12.762 0.08% 14790.833op/s 1 200
credit_card/is_card_number/378282246310005 execution_time 69.700µs 70.292µs ± 0.280µs 70.259µs ± 0.208µs 70.484µs 70.775µs 70.983µs 71.204µs 1.34% 0.518 0.104 0.40% 0.020µs 1 200
credit_card/is_card_number/378282246310005 throughput 14044163.098op/s 14226565.138op/s ± 56488.674op/s 14233030.040op/s ± 42111.947op/s 14269526.389op/s 14305621.837op/s 14326856.661op/s 14347176.385op/s 0.80% -0.496 0.066 0.40% 3994.352op/s 1 200
credit_card/is_card_number/37828224631000521389798 execution_time 52.132µs 52.197µs ± 0.031µs 52.196µs ± 0.020µs 52.216µs 52.252µs 52.283µs 52.304µs 0.21% 0.557 0.677 0.06% 0.002µs 1 200
credit_card/is_card_number/37828224631000521389798 throughput 19118969.981op/s 19158269.265op/s ± 11225.132op/s 19158678.565op/s ± 7496.842op/s 19166044.956op/s 19174504.333op/s 19179887.931op/s 19182175.922op/s 0.12% -0.552 0.668 0.06% 793.737op/s 1 200
credit_card/is_card_number/x371413321323331 execution_time 5.693µs 5.832µs ± 0.065µs 5.832µs ± 0.044µs 5.877µs 5.934µs 5.980µs 6.002µs 2.91% -0.013 -0.444 1.11% 0.005µs 1 200
credit_card/is_card_number/x371413321323331 throughput 166623921.322op/s 171476941.287op/s ± 1910164.473op/s 171471844.403op/s ± 1301374.724op/s 172718381.375op/s 174620591.436op/s 175581248.953op/s 175660400.314op/s 2.44% 0.065 -0.454 1.11% 135069.025op/s 1 200
credit_card/is_card_number_no_luhn/ execution_time 3.898µs 3.912µs ± 0.002µs 3.912µs ± 0.001µs 3.913µs 3.915µs 3.918µs 3.921µs 0.25% -0.137 7.056 0.06% 0.000µs 1 200
credit_card/is_card_number_no_luhn/ throughput 255010171.984op/s 255632535.071op/s ± 149264.270op/s 255644972.421op/s ± 85881.507op/s 255725853.886op/s 255809370.017op/s 255897874.062op/s 256514201.728op/s 0.34% 0.153 7.109 0.06% 10554.578op/s 1 200
credit_card/is_card_number_no_luhn/ 3782-8224-6310-005 execution_time 64.147µs 64.378µs ± 0.165µs 64.327µs ± 0.072µs 64.432µs 64.716µs 64.871µs 65.500µs 1.82% 2.547 10.812 0.26% 0.012µs 1 200
credit_card/is_card_number_no_luhn/ 3782-8224-6310-005 throughput 15267284.646op/s 15533252.939op/s ± 39529.668op/s 15545548.607op/s ± 17360.312op/s 15558820.082op/s 15570589.959op/s 15576595.327op/s 15589299.505op/s 0.28% -2.499 10.382 0.25% 2795.170op/s 1 200
credit_card/is_card_number_no_luhn/ 378282246310005 execution_time 57.347µs 57.561µs ± 0.118µs 57.539µs ± 0.067µs 57.615µs 57.770µs 57.950µs 58.025µs 0.84% 1.306 2.238 0.20% 0.008µs 1 200
credit_card/is_card_number_no_luhn/ 378282246310005 throughput 17234065.250op/s 17372903.239op/s ± 35565.010op/s 17379462.691op/s ± 20291.973op/s 17396800.729op/s 17415629.923op/s 17425135.481op/s 17437843.608op/s 0.34% -1.290 2.181 0.20% 2514.826op/s 1 200
credit_card/is_card_number_no_luhn/37828224631 execution_time 3.894µs 3.912µs ± 0.003µs 3.912µs ± 0.002µs 3.913µs 3.915µs 3.918µs 3.920µs 0.23% -1.168 12.070 0.06% 0.000µs 1 200
credit_card/is_card_number_no_luhn/37828224631 throughput 255076974.490op/s 255644208.788op/s ± 165894.311op/s 255654378.488op/s ± 100274.325op/s 255746360.425op/s 255849162.620op/s 255904554.747op/s 256819579.274op/s 0.46% 1.193 12.237 0.06% 11730.499op/s 1 200
credit_card/is_card_number_no_luhn/378282246310005 execution_time 54.402µs 54.801µs ± 0.185µs 54.768µs ± 0.117µs 54.909µs 55.162µs 55.345µs 55.451µs 1.25% 0.875 0.864 0.34% 0.013µs 1 200
credit_card/is_card_number_no_luhn/378282246310005 throughput 18033989.636op/s 18247909.075op/s ± 61272.938op/s 18258717.041op/s ± 39081.013op/s 18291157.609op/s 18329508.677op/s 18353322.354op/s 18381542.360op/s 0.67% -0.854 0.815 0.33% 4332.651op/s 1 200
credit_card/is_card_number_no_luhn/37828224631000521389798 execution_time 52.116µs 52.190µs ± 0.032µs 52.187µs ± 0.018µs 52.206µs 52.249µs 52.287µs 52.306µs 0.23% 0.820 1.275 0.06% 0.002µs 1 200
credit_card/is_card_number_no_luhn/37828224631000521389798 throughput 19118139.948op/s 19160724.965op/s ± 11642.802op/s 19161977.845op/s ± 6497.681op/s 19168213.830op/s 19177005.141op/s 19181852.521op/s 19187982.567op/s 0.14% -0.815 1.265 0.06% 823.270op/s 1 200
credit_card/is_card_number_no_luhn/x371413321323331 execution_time 5.696µs 5.827µs ± 0.064µs 5.825µs ± 0.043µs 5.872µs 5.934µs 5.979µs 6.016µs 3.28% 0.244 -0.215 1.10% 0.005µs 1 200
credit_card/is_card_number_no_luhn/x371413321323331 throughput 166221690.520op/s 171646408.860op/s ± 1886445.451op/s 171678942.084op/s ± 1268577.167op/s 172877957.639op/s 174608001.924op/s 175503585.983op/s 175565404.842op/s 2.26% -0.187 -0.261 1.10% 133391.837op/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.911µs; 3.912µs] or [-0.009%; +0.009%] None None None
credit_card/is_card_number/ throughput [255609683.552op/s; 255656662.218op/s] or [-0.009%; +0.009%] None None None
credit_card/is_card_number/ 3782-8224-6310-005 execution_time [79.941µs; 80.034µs] or [-0.058%; +0.058%] None None None
credit_card/is_card_number/ 3782-8224-6310-005 throughput [12494980.243op/s; 12509349.048op/s] or [-0.057%; +0.057%] None None None
credit_card/is_card_number/ 378282246310005 execution_time [73.213µs; 73.276µs] or [-0.043%; +0.043%] None None None
credit_card/is_card_number/ 378282246310005 throughput [13647254.973op/s; 13658876.899op/s] or [-0.043%; +0.043%] None None None
credit_card/is_card_number/37828224631 execution_time [3.911µs; 3.912µs] or [-0.011%; +0.011%] None None None
credit_card/is_card_number/37828224631 throughput [255601170.044op/s; 255659149.042op/s] or [-0.011%; +0.011%] None None None
credit_card/is_card_number/378282246310005 execution_time [70.253µs; 70.331µs] or [-0.055%; +0.055%] None None None
credit_card/is_card_number/378282246310005 throughput [14218736.351op/s; 14234393.924op/s] or [-0.055%; +0.055%] None None None
credit_card/is_card_number/37828224631000521389798 execution_time [52.193µs; 52.201µs] or [-0.008%; +0.008%] None None None
credit_card/is_card_number/37828224631000521389798 throughput [19156713.570op/s; 19159824.960op/s] or [-0.008%; +0.008%] None None None
credit_card/is_card_number/x371413321323331 execution_time [5.823µs; 5.841µs] or [-0.154%; +0.154%] None None None
credit_card/is_card_number/x371413321323331 throughput [171212210.862op/s; 171741671.711op/s] or [-0.154%; +0.154%] None None None
credit_card/is_card_number_no_luhn/ execution_time [3.912µs; 3.912µs] or [-0.008%; +0.008%] None None None
credit_card/is_card_number_no_luhn/ throughput [255611848.479op/s; 255653221.663op/s] or [-0.008%; +0.008%] None None None
credit_card/is_card_number_no_luhn/ 3782-8224-6310-005 execution_time [64.356µs; 64.401µs] or [-0.035%; +0.035%] None None None
credit_card/is_card_number_no_luhn/ 3782-8224-6310-005 throughput [15527774.507op/s; 15538731.371op/s] or [-0.035%; +0.035%] None None None
credit_card/is_card_number_no_luhn/ 378282246310005 execution_time [57.545µs; 57.578µs] or [-0.028%; +0.028%] None None None
credit_card/is_card_number_no_luhn/ 378282246310005 throughput [17367974.271op/s; 17377832.208op/s] or [-0.028%; +0.028%] None None None
credit_card/is_card_number_no_luhn/37828224631 execution_time [3.911µs; 3.912µs] or [-0.009%; +0.009%] None None None
credit_card/is_card_number_no_luhn/37828224631 throughput [255621217.432op/s; 255667200.144op/s] or [-0.009%; +0.009%] None None None
credit_card/is_card_number_no_luhn/378282246310005 execution_time [54.776µs; 54.827µs] or [-0.047%; +0.047%] None None None
credit_card/is_card_number_no_luhn/378282246310005 throughput [18239417.235op/s; 18256400.915op/s] or [-0.047%; +0.047%] None None None
credit_card/is_card_number_no_luhn/37828224631000521389798 execution_time [52.186µs; 52.195µs] or [-0.008%; +0.008%] None None None
credit_card/is_card_number_no_luhn/37828224631000521389798 throughput [19159111.385op/s; 19162338.545op/s] or [-0.008%; +0.008%] None None None
credit_card/is_card_number_no_luhn/x371413321323331 execution_time [5.818µs; 5.836µs] or [-0.153%; +0.153%] None None None
credit_card/is_card_number_no_luhn/x371413321323331 throughput [171384965.664op/s; 171907852.057op/s] or [-0.152%; +0.152%] None None None

Group 9

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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 247.686ns 257.827ns ± 11.480ns 253.000ns ± 3.488ns 261.922ns 283.993ns 287.536ns 288.611ns 14.08% 1.315 0.346 4.44% 0.812ns 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 [256.236ns; 259.418ns] or [-0.617%; +0.617%] None None None

Group 10

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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 85.903µs 86.066µs ± 0.158µs 86.040µs ± 0.042µs 86.101µs 86.196µs 86.389µs 87.983µs 2.26% 9.187 107.580 0.18% 0.011µ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 [86.044µs; 86.088µs] or [-0.025%; +0.025%] None None None

Group 11

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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.561µs 162.401µs ± 0.271µs 162.378µs ± 0.110µs 162.494µs 162.860µs 163.399µs 163.718µs 0.83% 1.347 5.454 0.17% 0.019µ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.363µs; 162.438µs] or [-0.023%; +0.023%] None None None

Group 12

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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 714.452µs 716.084µs ± 0.711µs 716.015µs ± 0.376µs 716.405µs 717.457µs 718.403µs 718.880µs 0.40% 0.977 2.037 0.10% 0.050µ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 [715.985µs; 716.182µs] or [-0.014%; +0.014%] None None None

Group 13

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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 49.053ms 49.472ms ± 1.346ms 49.290ms ± 0.092ms 49.393ms 49.551ms 59.488ms 61.443ms 24.66% 7.862 61.244 2.71% 0.095ms 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 [49.286ms; 49.659ms] or [-0.377%; +0.377%] None None None

Group 14

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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 5.012µs 5.088µs ± 0.049µs 5.101µs ± 0.040µs 5.118µs 5.171µs 5.174µs 5.179µs 1.52% 0.126 -1.226 0.96% 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.081µs; 5.095µs] or [-0.134%; +0.134%] None None None

Group 15

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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 493.251µs 494.064µs ± 0.410µs 494.036µs ± 0.202µs 494.248µs 494.574µs 495.000µs 497.725µs 0.75% 3.682 30.389 0.08% 0.029µs 1 200
normalization/normalize_service/normalize_service/A0000000000000000000000000000000000000000000000000... throughput 2009142.940op/s 2024029.056op/s ± 1673.178op/s 2024145.355op/s ± 829.333op/s 2024966.829op/s 2026093.689op/s 2026848.169op/s 2027363.779op/s 0.16% -3.635 29.856 0.08% 118.312op/s 1 200
normalization/normalize_service/normalize_service/Data🐨dog🐶 繋がっ⛰てて execution_time 370.123µs 370.646µs ± 0.249µs 370.630µs ± 0.166µs 370.809µs 371.081µs 371.355µs 371.421µs 0.21% 0.395 0.117 0.07% 0.018µs 1 200
normalization/normalize_service/normalize_service/Data🐨dog🐶 繋がっ⛰てて throughput 2692365.412op/s 2697996.909op/s ± 1814.700op/s 2698107.202op/s ± 1208.352op/s 2699273.816op/s 2700938.317op/s 2701434.854op/s 2701805.487op/s 0.14% -0.391 0.111 0.07% 128.319op/s 1 200
normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters execution_time 167.310µs 167.567µs ± 0.168µs 167.548µs ± 0.113µs 167.661µs 167.854µs 168.074µs 168.210µs 0.39% 0.940 1.058 0.10% 0.012µs 1 200
normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters throughput 5944958.806op/s 5967756.940op/s ± 5986.323op/s 5968424.398op/s ± 4024.460op/s 5972447.641op/s 5975634.226op/s 5976715.617op/s 5976945.670op/s 0.14% -0.933 1.037 0.10% 423.297op/s 1 200
normalization/normalize_service/normalize_service/[empty string] execution_time 37.160µs 37.248µs ± 0.047µs 37.242µs ± 0.032µs 37.280µs 37.330µs 37.363µs 37.412µs 0.46% 0.590 -0.033 0.13% 0.003µs 1 200
normalization/normalize_service/normalize_service/[empty string] throughput 26729688.290op/s 26846785.409op/s ± 33797.482op/s 26851659.421op/s ± 22871.999op/s 26872345.403op/s 26892369.663op/s 26902641.244op/s 26910991.188op/s 0.22% -0.584 -0.046 0.13% 2389.843op/s 1 200
normalization/normalize_service/normalize_service/test_ASCII execution_time 45.463µs 45.711µs ± 0.219µs 45.642µs ± 0.135µs 45.892µs 46.039µs 46.115µs 47.048µs 3.08% 1.415 5.100 0.48% 0.016µs 1 200
normalization/normalize_service/normalize_service/test_ASCII throughput 21254951.775op/s 21877102.087op/s ± 104281.329op/s 21909761.212op/s ± 65039.467op/s 21965147.335op/s 21981321.124op/s 21994373.546op/s 21995783.905op/s 0.39% -1.345 4.542 0.48% 7373.803op/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 [494.008µs; 494.121µs] or [-0.011%; +0.011%] None None None
normalization/normalize_service/normalize_service/A0000000000000000000000000000000000000000000000000... throughput [2023797.170op/s; 2024260.942op/s] or [-0.011%; +0.011%] None None None
normalization/normalize_service/normalize_service/Data🐨dog🐶 繋がっ⛰てて execution_time [370.611µs; 370.680µs] or [-0.009%; +0.009%] None None None
normalization/normalize_service/normalize_service/Data🐨dog🐶 繋がっ⛰てて throughput [2697745.409op/s; 2698248.409op/s] or [-0.009%; +0.009%] None None None
normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters execution_time [167.544µs; 167.591µs] or [-0.014%; +0.014%] None None None
normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters throughput [5966927.293op/s; 5968586.587op/s] or [-0.014%; +0.014%] None None None
normalization/normalize_service/normalize_service/[empty string] execution_time [37.242µs; 37.255µs] or [-0.017%; +0.017%] None None None
normalization/normalize_service/normalize_service/[empty string] throughput [26842101.403op/s; 26851469.415op/s] or [-0.017%; +0.017%] None None None
normalization/normalize_service/normalize_service/test_ASCII execution_time [45.681µs; 45.741µs] or [-0.066%; +0.066%] None None None
normalization/normalize_service/normalize_service/test_ASCII throughput [21862649.698op/s; 21891554.477op/s] or [-0.066%; +0.066%] None None None

Group 16

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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 190.781ns 192.930ns ± 2.174ns 192.791ns ± 1.353ns 193.695ns 195.698ns 203.059ns 206.532ns 7.13% 2.870 13.239 1.12% 0.154ns 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 [192.629ns; 193.231ns] or [-0.156%; +0.156%] None None None

Group 17

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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 4.141ms 4.145ms ± 0.007ms 4.144ms ± 0.001ms 4.145ms 4.150ms 4.172ms 4.226ms 1.98% 8.026 80.449 0.17% 0.001ms 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 [4.144ms; 4.146ms] or [-0.024%; +0.024%] None None None

Group 18

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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.640ms 10.665ms ± 0.015ms 10.663ms ± 0.009ms 10.672ms 10.689ms 10.704ms 10.754ms 0.85% 1.790 7.178 0.14% 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.663ms; 10.667ms] or [-0.020%; +0.020%] None None None

Group 19

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 0f91bb3 1774259263 vianney/implement-shared-runtime
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 14.857ms 14.904ms ± 0.031ms 14.897ms ± 0.012ms 14.913ms 14.969ms 15.012ms 15.094ms 1.32% 2.473 9.355 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 [14.899ms; 14.908ms] or [-0.028%; +0.028%] None None None

Baseline

Omitted due to size.

@github-actions
Copy link

github-actions bot commented Feb 20, 2026

📚 Documentation Check Results

⚠️ 1445 documentation warning(s) found

📦 libdd-common - 168 warning(s)

📦 libdd-data-pipeline - 799 warning(s)

📦 libdd-telemetry - 478 warning(s)


Updated: 2026-03-11 12:57:10 UTC | Commit: 85e0696 | missing-docs job results

@github-actions
Copy link

github-actions bot commented Feb 20, 2026

Clippy Allow Annotation Report

Comparing clippy allow annotations between branches:

  • Base Branch: origin/main
  • PR Branch: origin/vianney/implement-shared-runtime

Summary by Rule

Rule Base Branch PR Branch Change
unwrap_used 18 18 No change (0%)
Total 18 18 No change (0%)

Annotation Counts by File

File Base Branch PR Branch Change
libdd-data-pipeline/src/stats_exporter.rs 1 1 No change (0%)
libdd-data-pipeline/src/telemetry/mod.rs 1 1 No change (0%)
libdd-data-pipeline/src/trace_exporter/mod.rs 2 2 No change (0%)
libdd-telemetry/src/worker/mod.rs 13 13 No change (0%)
libdd-telemetry/src/worker/store.rs 1 1 No change (0%)

Annotation Stats by Crate

Crate Base Branch PR Branch Change
clippy-annotation-reporter 5 5 No change (0%)
datadog-ffe-ffi 1 1 No change (0%)
datadog-ipc 28 28 No change (0%)
datadog-live-debugger 6 6 No change (0%)
datadog-live-debugger-ffi 10 10 No change (0%)
datadog-profiling-replayer 4 4 No change (0%)
datadog-remote-config 3 3 No change (0%)
datadog-sidecar 59 59 No change (0%)
libdd-common 10 10 No change (0%)
libdd-common-ffi 12 12 No change (0%)
libdd-data-pipeline 5 5 No change (0%)
libdd-ddsketch 2 2 No change (0%)
libdd-dogstatsd-client 1 1 No change (0%)
libdd-profiling 13 13 No change (0%)
libdd-telemetry 19 19 No change (0%)
libdd-tinybytes 4 4 No change (0%)
libdd-trace-normalization 2 2 No change (0%)
libdd-trace-obfuscation 9 9 No change (0%)
libdd-trace-utils 15 15 No change (0%)
Total 208 208 No change (0%)

About This Report

This report tracks Clippy allow annotations for specific rules, showing how they've changed in this PR. Decreasing the number of these annotations generally improves code quality.

@github-actions
Copy link

github-actions bot commented Feb 20, 2026

🔒 Cargo Deny Results

⚠️ 1 issue(s) found, showing only errors (advisories, bans, sources)

📦 libdd-common - ✅ No issues

📦 libdd-data-pipeline - 1 error(s)

Show output
error[vulnerability]: Denial of Service via Stack Exhaustion
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:293:1
    │
293 │ time 0.3.41 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0009
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0009
    ├ ## Impact
      
      When user-provided input is provided to any type that parses with the RFC 2822 format, a denial of
      service attack via stack exhaustion is possible. The attack relies on formally deprecated and
      rarely-used features that are part of the RFC 2822 format used in a malicious manner. Ordinary,
      non-malicious input will never encounter this scenario.
      
      ## Patches
      
      A limit to the depth of recursion was added in v0.3.47. From this version, an error will be returned
      rather than exhausting the stack.
      
      ## Workarounds
      
      Limiting the length of user input is the simplest way to avoid stack exhaustion, as the amount of
      the stack consumed would be at most a factor of the length of the input.
    ├ Announcement: https://github.com/time-rs/time/blob/main/CHANGELOG.md#0347-2026-02-05
    ├ Solution: Upgrade to >=0.3.47 (try `cargo update -p time`)
    ├ time v0.3.41
      └── tracing-appender v0.2.3
          └── libdd-log v1.0.0
              └── (dev) libdd-data-pipeline v2.0.0

advisories FAILED, bans ok, sources ok

📦 libdd-telemetry - ✅ No issues


Updated: 2026-03-11 12:59:51 UTC | Commit: 85e0696 | dependency-check job results

@datadog-datadog-prod-us1

This comment has been minimized.

@VianneyRuhlmann VianneyRuhlmann marked this pull request as ready for review March 10, 2026 17:10
@VianneyRuhlmann VianneyRuhlmann requested review from a team as code owners March 10, 2026 17:10
///
/// # Errors
/// Returns an error if it fails to create a runtime.
pub fn runtime(&self) -> Result<Arc<Runtime>, io::Error> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is returning a single-threaded runtime ok?

When would the underlying runtime not be available? In between the before_fork() and after_fork_* functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If a component blocking function (e.g. TraceExporter::send) requires a tokio runtime while we are preparing for a fork, we want to allow the component to access one to avoid losing data (e.g. the trace payload) without restarting the full runtime which we would have to shutdown again. The components should use the runtime with block_on so a current thread runtime will behave in the same way as the multi-threaded one. Since the SharedRuntime doesn't hold a reference to this new runtime, it will be dropped when the blocking function returns guarantying no runtime is running across the fork.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know if it's worth the trouble, but one possibility to avoid misuse here could be to revert the control and take a future and block on it, instead of providing a full runtime to use, if that's the intended use (so a block_on wrapper, mostly). This would constrain what the caller can actually do.

}

#[derive(Debug)]
pub enum WorkerHandleError {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should you impl std::error::Error for consistency with the other errors?

}

fn reset(&mut self) {
// Drain all messages from the channel to remove messages sent to release the reference on
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Drain all messages from the channel to remove messages sent to release the reference on
// Drain all messages from the channel to remove messages sent to release the reference on IoStack

/// Main worker loop
fn run(&mut self) -> impl std::future::Future<Output = ()> + Send;
/// # Lifecycle
/// The worker's `Self::run` method should be executed everytime the `Self::trigger` method returns.
Copy link
Contributor

Choose a reason for hiding this comment

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

Defining a bunch of rules in comments that are not enforced in code is a bit of a smell. Do we anticipate there being more than PausableWorker and perhaps something that is WASM compatible? If there is a small number of impls, probably not a big deal because it looks like the rules are enforced internally in the impl, and not something the consumer has to deal with.

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 thought of this comments to be aimed at people implementing the Worker trait, rather than for someone designing a Worker "runner" which for now is supposed to be only PausableWorker. Regarding WASM compatibility where using mostly std async stuff which should work the same, I'm not sure about the JoinHandle which are tokio specific but since node doesn't fork we may also provide an alternative implementation which doesn't support pausing the workers.

Copy link
Contributor

Choose a reason for hiding this comment

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

To add to the original comment: I believe it's not entirely clear from the wording if this is a constraint on the user/caller, or a guarantee that the implementer/callee needs to uphold.

Copy link
Contributor

Choose a reason for hiding this comment

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

None of these functions are using catch_panic. Is that intentional?

Copy link
Contributor

Choose a reason for hiding this comment

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

Why does this live in libdd-data-pipeline? If we don't want a dedicated crate, shouldn't it go in libdd-common?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right I'll move it to ddcommon

Copy link
Contributor

Choose a reason for hiding this comment

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

Applies to the whole PR: Should we pepper in some debug log messages? Debugging this kind of stuff is tricky.

Copy link
Contributor

@yannham yannham left a comment

Choose a reason for hiding this comment

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

I'm still missing a lot of context, so I can't really comment on the integration of the shared runtime and apologies in advance if some remarks or questions aren't relevant. Though the general motivation, the approach and the architecture do look very sensible.

/// Main worker loop
fn run(&mut self) -> impl std::future::Future<Output = ()> + Send;
/// # Lifecycle
/// The worker's `Self::run` method should be executed everytime the `Self::trigger` method returns.
Copy link
Contributor

Choose a reason for hiding this comment

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

To add to the original comment: I believe it's not entirely clear from the wording if this is a constraint on the user/caller, or a guarantee that the implementer/callee needs to uphold.

#[repr(C)]
pub struct SharedRuntimeFFIError {
pub code: SharedRuntimeErrorCode,
pub msg: *mut c_char,
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor: can msg be null here to denote an empty one, or is it guaranteed to always be defined? If the latter, maybe mention it.

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 msg is generated from the rust error to_string method so it should never be empty. I'll add a comment.

info_endpoint: Endpoint,
refresh_interval: Duration,
trigger_rx: Option<mpsc::Receiver<()>>,
trigger_tx: mpsc::Sender<()>,
Copy link
Contributor

Choose a reason for hiding this comment

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

naive question, but why does the agent info fetcher has both ends of the trigger channel? Is it something related to the phantom waker issue?

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 fetcher needs to send a message to the channel when paused to release the reference to the waker. Otherwise the waker prevents us from dropping the runtime's IoStack which causes issues on forks. @paullegranddc has a better solution here to which we should migrate at some point.

sleep(Duration::from_millis(100)).await;
})
exporter.shared_runtime.runtime().unwrap().block_on(async {
sleep(Duration::from_millis(100)).await;
Copy link
Contributor

Choose a reason for hiding this comment

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

Out of curiosity, why does this test use an async runtime to block on a sleep?

let worker_handle = ctx
.shared_runtime
.spawn_worker(stats_exporter)
.map_err(|e| anyhow::anyhow!(e.to_string()))?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Very minor: if e impl Display, anyhow! already handles the conversion I believe.

Suggested change
.map_err(|e| anyhow::anyhow!(e.to_string()))?;
.map_err(|e| anyhow::anyhow!(e))?;

/// This allows external code to spawn additional tasks on the runtime if needed.
///
/// # Warning
/// Since this method can return a single-threaded runtime it should only be use to
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Since this method can return a single-threaded runtime it should only be use to
/// Since this method can return a single-threaded runtime it should only be used to

///
/// # Errors
/// Returns an error if it fails to create a runtime.
pub fn runtime(&self) -> Result<Arc<Runtime>, io::Error> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know if it's worth the trouble, but one possibility to avoid misuse here could be to revert the control and take a future and block on it, instead of providing a full runtime to use, if that's the intended use (so a block_on wrapper, mostly). This would constrain what the caller can actually do.

Comment on lines +338 to +339
/// This function should not take ownership of the SharedRuntime as it will cause the runtime
/// to be dropped in a non-blocking context causing a panic.
Copy link
Contributor

Choose a reason for hiding this comment

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

I fear I don't get this comment. Is it something the caller must avoid? Or is it a statement, like "this function doesn't take ownership"? But then I'm not sure what does "this function takes ownership" means in this context, since it's an concrete implementation taking a &self.

/// # Time-to-pause
/// This loop should yield regularly to reduce time-to-pause. See [`tokio::task::yield_now`].
///
/// # Cancellation safety
Copy link
Contributor

Choose a reason for hiding this comment

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

Just to be sure: this requires the inner worker's various async function to return cancel-safe futures, right? Is this something any user of PausableWorker has to ensure when wrapping a worker into a pausable worker? If yes, maybe it could make sense to repeat it in the documentation of new().

As an aside, this sounds like a complicated constraint to enforce, as a user of PausableWorker: you basically have to carefully look at the implementation of the worker you use and make sure it's indeed cancel-safe, and any future change to this implementation could invalidate that assumption. It's just a random idea, but another approach could be to push the burden of the proof to the Worker implementers instead (Make a CanBePausedWorkerButWithABetterName: Worker marker trait, and have T: CanBePaused... + Send + Sync + 'static instead?), which allegedly know better if they are cancel safe. Or just add this constraint in Worker itself, requiring all implementers to uphold it, if in practice we expect all workers to be pausable.

let (worker_handle, worker) = self.build_worker(tokio_runtime.clone());

let join_handle = tokio_runtime.spawn(async move { worker.run().await });
let join_handle = tokio_runtime.spawn(async move { worker.run_loop().await });
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm probably missing context here, but why does this use the current tokio runtime directly instead of the shared runtime?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants