#32: RETRACT the retention diagnosis; count what matters (steals + true drops); name the saturating class
The reopen said "the pool fills and never returns a source". The 30s census in
the SAME field logs disproves it: free returns to ~227-230 between bursts and
reuses climbs ~20/s all session. free=0 on the failure line is true by
DEFINITION at the instant of a failed acquire -- the third instance of the
counter-sampling trap (live=256-vs-6, then hsparm greps, now this), read off the
alarm line instead of the trend line.
WHAT THE LOGS ACTUALLY SHOW
* The pool cycles; release-on-stop exists and works (the engine steal loop).
* During firefights CONCURRENT demand exceeds 240 and the priority steal loop
services each new sound by killing an old one -- continuously through
combat (failures spread across every decile of every combat session).
* Idle standing demand is ~13 sources. My "each component holds its SourceSet
to entity teardown, ~20-25 per mech" narrative was wrong.
* The raw ACQUIRE FAILED line count (6.8k-19k per log) is NOISE: the steal
loop retries after every failed attempt, so lines accumulate per EVENT and
most events still play via a steal. True drops were never counted.
CHANGES
1. Census now carries steals= and drops= (drops = the steal loop ran dry and
the sound NEVER played) plus a per-class drop histogram
("[audio] dropped by class: {class 1005 x4v: N} ...") -- all ungated, so
the next field logs are decisive instead of suggestive.
2. The ACQUIRE FAILED print is rate-limited to 1/30s and now names the
requesting class + voice count. 19k-line log spam distorted this triage.
3. BT_AUDIO_SOURCES=<n> now raises the POOL cap too (it previously raised the
AL context budget while the pool stayed at 240, making the field
experiment impossible to run).
MEASURED (9 mechs, missile autofire, 150s)
* cap 240: peak 130 sources, 0 fails -- demand tracks SHOOTER count, not mech
count; one shooter cannot saturate. A 6-shooter lobby pins 240.
* cap 48 (BT_AUDIO_SOURCES=64): saturation reproduced -- census
steals=223 drops=455, histogram names the classes.
* Dominant field requester (requested=4) = class 1005 Static3DPatchSource:
world-placed effect sounds, i.e. EXPLOSIONS. 1001 DirectPatchSource x1v
dominates drops at low cap; 1002 Dynamic3DPatchSource x3v present.
CONSEQUENCE FOR THE FIX ORDER: #84's stale-aim double detonation duplicates
exactly the saturating class on observer nodes. Fix #84 FIRST, then re-read the
field census; only if it still saturates does the budget experiment
(BT_AUDIO_SOURCES with frame time measured) become the play.
KB: the wrong night-9 entry in open-questions.md replaced with the corrected
diagnosis; gotcha candidate noted -- an alarm-line counter is not a trend.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
202ebbf84a
commit
3354db4bd1
+26
-11
@@ -1034,17 +1034,32 @@ contributions already:
|
||||
see — an authored record that resolves with no distinct behaviour to
|
||||
reconstruct. Mike L. could confirm. (Gitea #104.)
|
||||
|
||||
**AUDIO SOURCE POOLING IS NOT FIXED — retention, not churn, is the wall** [T2].
|
||||
The `#32` pooling change removed the per-sound `alGenSources`/`alDeleteSources`
|
||||
churn (a real ~10% frame-time win) but every 693 field log still shows
|
||||
`ACQUIRE FAILED (requested=4 live=240 pooled=240 free=0 ...)`
|
||||
19,182 fails (Sauron) / 15,333 (Rajel) / 6,818 (Ronin), high-water **225 of 240**,
|
||||
starting ~1% into the session. `free=0` is the diagnosis: the pool fills and never
|
||||
returns a source. Each audio component reserves a SourceSet of up to 25 voices and
|
||||
holds it to entity teardown, so peak demand scales with live audio COMPONENTS, not
|
||||
audible sounds. A bigger cap only delays the wall. ⚠ Players reported audio as
|
||||
"working fine" the same night — subjective impressions do not clear this class of
|
||||
bug; read the log.
|
||||
**AUDIO #32, CORRECTED DIAGNOSIS (2026-08-02): saturation during combat, NOT
|
||||
retention** [T2 — census-measured]. An earlier version of this entry claimed the
|
||||
pool "fills and never returns a source"; that was read off the FAILURE line, where
|
||||
`free=0` is true by definition (a third instance of the counter-sampling trap).
|
||||
The 30-second census in the same logs disproves it: `free` returns to ~227-230
|
||||
between bursts and `reuses` climbs ~20/s all session — the pool cycles fine, and
|
||||
release-on-stop exists and works (the engine's steal loop:
|
||||
AudioSourceStop/SuspendMaintenance -> ReleaseChannels -> ReleaseSourceSet).
|
||||
* The real regime: during firefights CONCURRENT demand exceeds the 240 cap and
|
||||
the priority steal loop services each new sound by killing an old one,
|
||||
thousands of times per combat session. Idle standing demand is only ~13.
|
||||
* The raw `ACQUIRE FAILED` line count (6.8k-19k/log) is NOISE — the steal loop
|
||||
retries after every failed attempt, so lines pile up per event and most
|
||||
events still play via a steal. It is now rate-limited (1/30s) and the census
|
||||
carries the true metrics: `steals=` and `drops=` (drops = the steal loop ran
|
||||
dry and the sound NEVER played), plus a per-class drop histogram.
|
||||
* The saturating requester is class 1005 = **Static3DPatchSource, 4 voices** —
|
||||
world-placed effect sounds, i.e. EXPLOSIONS/impacts. Demand tracks the
|
||||
number of SHOOTERS (9-mech one-shooter bench peaks at 130 with 0 fails; a
|
||||
6-shooter field lobby pins 240). **#84's double detonation doubles exactly
|
||||
this class on observer nodes** — fix #84 first, then re-read the field
|
||||
census before touching the audio budget.
|
||||
* `BT_AUDIO_SOURCES=<n>` now raises the POOL cap too, not just the AL context
|
||||
budget (it previously did only the latter, making the experiment
|
||||
impossible). If post-#84 logs still saturate, that is the field experiment
|
||||
— with frame time measured, since more concurrent voices = more mixing CPU.
|
||||
|
||||
**Reading the missile impact line.** `[projectile] IMPACT damage=X ... burst=N`
|
||||
prints X = **per missile**; the delivered total is `X * N`. A tester reading X
|
||||
|
||||
Reference in New Issue
Block a user