One publishable run under the exclusive bench queue (wq run --class bench, one filtered group, subsbench 20000 100000, 30 samples), driven by tools/bench/subsbench-run.sh, on main 0794678 plus the ASS tuning commit described below. A first run before that change is described in the notes. Method: docs/bench.md.
Against the bar
Bar: geometric mean of the ratios <= 1.00x and no row worse than 1.25x, against the fastest managed comparator per row (ratio = OneMedia's median over that comparator's median).
| Row | Sizes with a ratio | Geomean | Worst | Verdict |
|---|---|---|---|---|
| parse srt | 2/2 | 1.03× | 1.11× | within the 1.25× row limit |
| parse vtt | 2/2 | 0.17× | 0.23× | at the bar |
| parse ass | 2/2 | 0.95× | 1.21× | within the 1.25× row limit |
| parse ttml | 2/2 | 0.50× | 0.62× | at the bar |
| convert srt->vtt | 2/2 | 0.41× | 0.44× | at the bar |
| convert srt->ass | 2/2 | 0.94× | 1.01× | within the 1.25× row limit |
| convert srt->ttml | 2/2 | 0.16× | 0.18× | at the bar |
| all 14 rows | 14/14 | 0.47× | 1.21× | meets the bar |
Notes
- Rows are
parse srt|vtt|ass|ttmlandconvert srt->vtt|ass|ttmlat 20,000 and 100,000 cues, on the synthetic input and with the work described in docs/bench.md. The bar uses the fastest managed comparator per row, which is the Subtitle Edit core library wherever it has the format (SubtitlesParser has no TTML parser and no writers, and is the slowest on every row it has; its ASS reader returns 23,411 of the 100,000 cues). - OneMedia does more work than the comparators on every row (encoding and line-ending detection, styled spans, extras, defects with offsets, a loss report on conversion), which favours them.
- The rows nearest the limit are
parse srt(both sizes) andparse assat 100,000 cues, where the median sits far above the minimum. At 100,000 cues a run allocates 54 to 110 MB (about 17 MB of it the decoded text) and the garbage collector's share is large; the median swings with the collector while the minimum does not (OneMedia's minimum is below the comparator's minimum on both ASS rows; on the SRT rows it is 1.1 to 1.2 times above). Median is the published figure. - One indicative tuning pass followed a first publishable run (job 1 of 2, same machine, same method, before the change) that had
parse assat 100,000 cues at 1.44× (median 78.67 ms against 54.65 ms) andparse srtat 100,000 cues at 1.20×, geomean 0.49×. The pass built the ASS override-tag buffer and its two delegates once per cue instead of once per override block (1.5 MB less allocation per 100,000-cue parse); output is unchanged (subsdump: 0 differences over 18,750 input/format lines of the testdata sidecars and 120 damaged variants of each; the subtitle tests pass). The second run, the one tabulated here, hasparse assat 1.21×. The allocation change is 2.4%, so most of that movement is run-to-run collector variance, not the change: treat the row as at the limit, not as comfortably inside it. - The load average before the run (5.33) is the one-minute average still decaying from the previous job; the machine ran nothing else during it (the exclusive queue).
Run
- Machine: AMD Ryzen 9 7950X3D 16-Core Processor; 32 logical cores; Linux 7.0.0-38-generic x86_64
- ISA: sse4.2 avx2 bmi2 avx512f avx512bw; the input is generated in memory, so storage is not in play
- .NET: 10.0.13 runtime, SDK 10.0.402
- Start 2026-11-02T14:09Z; elapsed 225 s; load average (1 min): before 5.33; during mean 2.36, max 5.33 over 45 samples (5 s samples); after 1.37
- Comparators as restored: SubtitlesParser 1.5.1 (MIT), Subtitle Edit core library 5.3.0 (
libse, GPL, public API only, bench project only) - 30 warm-up runs per implementation, then 30 samples in turn; median and minimum; one process; the bytes are in memory
Rows
Ratio is OneMedia's median over the fastest managed comparator's median. Alloc is bytes allocated per run by the calling thread. Result is what each run produced (cues parsed, or bytes written); SubtitlesParser's ASS reader returns 23,411 of 100,000 cues, so it is not the comparator there when it is slower anyway, and its row is information.
| Cues | Row | Implementation | Median | Min | Alloc / run | Result | Ratio to the fastest comparator |
|---|---|---|---|---|---|---|---|
| 20,000 | parse srt | onemedia | 4.28 ms | 3.76 ms | 10.5 MiB | 20,000 | 0.96× (vs SubtitleEdit core) |
| 20,000 | parse srt | SubtitlesParser | 49.44 ms | 28.23 ms | 50.1 MiB | 20,000 | 11.06× |
| 20,000 | parse srt | SubtitleEdit core | 4.47 ms | 3.24 ms | 13.2 MiB | 20,000 | 1.00× |
| 20,000 | parse vtt | onemedia | 3.80 ms | 3.57 ms | 11.1 MiB | 20,000 | 0.13× (vs SubtitleEdit core) |
| 20,000 | parse vtt | SubtitlesParser | 51.01 ms | 29.94 ms | 65.6 MiB | 20,000 | 1.72× |
| 20,000 | parse vtt | SubtitleEdit core | 29.69 ms | 15.79 ms | 34.8 MiB | 20,000 | 1.00× |
| 20,000 | parse ass | onemedia | 9.53 ms | 4.77 ms | 12.1 MiB | 20,000 | 0.74× (vs SubtitleEdit core) |
| 20,000 | parse ass | SubtitlesParser | 21.05 ms | 15.74 ms | 27.1 MiB | 20,000 | 1.64× |
| 20,000 | parse ass | SubtitleEdit core | 12.81 ms | 6.28 ms | 19.3 MiB | 20,000 | 1.00× |
| 20,000 | parse ttml | onemedia | 43.93 ms | 17.47 ms | 42.6 MiB | 20,000 | 0.40× (vs SubtitleEdit core) |
| 20,000 | parse ttml | SubtitleEdit core | 109.44 ms | 71.43 ms | 74.0 MiB | 20,000 | 1.00× |
| 20,000 | convert srt->vtt | onemedia | 10.81 ms | 6.26 ms | 19.6 MiB | 1,316,133 | 0.44× (vs SubtitleEdit core) |
| 20,000 | convert srt->vtt | SubtitleEdit core | 24.47 ms | 17.11 ms | 35.5 MiB | 1,316,131 | 1.00× |
| 20,000 | convert srt->ass | onemedia | 9.31 ms | 8.74 ms | 21.8 MiB | 1,724,268 | 1.01× (vs SubtitleEdit core) |
| 20,000 | convert srt->ass | SubtitleEdit core | 9.25 ms | 8.70 ms | 23.3 MiB | 1,740,081 | 1.00× |
| 20,000 | convert srt->ttml | onemedia | 19.28 ms | 14.21 ms | 26.9 MiB | 1,921,339 | 0.14× (vs SubtitleEdit core) |
| 20,000 | convert srt->ttml | SubtitleEdit core | 135.29 ms | 127.87 ms | 295.5 MiB | 2,282,604 | 1.00× |
| 100,000 | parse srt | onemedia | 33.92 ms | 17.98 ms | 52.6 MiB | 100,000 | 1.11× (vs SubtitleEdit core) |
| 100,000 | parse srt | SubtitlesParser | 352.84 ms | 293.65 ms | 311.6 MiB | 100,000 | 11.50× |
| 100,000 | parse srt | SubtitleEdit core | 30.69 ms | 15.25 ms | 66.3 MiB | 100,000 | 1.00× |
| 100,000 | parse vtt | onemedia | 40.16 ms | 18.04 ms | 55.3 MiB | 100,000 | 0.23× (vs SubtitleEdit core) |
| 100,000 | parse vtt | SubtitlesParser | 269.56 ms | 226.69 ms | 327.1 MiB | 100,000 | 1.57× |
| 100,000 | parse vtt | SubtitleEdit core | 171.27 ms | 151.72 ms | 173.4 MiB | 100,000 | 1.00× |
| 100,000 | parse ass | onemedia | 61.18 ms | 24.41 ms | 59.9 MiB | 100,000 | 1.21× (vs SubtitleEdit core) |
| 100,000 | parse ass | SubtitlesParser | 170.37 ms | 131.61 ms | 149.3 MiB | 23,411 | 3.38× |
| 100,000 | parse ass | SubtitleEdit core | 50.41 ms | 38.44 ms | 96.4 MiB | 100,000 | 1.00× |
| 100,000 | parse ttml | onemedia | 303.24 ms | 221.86 ms | 210.9 MiB | 100,000 | 0.62× (vs SubtitleEdit core) |
| 100,000 | parse ttml | SubtitleEdit core | 493.02 ms | 453.28 ms | 368.7 MiB | 100,000 | 1.00× |
| 100,000 | convert srt->vtt | onemedia | 63.50 ms | 40.48 ms | 98.2 MiB | 6,586,400 | 0.38× (vs SubtitleEdit core) |
| 100,000 | convert srt->vtt | SubtitleEdit core | 166.50 ms | 140.76 ms | 177.7 MiB | 6,580,867 | 1.00× |
| 100,000 | convert srt->ass | onemedia | 63.05 ms | 54.17 ms | 106.3 MiB | 8,702,835 | 0.88× (vs SubtitleEdit core) |
| 100,000 | convert srt->ass | SubtitleEdit core | 71.35 ms | 58.77 ms | 116.5 MiB | 8,770,636 | 1.00× |
| 100,000 | convert srt->ttml | onemedia | 129.80 ms | 114.11 ms | 134.4 MiB | 9,608,556 | 0.18× (vs SubtitleEdit core) |
| 100,000 | convert srt->ttml | SubtitleEdit core | 706.80 ms | 660.08 ms | 1477.8 MiB | 11,446,592 | 1.00× |