Skip to content

Measured stack-heavy work against the memory holding the stack - #636

Merged
fdesbiens merged 1 commit into
eclipse-threadx:devfrom
fdesbiens:feature/r52-s32z280-deep-stack-measure
Aug 17, 2026
Merged

Measured stack-heavy work against the memory holding the stack#636
fdesbiens merged 1 commit into
eclipse-threadx:devfrom
fdesbiens:feature/r52-s32z280-deep-stack-measure

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

#635 found BTCM worth ~7.4% on a context switch with no determinism advantage, and explained why: a switch saves sixteen registers, roughly one cache line, so the stack's cache state has almost nothing to contribute. It named the interesting case — work with a large stack working set — said it had not been measured, and said it should not be assumed.

This measures it, and the answer inverts the earlier one.

Method

deep_touch recurses 24 frames, writing a frame on the way down and reading it on the way up, so the working set is the whole descent rather than one frame. The cache is cleaned and invalidated before each sample, so every descent starts cold.

Two threads, one stack in BTCM and one in DRAM0. No partner threads and no relinquish — the timed region is entirely within one thread, which removes the confound that made #635's numbers hard to read, where the timed region included the partner's execution.

Result

Reproducible across runs:

stack in min mean max spread
BTCM 42,868 43,031 44,890 2,020
DRAM0 42,982 43,291 49,842 6,860

The mean is the same to within 0.6%. The worst case is 10% lower for BTCM and the spread is 3.4× tighter.

No sample in either configuration exceeded twice the minimum (interrupted 0 of 64), so these maxima are the workload rather than a timer tick — the mistake that produced a false 16× jitter claim in #635, and the reason the interrupted count is printed.

Two measurements, opposite conclusions, both true

footprint throughput determinism
context switch (#635) ~1 cache line, every switch +7.4% none
stack-heavy work (this) 24 frames, once +0.6% 10% worst case, 3.4× spread

The reason is that this workload is compute-bound at the optimisation level this BSP builds at — 43,000 cycles for 24 frames is dominated by call and loop overhead, so line fills are a few percent of the total and barely move the mean. What they do is vary, and that variance is what a bank with no cache in the path removes.

For anyone citing this

The determinism argument for TCM does hold here, but it is worth 10% of worst case and a threefold narrowing of spread — not an order of magnitude. Cite those numbers, not a larger claim.

Verification

All three targets build clean with no warnings; the demo passes and the boot image still passes six of six probes. BTCM usage is 10,240 of 16,384 bytes.

eclipse-threadx#635 found BTCM worth about 7.4% on a context switch with no determinism
advantage, and said why: a switch saves sixteen registers, roughly one cache
line, so the stack's cache state has almost nothing to contribute. It named the
interesting case as work with a large stack working set, said it had not been
measured, and said it should not be assumed. This measures it, and the answer
inverts the earlier one.

deep_touch recurses 24 frames, writing a frame on the way down and reading it on
the way up, so the working set is the whole descent. The cache is cleaned and
invalidated before each sample, so every descent starts cold. Two threads, one
stack in BTCM and one in DRAM0, no partner threads and no relinquish: the timed
region is entirely within one thread.

Reproducible across runs:

                      min      mean      max     spread
    stack in BTCM   42868     43031    44890       2020
    stack in DRAM0  42982     43291    49842       6860

The mean is the same to within 0.6%. The worst case is 10% lower for BTCM and
the spread is 3.4 times tighter. No sample in either configuration exceeded
twice the minimum, so these maxima are the workload rather than a timer tick --
which is the mistake that produced a false jitter result in eclipse-threadx#635 and is why the
count of interrupted samples is printed.

Put beside eclipse-threadx#635 the two measurements say opposite things and both are true.
For a context switch, a small footprint touched every time, BTCM buys throughput
and no determinism. For stack-heavy work, a large footprint touched once, it
buys determinism and almost no throughput.

The reason is that this workload is compute bound at the optimisation level this
BSP builds at: 43000 cycles for 24 frames is dominated by call and loop overhead,
so line fills are a few percent of the total and barely move the mean. What they
do is vary, and that variance is what a bank with no cache in the path removes.

So the determinism argument for TCM holds here, but it is worth 10% of worst case
and a threefold narrowing of spread, not an order of magnitude. Anyone citing
this in a safety argument should cite those numbers and not a larger claim.

Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com>
@fdesbiens
fdesbiens merged commit f535a4e into eclipse-threadx:dev Aug 17, 2026
4 checks passed
fdesbiens added a commit that referenced this pull request Aug 18, 2026
…s result (#638)

#636 reported that a stack in BTCM gave a threefold tighter spread than DRAM0
for stack-heavy work. That measurement used a single code placement, which is
the methodology #631 and #633 exist to correct: the cache benchmark got an
alignment sweep and the interrupt handler got one, and this measurement never
did. It was noticed when #637 added two threads to the same image and the figure
moved -- both spreads came out near 6500 and the minima rose 15%.

The recursive body is now generated at four placements and all four are
measured, per placement, in one image.

    placement    BTCM min / spread     DRAM0 min / spread
    offset 0      41854 / 6850          42036 / 6880
    offset 16     48670 / 1946          48792 / 1978
    offset 32     42388 / 6914          42752 / 7018
    offset 48     48914 / 1860          49198 / 6786

Reproducible across runs to within a few hundred cycles.

Spread is dominated by code placement rather than by the memory holding the
stack. It ranges from 1860 to 6914 depending on where the body falls in a cache
line, and placement also moves the minimum by 17%, from 41854 to 49214. Against
that, the memory contributes a consistent but small advantage: BTCM's minimum is
lower at all four placements, by 0.4% to 0.9%.

BTCM's spread beats DRAM0's decisively at one placement of the four, offset 48,
at 1860 against 6786. At the other three the two are within 2% of each other.
So the effect #636 reported is real where it occurs and is not a property of the
part: quoting it as one invited the reader to expect it everywhere.

#636's claim should be read as qualified by this. A stack in BTCM buys a small
consistent improvement in the best case and a large improvement in spread at
some code placements and not others. Anyone building a determinism argument on
it needs the placement sweep in the loop, not a single figure.

The pad nops that displace each placement execute on every recursion level
rather than once, so each placement carries a slightly different constant cost,
about 0.6% at the widest. That cancels in the BTCM against DRAM0 comparison,
which is made at the same placement, and does not affect spread within one.

Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com>
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