Skip to content

perf(light): resolve the opposite face once in the chunk propagator - #32

Merged
TheMeinerLP merged 1 commit into
mainfrom
perf/chunk-propagate
Aug 2, 2026
Merged

perf(light): resolve the opposite face once in the chunk propagator#32
TheMeinerLP merged 1 commit into
mainfrom
perf/chunk-propagate

Conversation

@TheMeinerLP

Copy link
Copy Markdown
Contributor

Applies the change from #28 to the second propagator. ChunkLightPropagator walks a whole chunk
rather than a single section, so its inner loop runs the same face.opposite() call — a switch over
the enum — once per face per queued position, six times for every block the light reaches. Resolving
it once at class load turns that into an array read.

The loop becomes indexed so the face and its opposite share an index. Nothing else changes; no
behaviour is affected, and the change cannot be slower than what it replaces.

What was measured

ChunkLightPropagatorBenchmark, both methods, all six parameter combinations, on two jars that
differ in this commit alone: origin/main at a09c71f (#26) against the same tree with this change.
#28 is absent from both, so the figures isolate this commit rather than the pair.

Two independent repeats per jar. A row counts as established only where both repeats of both jars
agree and the intervals do not overlap.

method sources/section sections base this change
propagate 1 4 76.06 ± 1.83 · 76.80 ± 4.18 64.08 ± 1.78 · 64.20 ± 1.31 −16.1 %
propagate 1 16 295.45 ± 6.59 · 292.76 ± 7.67 265.98 ± 6.64 · 266.40 ± 5.12 −9.5 %
propagate 1 24 476.10 ± 15.80 · 476.67 ± 7.14 410.30 ± 16.30 · 428.96 ± 19.95 −11.9 %
propagateSky 1 4 400.98 ± 5.81 · 410.41 ± 11.58 382.70 ± 10.15 · 374.58 ± 4.98 −6.7 %
propagateSky 8 16 1234.62 ± 36.80 · 1291.25 ± 40.76 1146.50 ± 37.86 · 1213.49 ± 34.37 −6.6 %
propagate 8 16 511.48 ± 37.05 · 481.19 ± 14.82 520.72 ± 18.82 · 473.56 ± 36.19 no effect
propagateSky 8 24 1752.23 ± 17.80 · 1825.61 ± 56.87 1656.45 ± 80.20 · 1754.85 ± 63.92 inside the spread

All figures µs/op, lower is better.

What the numbers do not say

The saving is a function of source density, not of chunk size. Where a section holds one light
source the queue is short and the per-neighbour work is a large share of the pass, and the change
shows between −9.5 % and −16.1 % across every section count. At eight sources per section more of
the pass goes into spreading light and the effect drops into the noise — propagate at 8 sources
and 16 sections measures no difference at all. The headline figure is one corner of the parameter
space, and quoting −16.1 % without the density it belongs to would be wrong.

Five of the twelve rows were discarded, not omitted. propagate at 8/4 and 8/24, and
propagateSky at 1/16, 1/24 and 8/4, each had one repeat whose interval exceeded a tenth of its own
score — up to ± 324 µs on a 966 µs score, and ± 1140 µs on one propagateSky run. Those repeats
measure the machine, not the code, and none of them is in the table above. They neither support nor
contradict it.

The machine was not idle. Load average during the series ran between 4 and 6 on 16 hardware
threads, from a browser, a file indexer and three language servers. That is the source of the five
discarded repeats, and it is why this is presented as a ratio between two jars measured under the
same conditions rather than as absolute microseconds. The five rows above survived that noise across
four independent runs each, which is the reason to believe them.

Where these numbers should come from instead

#29 and #31 landed after this branch was cut. The custom profile records cores, load_before
and load_after — precisely the conditions whose absence produced a false reading during this work,
before a re-measurement caught it. It cannot replace this particular comparison, because it builds
one jar from one commit and an A/B needs two, and its own provenance text is right that absolute
microseconds from a shared runner do not belong in a published table. But once a self-hosted
runner exists, running each side there and comparing within a runner is a better instrument than
this desktop.

Nothing here is proposed for Measured Results. The rows in the table are an argument for the
change, measured under conditions stated in full; they are not a published figure.

ChunkLightPropagatorBenchmark, 3 forks, 5 × 1 s warmup, 5 × 1 s measurement, -Xms512m -Xmx512m, JMH 1.37, JVM 25.0.3+9-LTS, AMD Ryzen 7 5800X (8 cores / 16 threads), load average 4–6
during the series — not idle, run on 2026-08-02, two repeats per jar. Raw JMH JSON available on
request.

Same change as in LightPropagator, on the loop that walks a whole chunk.
Measurement follows in the pull request.
@TheMeinerLP
TheMeinerLP requested a review from a team as a code owner August 2, 2026 15:20
@TheMeinerLP
TheMeinerLP merged commit d717ec8 into main Aug 2, 2026
6 checks passed
@TheMeinerLP
TheMeinerLP deleted the perf/chunk-propagate branch August 2, 2026 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant