Skip to content

Optimize Transform evaluation with re-entrant TLS scratch buffers#345

Merged
nsmith- merged 7 commits into
masterfrom
transform_noalloc
Jun 15, 2026
Merged

Optimize Transform evaluation with re-entrant TLS scratch buffers#345
nsmith- merged 7 commits into
masterfrom
transform_noalloc

Conversation

@nsmith-

@nsmith- nsmith- commented May 17, 2026

Copy link
Copy Markdown
Collaborator

Developed with LLM help, if it is not already obvious from the below 😄

Summary

Eliminate hot-path allocations in evaluate loops

This branch removes several std::vector heap allocations that occurred on every call to the core evaluate paths:

  • Transform::evaluate — replaced the per-call std::vectorVariable::Type new_values(values) copy with a thread-local slot pool (TransformScratch). A std::deque of slots indexed by recursion depth makes this safe for nested Transform evaluations.
  • CompoundCorrection::evaluate — replaced the per-call construction of ivalues and cvalues with thread-local statics that are reused across calls.
  • Category::evaluate — replaced map_.at() inside a try-catch (exception unwinding allocates) with an explicit find() check, eliminating exception overhead on every category lookup.
  • find_bin_idx — elided an unnecessary copy of _NonUniformBins by taking a const&.

A regression test for nested Transform correctness is included.

Details for TransformScratch

  • Added TransformScratch (anonymous namespace in src/correction.cc) with:
  • thread-local slot storage (std::vector<std::vector<Variable::Type>>)
  • thread-local recursion depth index
  • RAII acquire/release semantics for exception-safe depth unwind
  • Updated Transform::evaluate to:
    • acquire a per-depth scratch slot
    • copy values into the slot
    • mutate only the selected transformed input
    • evaluate child content using the scratch-backed vector

This keeps nested Transform evaluation on the same thread safe while reusing vector capacity across calls.

Design alternatives considered (pros/cons)

  1. Move-callable Correction::evaluate API
  • Pros:
    • Establishes a clear ownership boundary for the input buffer.
    • Makes it possible to keep one mutable working buffer per top-level call.
    • Can remove per-Transform copies if Transform mutates and restores in place.
  • Cons:
    • Requires a public API change and caller updates.
    • Rvalue-only shape is inconvenient for common lvalue call sites.
    • A by-value variant is less disruptive but still changes the API contract.
  1. Mutable reference in node_evaluate
  • Pros:
    • Avoids repeated copying when paired with in-place mutate/restore in Transform.
    • Has low runtime overhead in the hot path.
  • Cons:
    • Unsafe unless the referenced buffer is guaranteed to be owned/mutable.
    • Increases risk of accidental mutation of caller-provided inputs.
    • Weakens the current read-only mental model in evaluator traversal.
  1. One initial TLS copy in Correction::evaluate, pass mutable state downward
  • Pros:
    • Reduces copy frequency to once per top-level evaluation.
    • Likely faster for trees with many Transform nodes.
    • Keeps the public API unchanged.
  • Cons:
    • Single-slot TLS is not re-entrant-safe.
    • Relies on a non-reentrancy assumption that may not hold forever.
    • Introduces hidden lifetime/state coupling at a high layer.
  1. Current depth-indexed re-entrant TLS in Transform
  • Pros:
    • Correct for nested Transform recursion on the same thread.
    • No public API changes.
    • Localized implementation with good exception safety via RAII.
  • Cons:
    • Still performs a copy per Transform node.
    • May underperform a one-copy-per-top-level-call design for Transform-heavy trees.

Notes

  • This PR chooses the conservative/safe option now (approach 4).
  • A future internal refactor to a stack-owned evaluation context could further reduce copies without breaking public API.

Use a re-entrancy safe thread local storage for intermediate results.
@nsmith-

nsmith- commented May 17, 2026

Copy link
Copy Markdown
Collaborator Author

