docs/using/benchmarks.md
The core library includes a benchmarking tool that simulates processing live audio by loading a .wav audio file and feeding it in chunks to the model. To run it:
<!-- doc-test: skip -->cd core
mkdir -p build
cd build
cmake ..
cmake --build . --config Release
./benchmark
This will report the absolute time taken to process the audio, what percentage of the audio file's duration that is, and the average latency for a response.
The percentage is helpful because it approximates how much of a compute load the model will be on your hardware. For example, if it shows 20% then that means the speech processing will take a fifth of the compute time when running in your application, leaving 80% for the rest of your code.
The latency metric needs a bit of explanation. What most applications care about is how soon they are notified about a phrase after the user has finished talking, since this determines how fast the product can respond. As with any user interface, the time between speech ending and the app doing something determines how responsive the voice interface feels, with a goal of keeping it below 200ms. The latency figure logged here is the average time between when the library determines the user has stopped talking and the delivery of the final transcript of that phrase to the client. This is where streaming models have the most impact, since they do a lot of their work upfront, while speech is still happening, so they can usually finish very quickly.
By default the benchmark binary uses the Tiny English model and the two_cities.wav recording from this repository's test-assets folder, which is why it's run from the build directory, but you can pass in the --model-path, --model-arch, and --wav-path parameters to choose a model you've downloaded or a different recording.
You can also choose how often the transcript should be updated using the --transcription-interval argument. This defaults to 0.5 seconds, but the right value will depend on how fast your application needs updates. Longer intervals reduce the compute required a bit, at the cost of slower updates.
The MacBook Pro, Pixel 10a, and iPad (A16) Tiny / Small / Medium Streaming cells in the comparison table use the same latency metric, measured by scripts/test-mobile-latency.sh (also run from scripts/build-all-platforms.sh). That script downloads the models from the CDN, feeds two_cities.wav in small chunks as fast as the device can process, and averages lastTranscriptionLatencyMs over completed lines. Re-measure and refresh the README with the command below; a cell is rewritten only when the new average differs from the published value by more than 5%:
./scripts/test-mobile-latency.sh --update-readme
That writes whatever a single run measured, which is fine for the iPad — three consecutive runs there landed within a millisecond of each other — but the Mac and the Pixel wander enough that one run is not a number worth publishing. Medium Streaming on the Mac varied between 56 and 83ms across three runs, and on the Pixel between 383 and 432ms, mostly according to how recently the machine had been busy. The published cells are medians of three runs taken with the device given time to cool between them, so expect a single run to disagree with them a little. The Linux x86 and Raspberry Pi 5 columns are measured separately and were last taken before the build-optimization fix described in the changelog, so they read pessimistically until someone with that hardware refreshes them.
For platforms that support Python, you can run the scripts/run-benchmarks.py script which will evaluate similar metrics, with the advantage that it can also download the models so you don't need to worry about path handling.
It also evaluates equivalent Whisper models. This is a pretty opinionated benchmark that looks at the latency and total compute cost of the two families of models in a situation that is representative of many common real-time voice applications' requirements:
These are very different requirements from bulk offline processing scenarios, where the overall throughput of the system is more important, and so the latency on a single segment of speech is less important than the overall throughput of the system. This allows optimizations like batch processing.
We are not claiming that Whisper is not a great model for offline processing, but we do want to highlight the advantages we that Moonshine offers for live speech applications with real-time latency requirements.
The experimental setup is as follows: