bench_hll_vs_cpc.nx source
↩ module page · 77 lines · 2747 B
1// bench_hll_vs_cpc.nx -- head-to-head workload runner.
2//
3// Streams N distinct synthetic keys through OUR HLL_8 and OUR CPC at
4// matched lg_k, then feeds estimates + memory into the comparator
5// for a sealed verdict.
6//
7// This is sister-comparison (our vs our), validating Lang 2017's HIP
8// claim that CPC beats HLL on accuracy at same memory. The harness
9// extends naturally: swap CPC for a Python-datasketches stub to compare
10// against the incumbent.
11
12import "syscalls.nx"
13import "sketch_hll.nx"
14import "sketch_cpc.nx"
15import "sketch_comparator.nx"
16import "sketch_types.nx"
17
18func main() -> i64 {
19 let lg_k: i64 = 7 // m = 128 for both
20 let n: i64 = 1000 // distinct keys
21
22 let hll: *Hll = nx_hll_alloc(lg_k, 42)
23 let cpc: *Cpc = nx_cpc_alloc(lg_k, 8192, 42)
24 if hll == (0 as *Hll) { return __syscall(93, 5, 0, 0, 0, 0, 0) }
25 if cpc == (0 as *Cpc) { return __syscall(93, 6, 0, 0, 0, 0, 0) }
26
27 // Stream N distinct 8-byte keys through both.
28 let buf: *u8 = sys_mmap(8)
29 var i: i64 = 0
30 while i < n {
31 buf[0] = (i ) & 0xFF
32 buf[1] = (i >> 8 ) & 0xFF
33 buf[2] = (i >> 16) & 0xFF
34 buf[3] = 0xA1
35 buf[4] = 0
36 buf[5] = 0
37 buf[6] = 0
38 buf[7] = 0
39 nx_hll_add(hll, buf, 8)
40 nx_cpc_add(cpc, buf, 8)
41 i = i + 1
42 }
43
44 let hll_est: i64 = nx_hll_estimate(hll)
45 let cpc_est: i64 = nx_cpc_estimate(cpc)
46
47 // --- ACCURACY: who's closer to truth = n ? ---
48 // "ours" = CPC (the claimed-better one); "theirs" = HLL (baseline)
49 let r_acc: *ComparisonResult = nx_cmp_accuracy(cpc_est, hll_est, n, 10000)
50
51 // --- MEMORY: CPC vs HLL footprint ---
52 let cpc_mem: i64 = nx_cpc_memory_bytes(cpc)
53 let hll_mem: i64 = 24 + (1 << lg_k) // HLL header + register array
54 let r_mem: *ComparisonResult = nx_cmp_memory(cpc_mem, hll_mem, 10000)
55
56 // --- TIME: skip (would need external wall-clock; report as EQUIV) ---
57 let r_tim: *ComparisonResult = nx_cmp_time(100, 100, 10000)
58
59 // --- COMPOSITE verdict ---
60 let composite: i64 = nx_cmp_composite(r_acc, r_mem, r_tim)
61
62 // --- Encode results into i64 return for harness to parse ---
63 // Bits 0-3: accuracy verdict
64 // Bits 4-7: memory verdict
65 // Bits 8-11: time verdict
66 // Bits 12-15: composite
67 // Bits 16-31: hll_est (16-bit truncated)
68 // Bits 32-47: cpc_est (16-bit truncated)
69 var ret: i64 = 0
70 ret = ret | r_acc.verdict
71 ret = ret | (r_mem.verdict << 4)
72 ret = ret | (r_tim.verdict << 8)
73 ret = ret | (composite << 12)
74 ret = ret | ((hll_est & 0xFFFF) << 16)
75 ret = ret | ((cpc_est & 0xFFFF) << 32)
76 return ret
77}