==> tests/bench.c <==1/* Not a check: how much slower the interpreter is than native code on the differential fixture
2 * (integer and float work), printed for the README. Always passes once the results agree. */
3#define _XOPEN_SOURCE 700
4#include "mesh/check.h"
5#include "wasm/interp.h"
6
7#include <stdio.h>
8#include <time.h>
9
10#define PROG_PREFIX(x) native_##x
11#include "fixtures/prog.c"
12#include "fixtures/prog.h"
13
14static double now(void) {
15 struct timespec t;
16 clock_gettime(CLOCK_MONOTONIC, &t);
17 return (double)t.tv_sec + (double)t.tv_nsec / 1e9;
18}
19
20int main(void) {
21 char err[256];
22 wasm_compiled *c = wasm_compile(prog_wasm, prog_wasm_len, WASM_F_INTERP, err, sizeof err);
23 CHECK(c != NULL);
24 wasm_instance *I = c ? wasm_instantiate(c, NULL, 0, NULL, NULL, err, sizeof err) : NULL;
25 CHECK(I != NULL);
26 if (!I) return mesh_check_done();
27 uint32_t fns[2] = {(uint32_t)wasm_instance_func(I, "run", "i>i", err, sizeof err),
28 (uint32_t)wasm_instance_func(I, "fp_run", "i>i", err, sizeof err)};
29 const char *names[2] = {"run (integer)", "fp_run (float)"};
30 for (int k = 0; k < 2; k++) {
31 volatile uint32_t sink = 0;
32 double t0 = now();
33 int n = 0;
34 while (now() - t0 < 0.3) {
35 sink ^= k ? native_fp_run((uint32_t)n) : native_run((uint32_t)n);
36 n++;
37 }
38 double native = (now() - t0) / n;
39 t0 = now();
40 int m = 0;
41 while (now() - t0 < 0.3) {
42 uint64_t io[1] = {(uint64_t)m};
43 CHECK_I(wasm_call(I, fns[k], io), WASM_NUM_OK);
44 sink ^= (uint32_t)io[0];
45 m++;
46 }
47 double interp = (now() - t0) / m;
48 fprintf(stderr, "bench %s: native %.1f us, interpreted %.1f us: %.1fx\n", names[k], native * 1e6, interp * 1e6,
49 interp / native);
50 (void)sink;
51 }
52 wasm_instance_free(I);
53 wasm_compiled_free(c);
54 return mesh_check_done();
55}