Phase 19: measure graph scaling and guard capacity and contention behavior
This commit is contained in:
parent
1369e4d463
commit
6b85f28add
9 changed files with 639 additions and 3 deletions
|
|
@ -33,3 +33,59 @@ the API cannot enforce an extension's memory budget. There is no CPU overload
|
|||
scheduler, disk streaming, latency compensation or callback allocator audit of
|
||||
arbitrary third-party code. High-density interactive projects, physical devices,
|
||||
long-duration stereo/recording and live server termination remain unqualified.
|
||||
|
||||
## Phase 19 matrix, capacity and contention checks
|
||||
|
||||
`make benchmark` records 24 warmed graph cases: 2/16/64/256 nodes, mono/stereo,
|
||||
44.1k/31, 48k/128 and 96k/1024. Each reports control-thread compile time separately
|
||||
from 300 process calls, mean/p99/max, block deadline, mean load, and paired graph
|
||||
buffer bytes. Timing, sorting, allocation and logging happen outside processing.
|
||||
Metered gain chains test graph scaling; they do not represent expensive plugins.
|
||||
The checked-in `performance-baseline.json` records CPU/compiler/flags/kernel and
|
||||
all measurements. Copy a new run only after reviewing changes and conditions.
|
||||
|
||||
```sh
|
||||
make benchmark test-performance test-scale test-stress
|
||||
make benchmark-compare BENCHMARK_MAX_REGRESSION=1.5
|
||||
# Select a baseline from this same host/compiler/flags:
|
||||
make benchmark-compare BENCHMARK_BASELINE=/path/to/performance.json
|
||||
```
|
||||
|
||||
Comparison rejects mismatched CPU/architecture/compiler/flags or missing cases.
|
||||
It fails if mean time exceeds both the ratio budget and a 1 microsecond absolute
|
||||
noise allowance. p99/max are reported for investigation, not universally gated.
|
||||
Repeat surprising results under comparable load; do not silently replace the
|
||||
baseline to make a regression disappear. Scheduling, clocks, thermal state and
|
||||
shared-machine contention still affect results. No real-time scheduling/pinning
|
||||
or external profiler is required. CPU-pressure runs are correctness checks, not
|
||||
comparable timing baselines. Tests/benchmark outputs live below BUILD_DIR.
|
||||
|
||||
Initial matrix (Threadripper 1920X, GCC 16.2.1, -O2, 300 blocks): 256-node stereo
|
||||
48k/128 mean 353.214 us, p99 396.495 us, load .132; 96k/1024 mean 2478.520 us,
|
||||
p99 3092.434 us, load .232. The full JSON is the evidence. These met the local
|
||||
investigation target of mean load <.5 for ordinary graph chains; this is a
|
||||
host-specific development target, not a supported maximum CPU or latency promise.
|
||||
|
||||
The mixed 64-node/4096-note workload measured 340–357 us before removing unused
|
||||
live-controller processing and 313 us after (mean over 2000 blocks); p99 varied
|
||||
with system load. The measured hot-path change skips live voices/controller ramps
|
||||
when neither is active and avoids finished-ramp calls. Exact CC/odd-block tests
|
||||
continue to pass. No other graph optimization was justified by this measurement.
|
||||
|
||||
`test-scale` constructs all 64 tracks, 1024 clips, 1024 automation points and
|
||||
4096 notes, compiles a standalone 256-node metered graph, renders stereo odd-sized
|
||||
blocks and rejects capacity excesses. Project/GUI graphs remain capped at 64
|
||||
nodes. `test-stress` runs publication, allocation/retirement, capacity and optional
|
||||
GUI/timer/redraw tests while two ordinary CPU workers compete; subprocesses have
|
||||
timeouts and workers are always terminated. Existing callback guards verify no
|
||||
host allocation/free/loading/unloading. This does not qualify arbitrary plugins.
|
||||
|
||||
Callback work is bounded by documented node/frame/clip/note/event/point capacities.
|
||||
Exceeding model/plan/mailbox capacities returns CAPACITY transactionally; invalid
|
||||
or overlarge processing buffers are silenced and reported, JACK xruns are counted.
|
||||
There is no CPU scheduler or preemption inside a DSP callback: an expensive trusted
|
||||
plugin can miss a deadline or hang. Automated LADSPA lanes currently use run(1)
|
||||
and bounded per-sample lane searches and may be costly; they are excluded from
|
||||
the gain-chain baseline. Large WAV memory limits remain those in AUDIO_FILES.md.
|
||||
Physical-device endurance, CPU-overload sound quality and a full GUI latency
|
||||
benchmark remain unqualified.
|
||||
|
|
|
|||
|
|
@ -416,6 +416,14 @@ path bounds, post-rename sync errors and physical power-loss limits are explicit
|
|||
- Overload behavior is defined and does not cause unbounded work in the callback.
|
||||
- Significant performance regressions can be detected through repeatable tests.
|
||||
|
||||
Implemented: 24-case node/channel/rate/block matrix with separate compilation
|
||||
and warmed process timings, recorded machine/compiler baseline and opt-in
|
||||
regression budgets; maximum track/clip/note/automation/meter capacity checks and
|
||||
publication/GUI tests under CPU contention. Measurements justified skipping
|
||||
unused live-controller processing; exact output tests remain passing. See
|
||||
PERFORMANCE.md and performance-baseline.json for results, thresholds and overload
|
||||
policy. Arbitrary plugin costs and physical realtime/endurance are unqualified.
|
||||
|
||||
## Phase 20 — Release Engineering, Packaging, and Maintenance
|
||||
|
||||
**Goal:** Make the application straightforward to build, install, use, diagnose, and maintain.
|
||||
|
|
|
|||
349
docs/performance-baseline.json
Normal file
349
docs/performance-baseline.json
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
{
|
||||
"schema": 1,
|
||||
"context": {
|
||||
"cpu": "AMD Ryzen Threadripper 1920X 12-Core Processor",
|
||||
"architecture": "x86_64",
|
||||
"compiler": "cc (GCC) 16.2.1 20260810",
|
||||
"flags": "-O2 -g -std=c99 -Wall -Wextra -Wpedantic -Wconversion -Wshadow -Iinclude",
|
||||
"kernel": "7.2.11-artix1-1",
|
||||
"scheduler": "ordinary process; no realtime scheduling"
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"nodes": 2,
|
||||
"channels": 1,
|
||||
"rate": 44100,
|
||||
"frames": 31,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.003566,
|
||||
"mean_us": 0.348454,
|
||||
"p99_us": 0.351007,
|
||||
"max_us": 0.390995,
|
||||
"deadline_us": 702.947846,
|
||||
"load": 0.000496,
|
||||
"graph_buffer_bytes": 496
|
||||
},
|
||||
{
|
||||
"nodes": 2,
|
||||
"channels": 1,
|
||||
"rate": 48000,
|
||||
"frames": 128,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.010079,
|
||||
"mean_us": 2.3219,
|
||||
"p99_us": 3.858004,
|
||||
"max_us": 4.318004,
|
||||
"deadline_us": 2666.666667,
|
||||
"load": 0.000871,
|
||||
"graph_buffer_bytes": 2048
|
||||
},
|
||||
{
|
||||
"nodes": 2,
|
||||
"channels": 1,
|
||||
"rate": 96000,
|
||||
"frames": 1024,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.010961,
|
||||
"mean_us": 12.680954,
|
||||
"p99_us": 18.045001,
|
||||
"max_us": 21.059997,
|
||||
"deadline_us": 10666.666667,
|
||||
"load": 0.001189,
|
||||
"graph_buffer_bytes": 16384
|
||||
},
|
||||
{
|
||||
"nodes": 2,
|
||||
"channels": 2,
|
||||
"rate": 44100,
|
||||
"frames": 31,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.006352,
|
||||
"mean_us": 1.5425,
|
||||
"p99_us": 1.793,
|
||||
"max_us": 1.813998,
|
||||
"deadline_us": 702.947846,
|
||||
"load": 0.002194,
|
||||
"graph_buffer_bytes": 496
|
||||
},
|
||||
{
|
||||
"nodes": 2,
|
||||
"channels": 2,
|
||||
"rate": 48000,
|
||||
"frames": 128,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.007594,
|
||||
"mean_us": 2.917503,
|
||||
"p99_us": 5.650989,
|
||||
"max_us": 6.111994,
|
||||
"deadline_us": 2666.666667,
|
||||
"load": 0.001094,
|
||||
"graph_buffer_bytes": 2048
|
||||
},
|
||||
{
|
||||
"nodes": 2,
|
||||
"channels": 2,
|
||||
"rate": 96000,
|
||||
"frames": 1024,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.01585,
|
||||
"mean_us": 22.3441,
|
||||
"p99_us": 36.149009,
|
||||
"max_us": 44.774992,
|
||||
"deadline_us": 10666.666667,
|
||||
"load": 0.002095,
|
||||
"graph_buffer_bytes": 16384
|
||||
},
|
||||
{
|
||||
"nodes": 16,
|
||||
"channels": 1,
|
||||
"rate": 44100,
|
||||
"frames": 31,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.017393,
|
||||
"mean_us": 3.149973,
|
||||
"p99_us": 3.296009,
|
||||
"max_us": 11.472002,
|
||||
"deadline_us": 702.947846,
|
||||
"load": 0.004481,
|
||||
"graph_buffer_bytes": 3968
|
||||
},
|
||||
{
|
||||
"nodes": 16,
|
||||
"channels": 1,
|
||||
"rate": 48000,
|
||||
"frames": 128,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.030107,
|
||||
"mean_us": 12.434426,
|
||||
"p99_us": 16.982012,
|
||||
"max_us": 18.214996,
|
||||
"deadline_us": 2666.666667,
|
||||
"load": 0.004663,
|
||||
"graph_buffer_bytes": 16384
|
||||
},
|
||||
{
|
||||
"nodes": 16,
|
||||
"channels": 1,
|
||||
"rate": 96000,
|
||||
"frames": 1024,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.017924,
|
||||
"mean_us": 68.742836,
|
||||
"p99_us": 95.873009,
|
||||
"max_us": 109.757995,
|
||||
"deadline_us": 10666.666667,
|
||||
"load": 0.006445,
|
||||
"graph_buffer_bytes": 131072
|
||||
},
|
||||
{
|
||||
"nodes": 16,
|
||||
"channels": 2,
|
||||
"rate": 44100,
|
||||
"frames": 31,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.01581,
|
||||
"mean_us": 6.329124,
|
||||
"p99_us": 6.501999,
|
||||
"max_us": 12.534001,
|
||||
"deadline_us": 702.947846,
|
||||
"load": 0.009004,
|
||||
"graph_buffer_bytes": 3968
|
||||
},
|
||||
{
|
||||
"nodes": 16,
|
||||
"channels": 2,
|
||||
"rate": 48000,
|
||||
"frames": 128,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.042171,
|
||||
"mean_us": 37.250633,
|
||||
"p99_us": 51.957992,
|
||||
"max_us": 54.725009,
|
||||
"deadline_us": 2666.666667,
|
||||
"load": 0.013969,
|
||||
"graph_buffer_bytes": 16384
|
||||
},
|
||||
{
|
||||
"nodes": 16,
|
||||
"channels": 2,
|
||||
"rate": 96000,
|
||||
"frames": 1024,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.017924,
|
||||
"mean_us": 167.51364,
|
||||
"p99_us": 332.022013,
|
||||
"max_us": 387.477005,
|
||||
"deadline_us": 10666.666667,
|
||||
"load": 0.015704,
|
||||
"graph_buffer_bytes": 131072
|
||||
},
|
||||
{
|
||||
"nodes": 64,
|
||||
"channels": 1,
|
||||
"rate": 44100,
|
||||
"frames": 31,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.081966,
|
||||
"mean_us": 10.984623,
|
||||
"p99_us": 19.296,
|
||||
"max_us": 20.708991,
|
||||
"deadline_us": 702.947846,
|
||||
"load": 0.015627,
|
||||
"graph_buffer_bytes": 15872
|
||||
},
|
||||
{
|
||||
"nodes": 64,
|
||||
"channels": 1,
|
||||
"rate": 48000,
|
||||
"frames": 128,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.147651,
|
||||
"mean_us": 64.12053,
|
||||
"p99_us": 92.806993,
|
||||
"max_us": 93.618,
|
||||
"deadline_us": 2666.666667,
|
||||
"load": 0.024045,
|
||||
"graph_buffer_bytes": 65536
|
||||
},
|
||||
{
|
||||
"nodes": 64,
|
||||
"channels": 1,
|
||||
"rate": 96000,
|
||||
"frames": 1024,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.06297,
|
||||
"mean_us": 302.05437,
|
||||
"p99_us": 394.601011,
|
||||
"max_us": 396.89499,
|
||||
"deadline_us": 10666.666667,
|
||||
"load": 0.028318,
|
||||
"graph_buffer_bytes": 524288
|
||||
},
|
||||
{
|
||||
"nodes": 64,
|
||||
"channels": 2,
|
||||
"rate": 44100,
|
||||
"frames": 31,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.123665,
|
||||
"mean_us": 38.359343,
|
||||
"p99_us": 52.951,
|
||||
"max_us": 53.622003,
|
||||
"deadline_us": 702.947846,
|
||||
"load": 0.054569,
|
||||
"graph_buffer_bytes": 15872
|
||||
},
|
||||
{
|
||||
"nodes": 64,
|
||||
"channels": 2,
|
||||
"rate": 48000,
|
||||
"frames": 128,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.133965,
|
||||
"mean_us": 91.372266,
|
||||
"p99_us": 175.463996,
|
||||
"max_us": 177.548005,
|
||||
"deadline_us": 2666.666667,
|
||||
"load": 0.034265,
|
||||
"graph_buffer_bytes": 65536
|
||||
},
|
||||
{
|
||||
"nodes": 64,
|
||||
"channels": 2,
|
||||
"rate": 96000,
|
||||
"frames": 1024,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.063621,
|
||||
"mean_us": 620.865637,
|
||||
"p99_us": 1065.186996,
|
||||
"max_us": 1085.204,
|
||||
"deadline_us": 10666.666667,
|
||||
"load": 0.058206,
|
||||
"graph_buffer_bytes": 524288
|
||||
},
|
||||
{
|
||||
"nodes": 256,
|
||||
"channels": 1,
|
||||
"rate": 44100,
|
||||
"frames": 31,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.594482,
|
||||
"mean_us": 61.93558,
|
||||
"p99_us": 91.194001,
|
||||
"max_us": 98.316988,
|
||||
"deadline_us": 702.947846,
|
||||
"load": 0.088108,
|
||||
"graph_buffer_bytes": 63488
|
||||
},
|
||||
{
|
||||
"nodes": 256,
|
||||
"channels": 1,
|
||||
"rate": 48000,
|
||||
"frames": 128,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.289451,
|
||||
"mean_us": 142.010174,
|
||||
"p99_us": 196.253997,
|
||||
"max_us": 197.596004,
|
||||
"deadline_us": 2666.666667,
|
||||
"load": 0.053254,
|
||||
"graph_buffer_bytes": 262144
|
||||
},
|
||||
{
|
||||
"nodes": 256,
|
||||
"channels": 1,
|
||||
"rate": 96000,
|
||||
"frames": 1024,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.311192,
|
||||
"mean_us": 1379.590334,
|
||||
"p99_us": 1909.183004,
|
||||
"max_us": 2125.945,
|
||||
"deadline_us": 10666.666667,
|
||||
"load": 0.129337,
|
||||
"graph_buffer_bytes": 2097152
|
||||
},
|
||||
{
|
||||
"nodes": 256,
|
||||
"channels": 2,
|
||||
"rate": 44100,
|
||||
"frames": 31,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.304259,
|
||||
"mean_us": 81.809496,
|
||||
"p99_us": 114.608003,
|
||||
"max_us": 127.602994,
|
||||
"deadline_us": 702.947846,
|
||||
"load": 0.116381,
|
||||
"graph_buffer_bytes": 63488
|
||||
},
|
||||
{
|
||||
"nodes": 256,
|
||||
"channels": 2,
|
||||
"rate": 48000,
|
||||
"frames": 128,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.541971,
|
||||
"mean_us": 353.213863,
|
||||
"p99_us": 396.495001,
|
||||
"max_us": 401.252997,
|
||||
"deadline_us": 2666.666667,
|
||||
"load": 0.132455,
|
||||
"graph_buffer_bytes": 262144
|
||||
},
|
||||
{
|
||||
"nodes": 256,
|
||||
"channels": 2,
|
||||
"rate": 96000,
|
||||
"frames": 1024,
|
||||
"blocks": 300,
|
||||
"compile_ms": 0.518307,
|
||||
"mean_us": 2478.520283,
|
||||
"p99_us": 3092.433995,
|
||||
"max_us": 4376.808007,
|
||||
"deadline_us": 10666.666667,
|
||||
"load": 0.232361,
|
||||
"graph_buffer_bytes": 2097152
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue