Zephyr — heap mode
Raw cross-binding benchmark results measured on STM32F746G-DISCOVERY (Cortex-M7 @ 216 MHz) running Zephyr RTOS in default heap-allocation mode (_create() / _destroy() API), with CONFIG_OVE_BENCHMARK_WORST_CASE_TIMING=y — caches and flash accelerators disabled to approximate cacheless ARM-MCU timing. See benchmarks overview for the worst-case-timing methodology.
Methodology and reproduction steps: benchmarks overview. Same numbers under CONFIG_OVE_ZERO_HEAP=y: Zephyr zero-heap. Interpretation: heap vs zero-heap, per-binding analysis, wrapper-vs-native notes.
Generated by
scripts/bench_compare.py. Trimmed-mean (top 1% dropped) when available, else avg. Delta column is(binding − C) / C— values within ±10.0% are within typical measurement noise.
native_* rows. bench_native_zephyr.c is C code calling raw Zephyr APIs (k_mutex_*, k_sem_*, k_msgq_*), compiled identically into every binary; the CPP/RUST/ZIG columns for those rows are the same C code measured in three different processes.
Zephyr
| Suite | Case | C | CPP | Δ CPP | RUST | Δ RUST | ZIG | Δ ZIG |
|---|---|---|---|---|---|---|---|---|
| time | time_get_us_overhead | 2.5 µs | 2.4 µs | -4.7% | 2.6 µs | +6.4% | 2.5 µs | +2.6% |
| time | delay_1ms | 1.09 ms | 1.09 ms | -0.0% | 1.09 ms | -0.2% | 1.09 ms | -0.1% |
| thread | create_destroy | 116.1 µs | 113.5 µs | -2.2% | 115.0 µs | -0.9% | 114.0 µs | -1.8% |
| thread | yield | 10.6 µs | 10.6 µs | -0.3% | 10.6 µs | -0.6% | 10.4 µs | -2.3% |
| thread | get_self | 971 ns | 975 ns | +0.4% | 1.1 µs | +12.8% | 842 ns | -13.3% |
| thread | sleep_1ms | 1.09 ms | 1.09 ms | -0.0% | 1.09 ms | -0.2% | 1.09 ms | -0.1% |
| thread | context_switch | 56.5 µs | 54.6 µs | -3.4% | — | — | 54.2 µs | -4.0% |
| sync | mutex_memory | 32 B | 32 B | — | 32 B | — | 32 B | — |
| sync | sem_memory | 24 B | 24 B | — | 24 B | — | 24 B | — |
| sync | event_memory | 24 B | 24 B | — | 24 B | — | 24 B | — |
| sync | condvar_memory | 16 B | 16 B | — | 16 B | — | 16 B | — |
| sync | mutex_lock_unlock | 3.0 µs | 3.1 µs | +3.6% | 3.4 µs | +15.7% | 2.8 µs | -6.0% |
| sync | mutex_create_destroy | 11.6 µs | 12.0 µs | +4.0% | 8.7 µs | -25.0% | 7.9 µs | -31.4% |
| sync | mutex_contention_2t | 3.1 µs | 47.7 µs | +1448.5% | 38.9 µs | +1163.2% | 33.9 µs | +1000.3% |
| sync | sem_take_give | 2.0 µs | 2.2 µs | +5.2% | 2.1 µs | +4.1% | 2.1 µs | +2.2% |
| sync | sem_create_destroy | 12.0 µs | 12.3 µs | +2.7% | 12.6 µs | +5.4% | 11.9 µs | -0.7% |
| sync | event_signal_wait | 56.6 µs | 54.7 µs | -3.3% | 55.6 µs | -1.8% | 54.5 µs | -3.6% |
| sync | condvar_signal_wait | 65.1 µs | 63.9 µs | -1.8% | 64.6 µs | -0.7% | 63.3 µs | -2.8% |
| sync | recursive_mutex_lock_unlock | 3.1 µs | 3.1 µs | +2.4% | 3.4 µs | +9.9% | 2.9 µs | -4.3% |
| queue | memory | 96 B | 96 B | — | 96 B | — | 96 B | — |
| queue | send_receive | 4.7 µs | 4.3 µs | -9.0% | 6.0 µs | +26.6% | 4.4 µs | -6.9% |
| queue | create_destroy | 20.0 µs | 20.7 µs | +3.7% | 21.4 µs | +7.1% | 21.3 µs | +6.7% |
| queue | throughput_2t | 3.7 µs | 3.2 µs | -14.1% | 4.1 µs | +11.4% | 3.1 µs | -14.6% |
| timer | memory | 96 B | 96 B | — | 96 B | — | 96 B | — |
| timer | create_destroy | 14.1 µs | 14.5 µs | +2.7% | 15.4 µs | +8.6% | 14.0 µs | -1.1% |
| timer | start_stop | 9.0 µs | 8.7 µs | -3.7% | 8.8 µs | -2.5% | 8.7 µs | -3.5% |
| eventgroup | memory | 24 B | 24 B | — | 24 B | — | 24 B | — |
| eventgroup | set_get_bits | 9.0 µs | 9.2 µs | +1.3% | 9.1 µs | +0.9% | 8.9 µs | -1.0% |
| eventgroup | create_destroy | 11.7 µs | 11.9 µs | +2.3% | 12.3 µs | +5.4% | 11.6 µs | -0.8% |
| workqueue | memory | 2520 B | 2520 B | — | 2520 B | — | 2520 B | — |
| workqueue | create_destroy | 62.2 µs | 61.8 µs | -0.6% | 62.5 µs | +0.6% | 63.2 µs | +1.6% |
| workqueue | submit_execute | 58.4 µs | 57.6 µs | -1.4% | 57.6 µs | -1.3% | 57.2 µs | -2.0% |
| stream | memory | 320 B | 328 B | — | 320 B | — | 320 B | — |
| stream | send_recv_64B | 14.3 µs | 14.3 µs | +0.3% | 17.3 µs | +21.2% | 14.2 µs | -0.9% |
| stream | create_destroy | 11.7 µs | 12.2 µs | +4.0% | 12.5 µs | +7.2% | 11.7 µs | +0.1% |
| stream | throughput | 24.3 µs | 24.0 µs | -1.4% | 41.7 µs | +71.3% | 23.8 µs | -2.0% |
| native_zephyr | native_mutex_lock_unlock | 2.8 µs | 2.7 µs | -3.3% | 2.8 µs | +2.5% | 2.6 µs | -6.2% |
| native_zephyr | native_mutex_create_destroy | 813 ns | 911 ns | +12.1% | 799 ns | -1.7% | 776 ns | -4.6% |
| native_zephyr | native_mutex_contention_2t | 2.9 µs | 2.7 µs | -6.2% | 2.9 µs | -0.6% | 2.7 µs | -7.5% |
| native_zephyr | native_recursive_mutex_lock_unlock | 2.8 µs | 2.7 µs | -1.6% | 2.9 µs | +4.7% | 2.7 µs | -4.2% |
| native_zephyr | native_sem_take_give | 1.7 µs | 1.6 µs | -10.1% | 1.6 µs | -8.1% | 1.7 µs | -4.5% |
| native_zephyr | native_sem_create_destroy | 749 ns | 753 ns | +0.5% | 824 ns | +10.0% | 648 ns | -13.5% |
| native_zephyr | native_condvar_signal_wait | 66.9 µs | 66.1 µs | -1.2% | 66.1 µs | -1.2% | 65.6 µs | -1.8% |
| native_zephyr | native_event_signal_wait | 63.2 µs | 62.6 µs | -1.0% | 62.4 µs | -1.3% | 61.9 µs | -2.0% |
| native_zephyr | native_thread_yield | 10.5 µs | 10.5 µs | -0.1% | 10.4 µs | -0.7% | 10.3 µs | -2.0% |
| native_zephyr | native_thread_sleep_1ms | 1.09 ms | 1.09 ms | -0.0% | 1.09 ms | -0.2% | 1.09 ms | -0.1% |
| native_zephyr | native_thread_create_destroy | 80.0 µs | 77.9 µs | -2.5% | 78.2 µs | -2.2% | 77.5 µs | -3.1% |
| native_zephyr | native_thread_context_switch | 55.9 µs | 53.9 µs | -3.6% | 54.4 µs | -2.7% | 53.4 µs | -4.5% |
| native_zephyr | native_queue_send_receive | 4.8 µs | 4.0 µs | -15.8% | 5.9 µs | +24.5% | 4.1 µs | -13.1% |
| native_zephyr | native_queue_create_destroy | 1.3 µs | 1.1 µs | -18.2% | 1.3 µs | -4.2% | 1.1 µs | -13.4% |
| native_zephyr | native_stream_send_recv_64B | 12.8 µs | 12.8 µs | -0.1% | 11.0 µs | -13.8% | 12.7 µs | -0.5% |
| thread | ctx_switch | — | — | — | 55.6 µs | — | — | — |
Cases with |Δ| > 10.0% vs C:
- CPP
sync/mutex_contention_2t47726 vs 3082 (+1448.5%) - RUST
sync/mutex_contention_2t38932 vs 3082 (+1163.2%) - ZIG
sync/mutex_contention_2t33912 vs 3082 (+1000.3%) - RUST
stream/throughput41669 vs 24320 (+71.3%) - ZIG
sync/mutex_create_destroy7924 vs 11554 (-31.4%) - RUST
queue/send_receive5993 vs 4733 (+26.6%) - RUST
sync/mutex_create_destroy8661 vs 11554 (-25.0%) - RUST
native_zephyr/native_queue_send_receive5932 vs 4766 (+24.5%) - RUST
stream/send_recv_64B17324 vs 14295 (+21.2%) - CPP
native_zephyr/native_queue_create_destroy1074 vs 1313 (-18.2%) - CPP
native_zephyr/native_queue_send_receive4013 vs 4766 (-15.8%) - RUST
sync/mutex_lock_unlock3415 vs 2952 (+15.7%) - ZIG
queue/throughput_2t3133 vs 3669 (-14.6%) - CPP
queue/throughput_2t3152 vs 3669 (-14.1%) - RUST
native_zephyr/native_stream_send_recv_64B11018 vs 12775 (-13.8%) - ZIG
native_zephyr/native_sem_create_destroy648 vs 749 (-13.5%) - ZIG
native_zephyr/native_queue_create_destroy1137 vs 1313 (-13.4%) - ZIG
thread/get_self842 vs 971 (-13.3%) - ZIG
native_zephyr/native_queue_send_receive4142 vs 4766 (-13.1%) - RUST
thread/get_self1095 vs 971 (+12.8%) - CPP
native_zephyr/native_mutex_create_destroy911 vs 813 (+12.1%) - RUST
queue/throughput_2t4089 vs 3669 (+11.4%) - CPP
native_zephyr/native_sem_take_give1564 vs 1739 (-10.1%) - RUST
native_zephyr/native_sem_create_destroy824 vs 749 (+10.0%)
Wrapper vs native Zephyr API (within-run delta)
Each row pairs one binding's wrapper measurement against the raw Zephyr API baseline measured in the same process. See wrapper-vs-native notes for IPC caveats, lifecycle/intrinsic-cost interpretation, and notes on cross-process baseline variance.
| Operation | Binding | Wrapper called | Wrapper ns | Native ns | Δ |
|---|---|---|---|---|---|
| Thread yield | C | ove_thread_yield | 10625 ns | 10507 ns | +118 ns |
| Thread yield | CPP | ove::Thread::yield | 10590 ns | 10493 ns | +97 ns |
| Thread yield | RUST | ove::Thread::yield | 10562 ns | 10438 ns | +124 ns |
| Thread yield | ZIG | ove.Thread.yield | 10383 ns | 10300 ns | +83 ns |
| Thread sleep 1ms | C | ove_thread_sleep_ms(1) | 1087786 ns | 1087767 ns | +19 ns |
| Thread sleep 1ms | CPP | ove::Thread::sleep_ms(1) | 1087405 ns | 1087465 ns | -60 ns |
| Thread sleep 1ms | RUST | ove::Thread::sleep_ms(1) | 1085182 ns | 1085182 ns | +0 ns |
| Thread sleep 1ms | ZIG | ove.Thread.sleepMs(1) | 1087211 ns | 1087120 ns | +91 ns |
| Thread create+destroy | C | ove_thread_create+destroy | 116073 ns | 79956 ns | +36117 ns |
| Thread create+destroy | CPP | ove::Thread (ctor+dtor) | 113501 ns | 77933 ns | +35568 ns |
| Thread create+destroy | RUST | ove::Thread::spawn+join | 115000 ns | 78193 ns | +36807 ns |
| Thread create+destroy | ZIG | ove.Thread.spawn+join | 113986 ns | 77475 ns | +36511 ns |
| Thread context_switch (2t) | C | ove ping-pong (2t) | 56502 ns | 55859 ns | +643 ns |
| Thread context_switch (2t) | CPP | ove ping-pong (2t) | 54585 ns | 53868 ns | +717 ns |
| Thread context_switch (2t) | ZIG | ove ping-pong (2t) | 54220 ns | 53354 ns | +866 ns |
| Mutex lock+unlock | C | ove_mutex_lock+unlock | 2952 ns | 2753 ns | +199 ns |
| Mutex lock+unlock | CPP | ove::Mutex::lock+unlock | 3059 ns | 2661 ns | +398 ns |
| Mutex lock+unlock | RUST | ove::Mutex::lock+unlock | 3415 ns | 2823 ns | +592 ns |
| Mutex lock+unlock | ZIG | ove.Mutex.lock+unlock | 2774 ns | 2582 ns | +192 ns |
| Mutex create+destroy | C | ove_mutex_create+destroy | 11554 ns | 813 ns | +10741 ns |
| Mutex create+destroy | CPP | ove::Mutex (ctor+dtor) | 12017 ns | 911 ns | +11106 ns |
| Mutex create+destroy | RUST | ove::Mutex (new+drop) | 8661 ns | 799 ns | +7862 ns |
| Mutex create+destroy | ZIG | ove.Mutex.create+destroy | 7924 ns | 776 ns | +7148 ns |
| Mutex contention (2t) | C | ove_mutex_lock+unlock (×2t) | 3082 ns | 2897 ns | +185 ns |
| Mutex contention (2t) | CPP | ove::Mutex::lock+unlock (×2t) | 47726 ns | 2716 ns | +45010 ns |
| Mutex contention (2t) | RUST | ove::Mutex::lock+unlock (×2t) | 38932 ns | 2881 ns | +36051 ns |
| Mutex contention (2t) | ZIG | ove.Mutex.lock+unlock (×2t) | 33912 ns | 2679 ns | +31233 ns |
| Recursive mutex lock+unlock | C | ove_rmtx_lock+unlock | 3051 ns | 2790 ns | +261 ns |
| Recursive mutex lock+unlock | CPP | ove::RMutex::lock+unlock | 3124 ns | 2744 ns | +380 ns |
| Recursive mutex lock+unlock | RUST | ove::RMutex::lock+unlock | 3353 ns | 2922 ns | +431 ns |
| Recursive mutex lock+unlock | ZIG | ove.RMutex.lock+unlock | 2920 ns | 2674 ns | +246 ns |
| Sem take+give | C | ove_sem_take+give | 2045 ns | 1739 ns | +306 ns |
| Sem take+give | CPP | ove::Sem::take+give | 2151 ns | 1564 ns | +587 ns |
| Sem take+give | RUST | ove::Sem::take+give | 2128 ns | 1599 ns | +529 ns |
| Sem take+give | ZIG | ove.Sem.take+give | 2091 ns | 1661 ns | +430 ns |
| Sem create+destroy | C | ove_sem_create+destroy | 11966 ns | 749 ns | +11217 ns |
| Sem create+destroy | CPP | ove::Sem (ctor+dtor) | 12290 ns | 753 ns | +11537 ns |
| Sem create+destroy | RUST | ove::Sem (new+drop) | 12607 ns | 824 ns | +11783 ns |
| Sem create+destroy | ZIG | ove.Sem.create+destroy | 11883 ns | 648 ns | +11235 ns |
| Condvar signal+wait | C | ove_condvar_signal+wait | 65072 ns | 66868 ns | -1796 ns |
| Condvar signal+wait | CPP | ove::Condvar::signal+wait | 63871 ns | 66068 ns | -2197 ns |
| Condvar signal+wait | RUST | ove::Condvar::signal+wait | 64594 ns | 66094 ns | -1500 ns |
| Condvar signal+wait | ZIG | ove.Condvar.signal+wait | 63280 ns | 65637 ns | -2357 ns |
| Event signal+wait | C | ove_event_signal+wait | 56605 ns | 63236 ns | -6631 ns |
| Event signal+wait | CPP | ove::Event::signal+wait | 54739 ns | 62632 ns | -7893 ns |
| Event signal+wait | RUST | ove::Event::signal+wait | 55586 ns | 62407 ns | -6821 ns |
| Event signal+wait | ZIG | ove.Event.signal+wait | 54540 ns | 61944 ns | -7404 ns |
| Queue send+receive | C | ove_queue_send+receive | 4733 ns | 4766 ns | -33 ns |
| Queue send+receive | CPP | ove::Queue::send+recv | 4308 ns | 4013 ns | +295 ns |
| Queue send+receive | RUST | ove::Queue::send+recv | 5993 ns | 5932 ns | +61 ns |
| Queue send+receive | ZIG | ove.Queue.send+recv | 4407 ns | 4142 ns | +265 ns |
| Queue create+destroy | C | ove_queue_create+destroy | 19975 ns | 1313 ns | +18662 ns |
| Queue create+destroy | CPP | ove::Queue (ctor+dtor) | 20712 ns | 1074 ns | +19638 ns |
| Queue create+destroy | RUST | ove::Queue (new+drop) | 21392 ns | 1258 ns | +20134 ns |
| Queue create+destroy | ZIG | ove.Queue.create+destroy | 21309 ns | 1137 ns | +20172 ns |
| Stream send+recv 64B | C | ove_stream_send+recv 64B | 14295 ns | 12775 ns | +1520 ns |
| Stream send+recv 64B | CPP | ove::Stream::send+recv 64B | 14345 ns | 12762 ns | +1583 ns |
| Stream send+recv 64B | RUST | ove::Stream::send+recv 64B | 17324 ns | 11018 ns | +6306 ns |
| Stream send+recv 64B | ZIG | ove.Stream.send+recv 64B | 14163 ns | 12712 ns | +1451 ns |