code wiki / (root) / bench_hll_vs_cpc.nx

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}