summaryrefslogtreecommitdiff
path: root/ocaml/bench_simple.c
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml/bench_simple.c')
-rw-r--r--ocaml/bench_simple.c265
1 files changed, 265 insertions, 0 deletions
diff --git a/ocaml/bench_simple.c b/ocaml/bench_simple.c
new file mode 100644
index 0000000..530746f
--- /dev/null
+++ b/ocaml/bench_simple.c
@@ -0,0 +1,265 @@
+/// Simple standalone Nock benchmark
+/// This is a simplified version that doesn't require linking against full Vere
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <time.h>
+#include <sys/time.h>
+#include <gmp.h>
+
+// Simplified noun type (direct atom or indirect cell)
+typedef uintptr_t noun;
+
+#define IS_ATOM(n) (!((n) & 1))
+#define IS_CELL(n) ((n) & 1)
+#define MAKE_DIRECT_ATOM(n) ((noun)(n) << 1)
+#define GET_DIRECT_ATOM(n) ((n) >> 1)
+
+// Simple cell structure
+typedef struct cell_s {
+ noun head;
+ noun tail;
+} cell_t;
+
+#define CELL_PTR(n) ((cell_t*)((n) & ~1ULL))
+#define MAKE_CELL(ptr) ((noun)ptr | 1)
+
+static noun
+make_atom(uint64_t val)
+{
+ return MAKE_DIRECT_ATOM(val);
+}
+
+static noun
+make_cell(noun head, noun tail)
+{
+ cell_t* c = malloc(sizeof(cell_t));
+ c->head = head;
+ c->tail = tail;
+ return MAKE_CELL(c);
+}
+
+static noun
+head(noun n)
+{
+ return CELL_PTR(n)->head;
+}
+
+static noun
+tail(noun n)
+{
+ return CELL_PTR(n)->tail;
+}
+
+// Simplified slot (no error handling)
+static noun
+slot(uint64_t axis, noun n)
+{
+ if (axis == 1) return n;
+ if (axis & 1) {
+ // Odd: go right (tail)
+ return slot(axis >> 1, tail(n));
+ } else {
+ // Even: go left (head)
+ return slot(axis >> 1, head(n));
+ }
+}
+
+// Ultra-simplified nock (only handles the opcodes we benchmark)
+static noun
+nock_simple(noun subject, noun formula)
+{
+ if (IS_CELL(formula) && IS_CELL(head(formula))) {
+ // Cell construction: [[a b] c] -> [nock(a) nock(c)]
+ noun h = nock_simple(subject, head(formula));
+ noun t = nock_simple(subject, tail(formula));
+ return make_cell(h, t);
+ }
+
+ if (!IS_CELL(formula)) return 0; // Error
+
+ noun op = head(formula);
+ noun arg = tail(formula);
+
+ if (!IS_ATOM(op)) return 0; // Error
+
+ uint64_t opcode = GET_DIRECT_ATOM(op);
+
+ switch (opcode) {
+ case 0: // slot
+ if (!IS_ATOM(arg)) return 0;
+ return slot(GET_DIRECT_ATOM(arg), subject);
+
+ case 1: // constant
+ return arg;
+
+ case 3: { // is-cell
+ noun val = nock_simple(subject, arg);
+ return IS_CELL(val) ? make_atom(0) : make_atom(1);
+ }
+
+ case 4: { // increment
+ noun val = nock_simple(subject, arg);
+ if (!IS_ATOM(val)) return 0;
+ return MAKE_DIRECT_ATOM(GET_DIRECT_ATOM(val) + 1);
+ }
+
+ case 5: { // equality
+ noun pair = nock_simple(subject, arg);
+ noun a = head(pair);
+ noun b = tail(pair);
+ // Simplified: only works for direct atoms
+ if (IS_ATOM(a) && IS_ATOM(b)) {
+ return (a == b) ? make_atom(0) : make_atom(1);
+ }
+ return make_atom(1);
+ }
+
+ case 6: { // if-then-else
+ noun test_fol = head(arg);
+ noun yes_fol = head(tail(arg));
+ noun no_fol = tail(tail(arg));
+
+ noun test_val = nock_simple(subject, test_fol);
+ uint64_t test = GET_DIRECT_ATOM(test_val);
+
+ if (test == 0) {
+ return nock_simple(subject, yes_fol);
+ } else {
+ return nock_simple(subject, no_fol);
+ }
+ }
+
+ case 7: { // composition
+ noun b = head(arg);
+ noun c = tail(arg);
+ noun new_subj = nock_simple(subject, b);
+ return nock_simple(new_subj, c);
+ }
+
+ case 8: { // push
+ noun b = head(arg);
+ noun c = tail(arg);
+ noun val = nock_simple(subject, b);
+ noun new_subj = make_cell(val, subject);
+ return nock_simple(new_subj, c);
+ }
+
+ default:
+ return 0; // Error
+ }
+}
+
+static double
+get_time_ms(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (tv.tv_sec * 1000.0) + (tv.tv_usec / 1000.0);
+}
+
+static void
+bench(const char* name, noun subject, noun formula, int iterations)
+{
+ double start = get_time_ms();
+
+ for (int i = 0; i < iterations; i++) {
+ noun _result = nock_simple(subject, formula);
+ // Note: we're leaking memory here, but it's fine for a benchmark
+ }
+
+ double end = get_time_ms();
+ double total = end - start;
+ double per_iter = total / iterations;
+
+ printf("%-30s %8d iterations in %10.2f ms (%10.6f ms/iter, %10.0f ops/sec)\n",
+ name, iterations, total, per_iter, 1000.0 / per_iter);
+}
+
+int main()
+{
+ printf("Nock Benchmark - Simple C Implementation\n");
+ printf("=========================================\n");
+ printf("(Simplified version without full Vere infrastructure)\n\n");
+
+ int iterations = 1000000;
+ int slow_iters = 100000;
+
+ // Benchmark 0: slot
+ bench("Opcode 0: slot/fragment",
+ make_cell(make_atom(42), make_atom(99)),
+ make_cell(make_atom(0), make_atom(2)),
+ iterations);
+
+ // Benchmark 1: constant
+ bench("Opcode 1: constant",
+ make_atom(0),
+ make_cell(make_atom(1), make_atom(42)),
+ iterations);
+
+ // Benchmark 3: is-cell
+ bench("Opcode 3: is-cell (atom)",
+ make_atom(0),
+ make_cell(make_atom(3), make_cell(make_atom(1), make_atom(42))),
+ iterations);
+
+ // Benchmark 4: increment
+ bench("Opcode 4: increment",
+ make_atom(0),
+ make_cell(make_atom(4), make_cell(make_atom(1), make_atom(1000))),
+ iterations);
+
+ // Benchmark 5: equality
+ bench("Opcode 5: equality (equal)",
+ make_atom(0),
+ make_cell(make_atom(5),
+ make_cell(make_cell(make_atom(1), make_atom(42)),
+ make_cell(make_atom(1), make_atom(42)))),
+ iterations);
+
+ // Benchmark 6: if-then-else
+ bench("Opcode 6: if-then-else",
+ make_atom(0),
+ make_cell(make_atom(6),
+ make_cell(make_cell(make_atom(1), make_atom(0)),
+ make_cell(make_cell(make_atom(1), make_atom(11)),
+ make_cell(make_atom(1), make_atom(22))))),
+ iterations);
+
+ // Benchmark 7: composition
+ bench("Opcode 7: composition",
+ make_atom(42),
+ make_cell(make_atom(7),
+ make_cell(make_cell(make_atom(1), make_atom(99)),
+ make_cell(make_atom(0), make_atom(1)))),
+ iterations);
+
+ // Benchmark 8: push
+ bench("Opcode 8: push",
+ make_atom(42),
+ make_cell(make_atom(8),
+ make_cell(make_cell(make_atom(1), make_atom(99)),
+ make_cell(make_atom(0), make_atom(1)))),
+ iterations);
+
+ // Cell construction
+ bench("Cell construction",
+ make_atom(0),
+ make_cell(make_cell(make_atom(1), make_atom(1)),
+ make_cell(make_atom(1), make_atom(2))),
+ iterations);
+
+ // Deep slot lookup
+ bench("Deep slot lookup (depth 4)",
+ make_cell(make_cell(make_cell(make_cell(make_atom(1), make_atom(2)),
+ make_atom(3)),
+ make_atom(4)),
+ make_atom(5)),
+ make_cell(make_atom(0), make_atom(16)),
+ iterations);
+
+ printf("\n");
+
+ return 0;
+}