@ikrommyd FYI
Since you were noticing the heavy allocations, can you try to see if this PR makes any improvement in performance other than reducing allocation count?

@github-actions

github-actions Bot commented May 17, 2026

Copy link
Copy Markdown

CVMFS benchmarks

Top 25 slowest-loading corrections, sorted by mean time:

Benchmark Mean (ms) Stddev (ms) Rounds
test_load[JME/Run2-2017-UL-NanoAODv9/latest/jet_jerc.json.gz] 1001.701 4.166 5
test_load[JME/Run2-2017-UL-NanoAODv9/latest/fatJet_jerc.json.gz] 849.855 27.099 5
test_load[JME/Run3-24Prompt-Winter24-NanoAODv14/latest/jet_jerc.json.gz] 681.847 6.372 5
test_load[JME/Run3-24CDEReprocessingFGHIPrompt-Summer24-NanoAODv15/latest/jet_jerc.json.gz] 596.469 3.563 5
test_load[JME/Run3-24CDEReprocessingFGHIPrompt-Summer24-NanoAODv15/latest/fatJet_jerc.json.gz] 593.246 0.822 5
test_load[JME/Run3-25Prompt-Winter25-NanoAODv15/latest/jet_jerc.json.gz] 402.502 2.338 5
test_load[JME/Run3-25Prompt-Winter25-NanoAODv15/latest/fatJet_jerc.json.gz] 402.366 2.527 5
test_load[JME/Run2-2018-UL-NanoAODv9/latest/jet_jerc.json.gz] 339.607 1.648 5
test_load[JME/Run3-23CSep23-Summer23-NanoAODv12/latest/fatJet_jerc.json.gz] 336.343 1.586 5
test_load[JME/Run3-23CSep23-Summer23-NanoAODv12/latest/jet_jerc.json.gz] 333.180 2.498 5
test_load[JME/Run2-2016preVFP-UL-NanoAODv9/latest/jet_jerc.json.gz] 276.101 0.677 5
test_load[JME/Run2-2018-UL-NanoAODv9/latest/fatJet_jerc.json.gz] 263.168 1.209 5
test_load[JME/Run3-22EFGSep23-Summer22EE-NanoAODv12/latest/jet_jerc.json.gz] 261.717 8.488 5
test_load[JME/Run3-22EFGSep23-Summer22EE-NanoAODv12/latest/fatJet_jerc.json.gz] 257.473 1.503 5
test_load[JME/Run2-2016postVFP-UL-NanoAODv9/latest/jet_jerc.json.gz] 254.356 0.892 5
test_load[JME/Run3-23DSep23-Summer23BPix-NanoAODv12/latest/fatJet_jerc.json.gz] 240.838 6.164 5
test_load[JME/Run2-2016preVFP-UL-NanoAODv9/latest/fatJet_jerc.json.gz] 237.902 1.683 5
test_load[JME/Run3-23DSep23-Summer23BPix-NanoAODv12/latest/jet_jerc.json.gz] 236.630 1.231 5
test_load[JME/Run2-2017-UL-NanoAODv15/latest/jet_jerc.json.gz] 233.175 6.291 5
test_load[JME/Run2-2017-UL-NanoAODv15/latest/fatJet_jerc.json.gz] 230.681 0.336 5
test_load[JME/Run3-22Prompt-Winter22-NanoAODv12/latest/fatJet_jerc.json.gz] 224.460 1.857 5
test_load[JME/Run2-2016postVFP-UL-NanoAODv9/latest/fatJet_jerc.json.gz] 223.958 0.713 5
test_load[JME/Run3-22Prompt-Winter22-NanoAODv12/latest/jet_jerc.json.gz] 222.962 0.453 5
test_load[JME/Run2-2018-UL-NanoAODv15/latest/jet_jerc.json.gz] 221.308 0.631 5
test_load[JME/Run2-2018-UL-NanoAODv15/latest/fatJet_jerc.json.gz] 220.865 0.453 5

