Recursive AI

Speed rows

All onemedia docs

bench/OneMedia.Bench measures OneMedia against managed comparators and prints the ratio, allocations and memory for each row. It is a console app, not packed, and the only project that references the comparator packages.

What is measured

RowOneMediaComparator (the bar)Reference tools (information)
mp4-demuxread every packet of every trackSharpMP4ffmpeg -c copy -f null
mp4-audioread the audio track only, other tracks switched offOneAudio Mp4PacketSource–
mp4-probeopen, track list, durationMetadataExtractor, TagLib#, ATL.NET (fastest of the three counts)ffprobe, MediaInfo, ExifTool, MP4Box -info
mkv-demuxread every packetthe Matroska package (full deserialise, then walk the blocks)ffmpeg -c copy -f null, mkvextract tracks (first track)
mkv-probeopen, track list, durationthe package's element reader: Info and Tracks read, clusters skippedffprobe, MediaInfo, ExifTool, mkvmerge -J, mkvinfo

The Matroska package counts a laced block as one packet, where OneMedia delivers each frame of a lace; the table flags the different counts. The comparator therefore does less work per file than OneMedia on laced audio, which favours the comparator.

Files per row are listed by list: a small generated file, open-movie files of different shapes (1080p, fragmented, Matroska/WebM), the published Matroska test files, and the over-4 GiB files with the index at the end (MP4) and a plain over-4 GiB Matroska. A file missing from the corpus is skipped and said so.

The work is the same for everyone. A packet read counts the packet, adds its size and XORs its first and last byte, so every payload is delivered to the caller and not skipped. The counts are printed next to the times; a comparator whose packet count differs from OneMedia's is flagged in the table (Matroska laced blocks, files the package cannot read). The probe rows read what each library offers: tracks and duration, plus the title and first artist where the library has them; OneMedia's native tags join its probe when its tag layer lands.

Calls. Each comparator is called as its published README shows, with a 64 KiB file buffer. Where the README does not cover a row the obvious public call is used: SharpMP4 reads track by track with ReadSample; MetadataExtractor uses ImageMetadataReader.ReadMetadata(stream) and reads every tag's description; TagLib# uses File.Create(path); ATL.NET uses new Track(path). ATL.NET is audio-oriented and may refuse video files; a refusal is shown as fail.

Method

  • One fresh process per (row, implementation, file), so peak memory belongs to that work alone. The parent reads each file once before its rows so all implementations start with it in the page cache; the tables say so.
  • In the process: a cold first run (JIT and type loading included), then a warm-up of at least 30 runs and 1.5 s for every implementation alike, so that the runtime has promoted the hot methods to optimised code before any sample (tier-0, then the instrumented stage, then optimised, each behind a 100 ms quiet timer). Then one sizing run and 5 samples, each the mean of enough back-to-back runs to take about 50 ms. The median is reported, and the range is kept in results.tsv. Probe rows (*-probe) are sampled this way on every file, since probe work does not grow with the file. Demux-style rows on files over 1 GiB get the cold run and then 3 samples of one run each. The cold first run is shown apart in the note column, for the comparators as well; it is a published, non-gating number (the first open in a process: what a one-off info call or a per-file open pays).
  • Allocation is GC.GetAllocatedBytesForCurrentThread per run, and per packet. Peak memory is the process's peak working set; the working set before any work is printed beside it.
  • Reference tools run as processes under /usr/bin/time, three times (once over 1 GiB): wall time measured by the parent, peak resident set from time. Their start-up cost is part of the figure.
  • Ratio = OneMedia's median ÷ the fastest managed comparator's median for that file. The bar is a geometric mean ≤ 1.00× per row and no file above 1.25×. Rows with no managed comparator pass.
  • Every run records CPU, logical cores, ISA flags, storage of the corpus, runtime, restored package versions, tool versions and the one-minute load average before, during (mean and max of 5 s samples) and after.

Running it

dotnet run -c Release --project bench/OneMedia.Bench -- run --rows 0.1 --out results/x64 [--corpus DIR]

--rows takes a stage (0.1) or row ids. --files a,b keeps files whose path contains one of the strings, --no-tools leaves out the reference tools, --reps and --tool-reps set the repetitions, --budget MIN stops starting new cells after that many minutes (exit code 75) and --resume continues from results.tsv. report rebuilds report.md; prepare derives the fragmented MP4 (done by run); list shows rows and files. The corpus is $ONEMEDIA_HOME/corpus (default ~/onemedia/corpus).

Timings are only comparable between runs on a quiet machine. The published run is one command per machine under the exclusive bench queue.

JIT tiers: steady state and first open

Each cell runs in a fresh process. The runtime starts every method in unoptimised tier-0 code and promotes hot ones only after a 100 ms quiet period and a background compile, with a second instrumented stage under dynamic PGO. Measuring before that climb finishes measures tier-0 code, which punishes libraries that do more of their own work per call. The samples are therefore taken after a warm-up long enough for every implementation to have tiered up (see Method), and the library carries no tiering overrides.

The first call in a process is a separate matter: it is JIT dominated, it is what a one-off open pays, and it is reported as "cold first run" for OneMedia and for every comparator. It is published but does not enter the ratio.

To see the unwarmed regime for a cell, run OneMedia.Bench child ROW IMPL REL CORPUS REPS under DOTNET_TieredCompilation=0 (every method fully optimised) or DOTNET_TieredPGO=0.

Provenance of the comparator calls

Every comparator call was chosen from the package's published README, its package page and its public type and member signatures. No comparator's source, decompiled code or unpacked package contents was read, and no reference tool's source was read; the tools run as released binaries.

Looking at a cell

  • OneMedia.Bench once ROW IMPL REL [CORPUS [TIMES]] runs one cell, optionally in a loop, and prints the mean time of a run.
  • bench/iocount.sh DLL ROW IMPL REL counts the read calls and bytes a cell makes on its input file (strace).
  • bench/profile.sh DLL ROW IMPL REL TIMES samples a looped cell with dotnet-trace and prints self and inclusive time by method. It needs dotnet-trace in ~/onemedia/u5-bench/tools (dotnet tool install dotnet-trace --tool-path ...).