Skip to content

Commit aa885cd

Browse files
tbitcsoz-agent
andcommitted
fix(benchmarks): use clock_gettime(CLOCK_MONOTONIC) on native_sim for real timing
native_sim compiles to a native Linux binary, so the host POSIX clock is directly available. Both Zephyr's timing_counter_get() and k_uptime_get_32() measure the simulated Zephyr kernel clock which does NOT advance during CPU-bound loops (it only advances on timer interrupts). Result: always 0. clock_gettime(CLOCK_MONOTONIC) reads the host kernel's real monotonic clock, giving true nanosecond-resolution wall-clock timing for the benchmark loops. Guarded by CONFIG_NATIVE_SIMULATOR so real hardware targets fall back to the Zephyr timing API (k_cycle_get_64 / sys_clock_hw_cycles_per_sec). Co-Authored-By: Oz <oz-agent@warp.dev>
1 parent 9aa63c3 commit aa885cd

2 files changed

Lines changed: 52 additions & 19 deletions

File tree

  • tests/benchmarks

tests/benchmarks/kalman_benchmark/src/main.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,32 @@
1010

1111
#include <zephyr/kernel.h>
1212
#include <zephyr/logging/log.h>
13-
#include <zephyr/timing/timing.h>
1413
#include <arbiter/arbiter.h>
1514
#include "arbiter_model.h"
1615

16+
/* On native_sim the firmware is a native Linux binary: use POSIX
17+
* clock_gettime(CLOCK_MONOTONIC) for real nanosecond timing.
18+
* Zephyr's timing API and k_uptime_get_32() both measure simulated
19+
* Zephyr kernel ticks which do NOT advance during CPU-bound loops.
20+
*/
21+
#ifdef CONFIG_NATIVE_SIMULATOR
22+
#include <time.h>
23+
static inline uint64_t bench_ns(void)
24+
{
25+
struct timespec ts;
26+
clock_gettime(CLOCK_MONOTONIC, &ts);
27+
return (uint64_t)ts.tv_sec * 1000000000ULL + (uint64_t)ts.tv_nsec;
28+
}
29+
#else
30+
/* On real hardware fall back to Zephyr timing API */
31+
#include <zephyr/timing/timing.h>
32+
static inline uint64_t bench_ns(void)
33+
{
34+
return (uint64_t)k_cycle_get_64() * 1000ULL /
35+
(sys_clock_hw_cycles_per_sec() / 1000000ULL);
36+
}
37+
#endif
38+
1739
LOG_MODULE_REGISTER(kf_bench, LOG_LEVEL_INF);
1840

1941
/* ------------------------------------------------------------------ */
@@ -117,11 +139,6 @@ int main(void)
117139
LOG_INF("Iterations: %d (warmup: %d)", BENCH_ITERATIONS,
118140
WARMUP_ITERATIONS);
119141

120-
/* Use k_uptime_get_32() (real-time ms counter) instead of the
121-
* timing API: native_sim's timing_counter_get() measures simulated
122-
* Zephyr clock ticks which do NOT advance during CPU-bound loops.
123-
*/
124-
125142
/* ----- Hand-coded Kalman benchmark ----- */
126143
struct hand_kf hkf;
127144
int32_t true_val = 0;
@@ -142,7 +159,7 @@ int main(void)
142159
true_val = 0;
143160
prng_seed = 42;
144161

145-
uint32_t t0_ms = k_uptime_get_32();
162+
uint64_t t0_ns = bench_ns();
146163