Otherwise, when the vector grows beyond capacity, all existing
references become invalid
@ikrommyd

ikrommyd commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

So I'm seeing this reduction in the number of allocations of my analysis with this PR 400093149 -> 369875546.
That's a 7.5% decrease. It's something but it looks like correctionlib is allocating a lot still anyways. Perhaps that's just necessary due to the sheer number of times evaluate is called in the analysis.
Before:

❯ memray stats -n 20 output.bin
📏 Total allocations:
        400093149

📦 Total memory allocated:
        639.939GB

📈 Peak memory usage:
        2.584GB

📊 Histogram of allocation size:
        min: 1.000B
        ------------------------------------------------
        < 8.000B   :  36319683 ▇▇▇▇
        < 64.000B  : 253460132 ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇
        < 512.000B :  96390629 ▇▇▇▇▇▇▇▇▇▇
        < 4.096kB  :  12445393 ▇▇
        < 32.768kB :    350630 ▇
        < 262.153kB:    353459 ▇
        < 2.097MB  :    751307 ▇
        < 16.778MB :     18133 ▇
        < 134.225MB:      3782 ▇
        <=1.074GB  :         1 ▇
        ------------------------------------------------
        max: 1.074GB

📂 Allocator type distribution:
         MALLOC: 396818135
         REALLOC: 3170552
         POSIX_MEMALIGN: 90810
         CALLOC: 13437
         MMAP: 215

🥇 Top 20 largest allocating locations (by size):
        - empty:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:153 -> 258.807GB
        - astype:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:758 -> 42.662GB
        - _wrapfunc:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/numpy/_core/fromnumeric.py:54 -> 41.095GB
        - read:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/gzip.py:578 -> 34.039GB
        - __init__:/home/iason/Dropbox/work/pyhep_dev/correctionlib/src/correctionlib/highlevel.py:350 -> 26.309GB
        - concat:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:510 -> 25.883GB
        - _call_as_numpy:/home/iason/Dropbox/work/pyhep_dev/correctionlib/src/correctionlib/highlevel.py:96 -> 23.524GB
        - _recursively_apply:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/contents/listoffsetarray.py:2224 -> 19.197GB
        - _carry:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/contents/numpyarray.py:370 -> 18.804GB
        - _apply_ufunc_nep_50:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:289 -> 16.494GB
        - arange:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:203 -> 14.520GB
        - __getitem__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/virtual.py:341 -> 13.533GB
        - _broadcast_tooffsets64:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/contents/regulararray.py:454 -> 9.302GB
        - decode:<frozen codecs>:325 -> 9.044GB
        - readall:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/compression/_common/_streams.py:121 -> 8.991GB
        - _recursively_apply:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/contents/indexedoptionarray.py:1670 -> 8.427GB
        - _normalise_item_bool_to_int:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_slicing.py:521 -> 8.241GB
        - __getitem__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/index.py:249 -> 7.036GB
        - asarray:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:87 -> 6.500GB
        - array_equal:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/numpy/_core/numeric.py:2601 -> 5.295GB

