RotationScaleMerge::RunArm: free the fulls before growing them

When a chain needs more fulls than the arrays hold, fulls and fulls_staging are released before the
resize. The gather overwrites every field, so growing in place only copied the previous chain's
records into the new allocation to be overwritten.

The expected saving (a few tenths of a second on 8tyy) is below the run-to-run noise of the wall
clock: 8tyy median of 3, 127.0 s without vs 129.6 s with, under different machine load. 8qaw max RSS
21.9 -> 21.7 GB.

p.mtz md5-identical to rc175 on myoglobin, cytochrome C (also at -N 4 and -N 8), thaumatin, 8a1a,
8tyy, 9gdj and 8qaw.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SVmAWnzCmRKAXVUCdc4iNi
This commit is contained in:
2026-10-07 12:11:21 +02:00
co-authored by Claude Opus 5.5
parent 1907f47368
commit 5282dd6199
@@ -6476,7 +6476,13 @@ RotationScaleMerge::Result RotationScaleMerge::RunArm(bool scale_partials, bool
// resize, not assign: the gather below writes every field of every full, so zeroing 80 bytes
// each first is a few hundred megabytes of pure write traffic per chain. The staging arrays are
// members for the same reason.
// members for the same reason. Nothing in them survives the gather either, so when they have
// to grow they are freed first: growing in place would copy the previous chain's records into
// the new allocation only for the gather to overwrite them.
if (static_cast<size_t>(nf) > fulls.capacity()) {
fulls = {};
fulls_staging = {};
}
fulls.resize(nf);
FullsStaging &st = fulls_staging;
st.Resize(nf);