147164
for (int i = 0; i < BENCH_ITERATIONS; i++) {
148165
if (i < 600) {
@@ -151,8 +168,8 @@ int main(void)
151168
hand_kf_tick(&hkf, true_val + prng_noise(3000));
152169
}
153170

154-
uint32_t t1_ms = k_uptime_get_32();
155-
uint64_t hand_ns = (uint64_t)(t1_ms - t0_ms) * 1000000ULL;
171+
uint64_t t1_ns = bench_ns();
172+
uint64_t hand_ns = t1_ns - t0_ns;
156173
uint64_t hand_per_tick = hand_ns / BENCH_ITERATIONS;
157174

158175
LOG_INF("--- Hand-coded Kalman ---");
@@ -199,7 +216,7 @@ int main(void)
199216
true_val = 0;
200217
prng_seed = 42;
201218

202-
uint32_t t2_ms = k_uptime_get_32();
219+
uint64_t t2_ns = bench_ns();
203220

204221
for (int i = 0; i < BENCH_ITERATIONS; i++) {
205222
if (i < 600) {
@@ -219,8 +236,8 @@ int main(void)
219236
ARBITER_eval(&ARBITER_generated_model, &snap, &result, NULL);
220237
}
221238

222-
uint32_t t3_ms = k_uptime_get_32();
223-
uint64_t ARBITER_ns = (uint64_t)(t3_ms - t2_ms) * 1000000ULL;
239+
uint64_t t3_ns = bench_ns();
240+
uint64_t ARBITER_ns = t3_ns - t2_ns;
224241
uint64_t ARBITER_per_tick = ARBITER_ns / BENCH_ITERATIONS;
225242

226243
LOG_INF("--- arbiter Engine Kalman ---");

tests/benchmarks/pid_benchmark/src/main.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,26 @@
1818

1919
#include <zephyr/kernel.h>
2020
#include <zephyr/logging/log.h>
21-
#include <zephyr/timing/timing.h>
2221
#include <arbiter/arbiter.h>
2322
#include "arbiter_model.h"
2423

24+
#ifdef CONFIG_NATIVE_SIMULATOR
25+
#include <time.h>
26+
static inline uint64_t bench_ns(void)
27+
{
28+
struct timespec ts;
29+
clock_gettime(CLOCK_MONOTONIC, &ts);
30+
return (uint64_t)ts.tv_sec * 1000000000ULL + (uint64_t)ts.tv_nsec;
31+
}
32+
#else
33+
#include <zephyr/timing/timing.h>
34+
static inline uint64_t bench_ns(void)
35+
{
36+
return (uint64_t)k_cycle_get_64() * 1000ULL /
37+
(sys_clock_hw_cycles_per_sec() / 1000000ULL);
38+
}
39+
#endif
40+
2541
LOG_MODULE_REGISTER(pid_bench, LOG_LEVEL_INF);
2642

2743
/* ------------------------------------------------------------------ */
@@ -141,15 +157,15 @@ int main(void)
141157
hand_pid_init(&hpid);
142158
plant_h = 0;
143159

144-
uint32_t t0_ms = k_uptime_get_32();
160+
uint64_t t0_ns = bench_ns();
145161

146162
for (int i = 0; i < BENCH_ITERATIONS; i++) {
147163
hand_pid_tick(&hpid, 10000, plant_h);
148164
plant_h += hpid.output / 10;
149165
}
150166

151-
uint32_t t1_ms = k_uptime_get_32();
152-
uint64_t hand_ns = (uint64_t)(t1_ms - t0_ms) * 1000000ULL;
167+
uint64_t t1_ns = bench_ns();
168+
uint64_t hand_ns = t1_ns - t0_ns;
153169
uint64_t hand_per_tick_ns = hand_ns / BENCH_ITERATIONS;
154170

155171
LOG_INF("--- Hand-coded PID ---");
@@ -198,7 +214,7 @@ int main(void)
198214
ARBITER_set_u32(&ARBITER_ctx, F_DT_MS, 10);
199215
plant_z = 0;
200216

201-
uint32_t t2_ms = k_uptime_get_32();
217+
uint64_t t2_ns = bench_ns();
202218

203219
for (int i = 0; i < BENCH_ITERATIONS; i++) {
204220
ARBITER_set_i32(&ARBITER_ctx, F_SETPOINT, 10000);
@@ -214,8 +230,8 @@ int main(void)
214230
plant_z += ARBITER_ctx.fact_values[F_OUTPUT].value / 10;
215231
}
216232

217-
uint32_t t3_ms = k_uptime_get_32();
218-
uint64_t ARBITER_ns = (uint64_t)(t3_ms - t2_ms) * 1000000ULL;
233+
uint64_t t3_ns = bench_ns();
234+
uint64_t ARBITER_ns = t3_ns - t2_ns;
219235
uint64_t ARBITER_per_tick_ns = ARBITER_ns / BENCH_ITERATIONS;
220236

221237
LOG_INF("--- arbiter Engine PID ---");

0 commit comments

Comments
 (0)