Skip to content

NuttX — heap mode

Raw cross-binding benchmark results measured on STM32F746G-DISCOVERY (Cortex-M7 @ 216 MHz) running Apache NuttX 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: NuttX 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_nuttx.c is C code calling raw NuttX APIs (nxsem_*, pthread_*), compiled identically into every binary; the CPP/RUST/ZIG columns for those rows are the same C code measured in three different processes.

NuttX

Suite Case C CPP Δ CPP RUST Δ RUST ZIG Δ ZIG
time time_get_us_overhead 3.0 µs 3.1 µs +4.8% 3.1 µs +3.9% 3.0 µs +1.5%
time delay_1ms 1.98 ms 1.98 ms +0.0% 1.98 ms +0.0% 1.98 ms +0.0%
thread create_destroy 617.0 µs 623.0 µs +1.0% 591.4 µs -4.1% 591.2 µs -4.2%
thread yield 3.6 µs 3.8 µs +6.3% 3.7 µs +3.0% 3.5 µs -2.5%
thread get_self 2.6 µs 2.6 µs -1.1% 2.8 µs +8.0% 2.5 µs -5.8%
thread sleep_1ms 1.98 ms 1.98 ms +0.0% 1.98 ms +0.0% 1.98 ms +0.0%
thread context_switch 45.8 µs 45.6 µs -0.4% 45.8 µs +0.1%
sync mutex_memory 24 B 24 B 24 B 24 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 40 B 40 B 40 B 40 B
sync mutex_lock_unlock 5.4 µs 5.4 µs +0.9% 5.3 µs -1.0% 5.5 µs +2.2%
sync mutex_create_destroy 29.0 µs 29.3 µs +0.9% 30.4 µs +4.6% 29.2 µs +0.6%
sync mutex_contention_2t 4.7 µs 5.0 µs +6.5% 4.8 µs +2.6% 4.8 µs +2.6%
sync sem_take_give 4.3 µs 4.2 µs -2.1% 4.8 µs +12.5% 4.2 µs -1.8%
sync sem_create_destroy 27.7 µs 28.1 µs +1.3% 28.9 µs +4.3% 28.0 µs +0.9%
sync event_signal_wait 45.3 µs 45.5 µs +0.4% 46.6 µs +2.8% 45.8 µs +1.0%
sync condvar_signal_wait 62.8 µs 63.0 µs +0.4% 63.9 µs +1.8% 63.6 µs +1.4%
sync recursive_mutex_lock_unlock 8.5 µs 8.2 µs -2.7% 8.4 µs -0.7% 8.2 µs -2.9%
queue memory 96 B 96 B 96 B 96 B
queue send_receive 11.8 µs 11.6 µs -1.5% 11.9 µs +1.6% 12.5 µs +6.4%
queue create_destroy 57.4 µs 57.7 µs +0.5% 57.7 µs +0.4% 59.4 µs +3.4%
queue throughput_2t 8.2 µs 7.5 µs -8.6% 8.2 µs -0.4% 8.4 µs +2.6%
timer memory 24 B 24 B 24 B
timer create_destroy 70.5 µs 66.7 µs -5.4% 67.0 µs -5.0%
timer start_stop 27.7 µs 27.2 µs -2.0% 26.9 µs -3.0%
eventgroup memory 32 B 32 B 32 B
eventgroup set_get_bits 1.7 µs 1.9 µs +7.7% 1.7 µs -3.4%
eventgroup create_destroy 27.8 µs 28.3 µs +1.8% 28.0 µs +0.7%
workqueue memory 3168 B 3200 B 3168 B 3168 B
workqueue create_destroy 526.5 µs 528.8 µs +0.4% 535.5 µs +1.7% 533.3 µs +1.3%
workqueue submit_execute 67.0 µs 67.7 µs +1.1% 69.1 µs +3.1% 68.1 µs +1.5%
stream memory 360 B 360 B 360 B 360 B
stream send_recv_64B 54.0 µs 53.2 µs -1.4% 53.4 µs -1.0% 53.2 µs -1.3%
stream create_destroy 63.8 µs 63.4 µs -0.7% 64.0 µs +0.2% 63.2 µs -1.0%
stream throughput 69.3 µs 68.2 µs -1.6% 90.7 µs +30.9% 67.5 µs -2.6%
native_nuttx native_mutex_lock_unlock 15.0 µs 15.0 µs -0.3% 14.9 µs -1.1% 15.0 µs -0.3%
native_nuttx native_mutex_create_destroy 5.6 µs 5.7 µs +3.1% 5.2 µs -6.6% 5.3 µs -4.6%
native_nuttx native_mutex_contention_2t 14.0 µs 14.0 µs +0.2% 14.1 µs +1.0% 14.2 µs +1.0%
native_nuttx native_recursive_mutex_lock_unlock 14.0 µs 14.0 µs +0.3% 14.2 µs +1.4% 14.1 µs +1.0%
native_nuttx native_sem_take_give 4.5 µs 4.6 µs +2.3% 4.5 µs -1.3% 4.3 µs -3.8%
native_nuttx native_sem_create_destroy 3.1 µs 3.2 µs +2.1% 3.0 µs -5.3% 3.1 µs -2.1%
native_nuttx native_condvar_signal_wait 99.0 µs 98.8 µs -0.2% 98.9 µs -0.1% 97.8 µs -1.2%
native_nuttx native_event_signal_wait 81.8 µs 98.5 µs +20.4% 98.6 µs +20.5% 80.2 µs -1.9%
native_nuttx native_thread_yield 3.5 µs 3.6 µs +2.3% 3.5 µs -1.2% 3.3 µs -5.4%
native_nuttx native_thread_sleep_1ms 1.98 ms 1.98 ms +0.0% 1.98 ms +0.0% 1.98 ms +0.0%
native_nuttx native_thread_create_destroy 495.4 µs 500.8 µs +1.1% 488.3 µs -1.4% 489.4 µs -1.2%
native_nuttx native_thread_context_switch 45.5 µs 45.5 µs -0.0% 45.1 µs -1.0% 45.4 µs -0.4%
native_nuttx native_queue_send_receive 33.4 µs 33.2 µs -0.6% 33.9 µs +1.5% 34.7 µs +3.9%
native_nuttx native_queue_create_destroy 397.1 µs 398.8 µs +0.4% 394.8 µs -0.6% 395.5 µs -0.4%
thread ctx_switch 46.4 µs

Cases with |Δ| > 10.0% vs C:

  • RUST stream/throughput 90709 vs 69311 (+30.9%)
  • RUST native_nuttx/native_event_signal_wait 98571 vs 81778 (+20.5%)
  • CPP native_nuttx/native_event_signal_wait 98477 vs 81778 (+20.4%)
  • RUST sync/sem_take_give 4807 vs 4271 (+12.5%)

Wrapper vs native NuttX API (within-run delta)

Each row pairs one binding's wrapper measurement against the raw NuttX 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 3593 ns 3494 ns +99 ns
Thread yield CPP ove::Thread::yield 3820 ns 3576 ns +244 ns
Thread yield RUST ove::Thread::yield 3701 ns 3451 ns +250 ns
Thread yield ZIG ove.Thread.yield 3504 ns 3304 ns +200 ns
Thread sleep 1ms C ove_thread_sleep_ms(1) 1983491 ns 1983433 ns +58 ns
Thread sleep 1ms CPP ove::Thread::sleep_ms(1) 1983931 ns 1984009 ns -78 ns
Thread sleep 1ms RUST ove::Thread::sleep_ms(1) 1984299 ns 1984228 ns +71 ns
Thread sleep 1ms ZIG ove.Thread.sleepMs(1) 1983887 ns 1983892 ns -5 ns
Thread create+destroy C ove_thread_create+destroy 617033 ns 495431 ns +121602 ns
Thread create+destroy CPP ove::Thread (ctor+dtor) 622994 ns 500848 ns +122146 ns
Thread create+destroy RUST ove::Thread::spawn+join 591433 ns 488292 ns +103141 ns
Thread create+destroy ZIG ove.Thread.spawn+join 591226 ns 489374 ns +101852 ns
Thread context_switch (2t) C ove ping-pong (2t) 45764 ns 45543 ns +221 ns
Thread context_switch (2t) CPP ove ping-pong (2t) 45565 ns 45533 ns +32 ns
Thread context_switch (2t) ZIG ove ping-pong (2t) 45824 ns 45378 ns +446 ns
Mutex lock+unlock C ove_mutex_lock+unlock 5372 ns 15042 ns -9670 ns
Mutex lock+unlock CPP ove::Mutex::lock+unlock 5421 ns 14991 ns -9570 ns
Mutex lock+unlock RUST ove::Mutex::lock+unlock 5317 ns 14870 ns -9553 ns
Mutex lock+unlock ZIG ove.Mutex.lock+unlock 5491 ns 15003 ns -9512 ns
Mutex create+destroy C ove_mutex_create+destroy 29028 ns 5561 ns +23467 ns
Mutex create+destroy CPP ove::Mutex (ctor+dtor) 29285 ns 5736 ns +23549 ns
Mutex create+destroy RUST ove::Mutex (new+drop) 30376 ns 5193 ns +25183 ns
Mutex create+destroy ZIG ove.Mutex.create+destroy 29204 ns 5305 ns +23899 ns
Mutex contention (2t) C ove_mutex_lock+unlock (×2t) 4665 ns 14014 ns -9349 ns
Mutex contention (2t) CPP ove::Mutex::lock+unlock (×2t) 4968 ns 14041 ns -9073 ns
Mutex contention (2t) RUST ove::Mutex::lock+unlock (×2t) 4784 ns 14148 ns -9364 ns
Mutex contention (2t) ZIG ove.Mutex.lock+unlock (×2t) 4785 ns 14154 ns -9369 ns
Recursive mutex lock+unlock C ove_rmtx_lock+unlock 8480 ns 13962 ns -5482 ns
Recursive mutex lock+unlock CPP ove::RMutex::lock+unlock 8247 ns 14008 ns -5761 ns
Recursive mutex lock+unlock RUST ove::RMutex::lock+unlock 8417 ns 14161 ns -5744 ns
Recursive mutex lock+unlock ZIG ove.RMutex.lock+unlock 8234 ns 14100 ns -5866 ns
Sem take+give C ove_sem_take+give 4271 ns 4515 ns -244 ns
Sem take+give CPP ove::Sem::take+give 4181 ns 4621 ns -440 ns
Sem take+give RUST ove::Sem::take+give 4807 ns 4458 ns +349 ns
Sem take+give ZIG ove.Sem.take+give 4192 ns 4343 ns -151 ns
Sem create+destroy C ove_sem_create+destroy 27743 ns 3120 ns +24623 ns
Sem create+destroy CPP ove::Sem (ctor+dtor) 28117 ns 3187 ns +24930 ns
Sem create+destroy RUST ove::Sem (new+drop) 28924 ns 2954 ns +25970 ns
Sem create+destroy ZIG ove.Sem.create+destroy 27980 ns 3053 ns +24927 ns
Condvar signal+wait C ove_condvar_signal+wait 62779 ns 98978 ns -36199 ns
Condvar signal+wait CPP ove::Condvar::signal+wait 63014 ns 98799 ns -35785 ns
Condvar signal+wait RUST ove::Condvar::signal+wait 63879 ns 98852 ns -34973 ns
Condvar signal+wait ZIG ove.Condvar.signal+wait 63641 ns 97830 ns -34189 ns
Event signal+wait C ove_event_signal+wait 45346 ns 81778 ns -36432 ns
Event signal+wait CPP ove::Event::signal+wait 45532 ns 98477 ns -52945 ns
Event signal+wait RUST ove::Event::signal+wait 46609 ns 98571 ns -51962 ns
Event signal+wait ZIG ove.Event.signal+wait 45822 ns 80228 ns -34406 ns
Queue send+receive C ove_queue_send+receive 11759 ns 33412 ns -21653 ns
Queue send+receive CPP ove::Queue::send+recv 11578 ns 33200 ns -21622 ns
Queue send+receive RUST ove::Queue::send+recv 11948 ns 33905 ns -21957 ns
Queue send+receive ZIG ove.Queue.send+recv 12510 ns 34730 ns -22220 ns
Queue create+destroy C ove_queue_create+destroy 57441 ns 397072 ns -339631 ns
Queue create+destroy CPP ove::Queue (ctor+dtor) 57729 ns 398829 ns -341100 ns
Queue create+destroy RUST ove::Queue (new+drop) 57670 ns 394772 ns -337102 ns
Queue create+destroy ZIG ove.Queue.create+destroy 59390 ns 395493 ns -336103 ns