🥇 Top 20 largest allocating locations (by number of allocations):
        - _call_as_numpy:/home/iason/Dropbox/work/pyhep_dev/correctionlib/src/correctionlib/highlevel.py:96 -> 222869404
        - __init__:/home/iason/Dropbox/work/pyhep_dev/correctionlib/src/correctionlib/highlevel.py:350 -> 134768486
        - __call__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_kernels.py:98 -> 18768749
        - model_dump_json:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/pydantic/main.py:542 -> 8075686
        - __getitem__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/contents/content.py:532 -> 4912520
        - write_table:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/pyarrow/parquet/core.py:1213 -> 2577117
        - empty:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:153 -> 843857
        - model_validate:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/pydantic/main.py:732 -> 838515
        - __call__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/llvmlite/binding/ffi.py:212 -> 705289
        - _impl:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/operations/ak_from_iter.py:102 -> 677405
        - _impl:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/operations/ak_from_iter.py:100 -> 516447
        - __init__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/pyarrow/parquet/core.py:1115 -> 404924
        - __getitem__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/pandas/core/arrays/arrow/array.py:799 -> 347058
        - doDecorr:/home/iason/Dropbox/work/Hgg/HiggsDNA/higgs_dna/tools/decorrelator.py:106 -> 315522
        - close:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/pyarrow/parquet/core.py:1220 -> 293034
        - _impl:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/operations/ak_from_iter.py:99 -> 282125
        - decompress:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/uproot/compression.py:205 -> 145751
        - dump_ak_array:/home/iason/Dropbox/work/Hgg/HiggsDNA/higgs_dna/utils/dumping_utils.py:164 -> 125092
        - __getitem__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/highlevel.py:1114 -> 122525
        - _to_arrow:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/contents/numpyarray.py:1243 -> 114032

After:

❯ memray stats -n 20 output.bin
📏 Total allocations:
        369875546

📦 Total memory allocated:
        629.251GB

📈 Peak memory usage:
        2.585GB

📊 Histogram of allocation size:
        min: 1.000B
        ------------------------------------------------
        < 8.000B   :  36319685 ▇▇▇▇
        < 64.000B  : 253460132 ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇
        < 512.000B :  66173022 ▇▇▇▇▇▇▇
        < 4.096kB  :  12445393 ▇▇
        < 32.768kB :    350631 ▇
        < 262.153kB:    353460 ▇
        < 2.097MB  :    751307 ▇
        < 16.778MB :     18133 ▇
        < 134.225MB:      3782 ▇
        <=1.074GB  :         1 ▇
        ------------------------------------------------
        max: 1.074GB

📂 Allocator type distribution:
         MALLOC: 366600530
         REALLOC: 3170553
         POSIX_MEMALIGN: 90810
         CALLOC: 13438
         MMAP: 215

🥇 Top 20 largest allocating locations (by size):
        - empty:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:153 -> 258.807GB
        - astype:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:758 -> 42.662GB
        - _wrapfunc:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/numpy/_core/fromnumeric.py:54 -> 41.095GB
        - read:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/gzip.py:578 -> 34.039GB
        - __init__:/home/iason/Dropbox/work/pyhep_dev/correctionlib/src/correctionlib/highlevel.py:350 -> 26.309GB
        - concat:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:510 -> 25.883GB
        - _recursively_apply:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/contents/listoffsetarray.py:2224 -> 19.197GB
        - _carry:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/contents/numpyarray.py:370 -> 18.804GB
        - _apply_ufunc_nep_50:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:289 -> 16.494GB
        - arange:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:203 -> 14.520GB
        - __getitem__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/virtual.py:341 -> 13.533GB
        - _call_as_numpy:/home/iason/Dropbox/work/pyhep_dev/correctionlib/src/correctionlib/highlevel.py:96 -> 12.836GB
        - _broadcast_tooffsets64:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/contents/regulararray.py:454 -> 9.302GB
        - decode:<frozen codecs>:325 -> 9.044GB
        - readall:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/compression/_common/_streams.py:121 -> 8.991GB
        - _recursively_apply:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/contents/indexedoptionarray.py:1670 -> 8.427GB
        - _normalise_item_bool_to_int:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_slicing.py:521 -> 8.241GB
        - __getitem__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/index.py:249 -> 7.036GB
        - asarray:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:87 -> 6.500GB
        - array_equal:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/numpy/_core/numeric.py:2601 -> 5.295GB

🥇 Top 20 largest allocating locations (by number of allocations):
        - _call_as_numpy:/home/iason/Dropbox/work/pyhep_dev/correctionlib/src/correctionlib/highlevel.py:96 -> 192651721
        - __init__:/home/iason/Dropbox/work/pyhep_dev/correctionlib/src/correctionlib/highlevel.py:350 -> 134768486
        - __call__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_kernels.py:98 -> 18768749
        - model_dump_json:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/pydantic/main.py:542 -> 8075686
        - __getitem__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/contents/content.py:532 -> 4912520
        - write_table:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/pyarrow/parquet/core.py:1213 -> 2577117
        - empty:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/_nplikes/array_module.py:153 -> 843857
        - model_validate:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/pydantic/main.py:732 -> 838515
        - __call__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/llvmlite/binding/ffi.py:212 -> 705364
        - _impl:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/operations/ak_from_iter.py:102 -> 677405
        - _impl:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/operations/ak_from_iter.py:100 -> 516447
        - __init__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/pyarrow/parquet/core.py:1115 -> 404924
        - __getitem__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/pandas/core/arrays/arrow/array.py:799 -> 347058
        - doDecorr:/home/iason/Dropbox/work/Hgg/HiggsDNA/higgs_dna/tools/decorrelator.py:106 -> 315522
        - close:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/pyarrow/parquet/core.py:1220 -> 293034
        - _impl:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/operations/ak_from_iter.py:99 -> 282125
        - decompress:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/uproot/compression.py:205 -> 145751
        - dump_ak_array:/home/iason/Dropbox/work/Hgg/HiggsDNA/higgs_dna/utils/dumping_utils.py:164 -> 125092
        - __getitem__:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/highlevel.py:1114 -> 122525
        - _to_arrow:/home/iason/micromamba/envs/coffea-202x/lib/python3.14/site-packages/awkward/contents/numpyarray.py:1243 -> 114032

@ikrommyd

ikrommyd commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

I did not notice any observable performance changes. The analysis takes the same time to run within statistical errors. Now I don't know if you benchmarked the transform node in particular and found it faster, but I assume that the actual analysis' runtime is heavily dominated by other factors so the reduction in the number of allocations is not a noticeable performance improvement in runtime.

@nsmith-

nsmith- commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator Author

Ok, thanks for testing. I'm surprised in only dropped a little; maybe I'm mistaken in understanding where the allocations are happening. Will actually measure rather than shoot from the hip here...

@ikrommyd

ikrommyd commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Yeah so the above stats are by wrapping the processor call MyProcessor().process(events) with a memray tracker.
It shows line 96 and line 350 of highlevel.py as the major allocation points when it comes to number of allocations and size. Line 350 is a bit surprising to me cause that is self._base = correctionlib._core.CorrectionSet.from_string(self._data).
Line 96 is the normal correction function call with func being corr._base.evalv.

memray can trace native call stacks and attach them to python call stacks (has a harder time on macos than linux) but when you do memray flamegraph/table or something, it gives you bath the flamegraph or table at the high water mark. At the high water mark in HiggsDNA, most heap memory has been allocated from torch and xgboost so I can't see the correctionlib allocations in there in the flamegraph or the table to see the native call stack underneath them.

Perhaps there's a way to say "I want the flamegraph only for this module" or something to memray but I wasn't able to find it in their API. Another solution would be to instrument correctionlib highlevel.py with a memray tracker so that only memory allocations in this module are tracked and you'd probably be able to see the native stacks easier in the flamegraph.

Edit: I will try with --aggregate which as far as I understand aggregates all the allocations so that should probably make correctionlib visible in the flamegraphs and also try with --temporary-allocations during memray flamegraph

  --temporary-allocation-threshold N
                        Report temporary allocations, as opposed to leaked allocations or high watermark allocations. An allocation is considered temporary if at most N other
                        allocations occur before it is deallocated. With N=0, an allocation is temporary only if it is immediately deallocated before any other allocation
                        occurs.
  --temporary-allocations
                        Equivalent to --temporary-allocation-threshold=1

@nsmith- nsmith- added this pull request to the merge queue Jun 15, 2026
Merged via the queue into master with commit 5df11df Jun 15, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants