Measured Speed
Start with a Mandelbrot calculation
A Mandelbrot image gives us a useful job for Turbo: repeat a small calculation for each pixel, then turn the results into a picture. We tried this with fixed-point math, which represents fractional values using scaled integers. It gives the board plenty of repeated arithmetic to work through.

An actual capture from the earlier PyMCU-based Feather RP2040 DVI Mandelbrot experiment, with 152 × 96 samples enlarged for display. Its on-screen render time belongs to that recording. The timed comparison below came from a separate Metro RP2040 run.
One board. One workload. Three execution modes.
For the comparison, we gave the same fixed-point Mandelbrot function to three execution modes: ordinary Python bytecode, Native, and Viper. Each calculated a 160 × 120 image, allowing up to 64 iterations per pixel. The table shows how long the calculation took and the value it returned, so we can compare the time without changing the job.
| Execution mode | Recorded median time | Speedup over bytecode | Returned value |
|---|---|---|---|
| Python bytecode | 8,335.3 ms | 1.00× | 407644 |
| Native | 4,778.0 ms | 1.74× | 407644 |
| Viper | 422.9 ms | 19.71× | 407644 |
The board doing this timed work was an Adafruit Metro RP2040. We also used a Feather RP2040 DVI for experiments that sent pictures to a display, including the capture above. They play different roles here: the Metro supplied these timings, and the Feather lets us see a visual example.
The test record calls the Metro's processor target armv6m. That is the instruction-set family used by its Cortex-M0+ CPU cores, and it tells the compiler which instructions the chip can run. The record also identifies CircuitPython firmware 10.3.0-42-g3cdb20693f. Firmware matters because it supplies the Python runtime and native-module loader; these measurements belong to that build, even though the installation page now points to newer official firmware.
These are recorded results from September 8, 2026, reviewed for this guide. We have not rerun this benchmark for the draft. All three modes returned 407644. The stopwatch covers the computation, so screen refresh, file loading and the rest of an application need their own measurements.
Recorded CLI output · Benchmark source · Firmware context
The returned value 407644 is the sum of the calculated iteration counts. Matching it catches many mistakes, but two different shopping baskets can have the same total. Likewise, different pixel values can produce the same sum. Compare the complete output when you can, and use more than one input before trusting a changed function.
Source: the benchmark's return value.
It is the speedup of this measured Mandelbrot computation. A project also spends time moving pixels, reading files, talking to sensors, and waiting for hardware. Measure those separately. The interesting payoff is time returned to the rest of your program: more room for interaction, a larger calculation, or another update.
A faster cook cannot make the kettle boil sooner. For an illustrative program that spends 50 ms computing and 50 ms waiting for hardware, making the computation 20 times faster gives 2.5 + 50 = 52.5 ms overall: about 1.90×, not 20×. This is a made-up example to explain the limit, not another Turbo measurement.
Another way to speed up the work
Before compiling a loop, check whether ulab already has the operation you need. Its array math, statistics, FFTs and filters run in native code, so one call can process a batch of values without a Python loop. Jeff Epler's RMS benchmark is a useful example. Turbo is useful when the work is a custom loop with its own branches and rules: it can compile that loop, including its control flow. The ulab documentation lists its available operations.
Our Mandelbrot test keeps the same fixed-point, per-pixel calculation and compares bytecode, Native and Viper. Each pixel repeats arithmetic until it escapes or reaches the iteration limit. An ulab version could organize pixels into arrays and masks, but that would be a separate implementation to check and measure. We haven't benchmarked one here, so this chart does not establish how Turbo compares with ulab. Jeff's Metro M4 results belong to his separate workload.
The board in this test
The recorded times above came from the Metro RP2040 below, running the exact firmware identified with the chart. You do not need hardware to read or compare the results.
Page last edited September 11, 2026
Text editor powered by tinymce.