code wiki / _hdl_build / _cdc_fixture_gen.nx

_cdc_fixture_gen.nx source

↩ module page · 155 lines · 7747 B

1// _cdc_fixture_gen.nx -- LOCAL INSTRUMENT (2026-09-06): a seeded pseudo-random fixture generator and a chunk-length 2// census for the content-defined chunker, so a dedupe accept rule is measured on ENTROPY-BEARING bytes. 3// 4// WHY: the first 64 MiB dedupe measurement used a generated PNG whose IDAT is a stored deflate block of a period-3 5// byte pattern (1 MiB gzips to 5,678 B). A gear fingerprint over period-3 content takes three values, none hit the 6// mask, so EVERY cut was forced at max (1339 x 48,402 + 28,970 = 64,839,248 exactly) -- fixed-size chunking wearing 7// a content-defined name -- and a one-byte insertion shifted every later cut, so reuse stopped at the insertion 8// point (661 of 1340 = the offset-preserving prefix, 49.3 percent = 32,000,000 / 64,839,248). That is a property of 9// the DATA every chunker shares; the accept rule needs a fixture whose cuts are content-defined. 10// 11// verbs: 12// gen <out> <bytes> <seed> xorshift64* stream, deterministic for (bytes, seed) 13// insert <in> <out> <offset> <byte> copy with ONE byte inserted at offset (the dedupe workload) 14// chunks <file> <min> <avg> <max> cut with nx_cdc_lib at the door's own parameters; prints count, min/max/avg 15// length, how many cuts were FORCED at max, and the gzip-free entropy proxy 16// (distinct bytes in the first block) 17// exit: 0 ok | 2 usage | 1 io 18import "nx_syscalls.nx" 19import "nx_cdc_lib.nx" 20const FG_BLOCK: i64 = 1048576 21const FG_EXIT_USAGE: i64 = 2 22const FG_EXIT_IO: i64 = 1 23const FG_MODE_644: i64 = 420 24const FG_XS_A: i64 = 12 25const FG_XS_B: i64 = 25 26const FG_XS_C: i64 = 27 27const FG_XS_MUL: i64 = 2685821657736338717 28 29func fg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 30func fg_puts(s: *u8) -> i64 { return sys_write(1, s, fg_slen(s)) } 31func fg_putn(v: i64) -> i64 { 32 let b: *u8 = sys_mmap(32) 33 var n: i64 = v 34 var neg: i64 = 0 35 if n < 0 { neg = 1; n = 0 - n } 36 var k: i64 = 0 37 if n == 0 { b[0] = 48 as u8; k = 1 } 38 let t: *u8 = sys_mmap(32) 39 var m: i64 = 0 40 while n > 0 { t[m] = (48 + (n % 10)) as u8; n = n / 10; m = m + 1 } 41 var o: i64 = 0 42 if neg == 1 { b[0] = 45 as u8; o = 1 } 43 while m > 0 { m = m - 1; b[o] = t[m]; o = o + 1 } 44 if o == 0 { o = k } 45 return sys_write(1, b, o) 46} 47func fg_parse(s: *u8) -> i64 { 48 var v: i64 = 0 49 var i: i64 = 0 50 while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } i = i + 1 } 51 return v 52} 53// xorshift64*: state must be non-zero; the high byte of the multiplied state is the output byte 54func fg_next(st: *i64) -> i64 { 55 var x: i64 = st[0] 56 x = x ^ (x >> FG_XS_A) 57 x = x ^ (x << FG_XS_B) 58 x = x ^ (x >> FG_XS_C) 59 st[0] = x 60 let y: i64 = x * FG_XS_MUL 61 return (y >> 56) & 255 62} 63func fg_write_all(fd: i64, b: *u8, n: i64) -> i64 { 64 var w: i64 = 0 65 while w < n { let r: i64 = sys_write(fd, ((b as i64) + w) as *u8, n - w); if r <= 0 { return 0 } w = w + r } 66 return 1 67} 68func v_gen(out: *u8, bytes: i64, seed: i64) -> i64 { 69 let st: *i64 = sys_mmap(16) as *i64 70 st[0] = seed 71 if st[0] == 0 { st[0] = 1 } 72 let fd: i64 = sys_openat_wr(out, FG_MODE_644) 73 if fd < 0 { fg_puts("FG-IO cannot open output\n" as *u8); return FG_EXIT_IO } 74 let blk: *u8 = sys_mmap(FG_BLOCK) 75 var left: i64 = bytes 76 while left > 0 { 77 var n: i64 = left 78 if n > FG_BLOCK { n = FG_BLOCK } 79 var i: i64 = 0 80 while i < n { blk[i] = fg_next(st) as u8; i = i + 1 } 81 if fg_write_all(fd, blk, n) == 0 { sys_close(fd); fg_puts("FG-IO short write\n" as *u8); return FG_EXIT_IO } 82 left = left - n 83 } 84 sys_close(fd) 85 fg_puts("FG-GEN bytes=" as *u8); fg_putn(bytes); fg_puts(" seed=" as *u8); fg_putn(seed); fg_puts(" out=" as *u8); fg_puts(out); fg_puts("\n" as *u8) 86 return 0 87} 88func v_insert(inp: *u8, out: *u8, off: i64, byte: i64) -> i64 { 89 let lp: *i64 = sys_mmap(16) as *i64 90 let b: *u8 = sys_read_file(inp, lp) 91 if (b as i64) == 0 { fg_puts("FG-IO cannot read input\n" as *u8); return FG_EXIT_IO } 92 let n: i64 = lp[0] 93 if off > n { fg_puts("FG-USAGE offset past end\n" as *u8); return FG_EXIT_USAGE } 94 let fd: i64 = sys_openat_wr(out, FG_MODE_644) 95 if fd < 0 { fg_puts("FG-IO cannot open output\n" as *u8); return FG_EXIT_IO } 96 let one: *u8 = sys_mmap(8) 97 one[0] = byte as u8 98 var ok: i64 = fg_write_all(fd, b, off) 99 if ok == 1 { ok = fg_write_all(fd, one, 1) } 100 if ok == 1 { ok = fg_write_all(fd, ((b as i64) + off) as *u8, n - off) } 101 sys_close(fd) 102 if ok == 0 { fg_puts("FG-IO short write\n" as *u8); return FG_EXIT_IO } 103 fg_puts("FG-INSERT in_bytes=" as *u8); fg_putn(n); fg_puts(" out_bytes=" as *u8); fg_putn(n + 1); fg_puts(" at=" as *u8); fg_putn(off); fg_puts("\n" as *u8) 104 return 0 105} 106func v_chunks(path: *u8, mn: i64, avg: i64, mx: i64) -> i64 { 107 let lp: *i64 = sys_mmap(16) as *i64 108 let b: *u8 = sys_read_file(path, lp) 109 if (b as i64) == 0 { fg_puts("FG-IO cannot read file\n" as *u8); return FG_EXIT_IO } 110 let n: i64 = lp[0] 111 let tbl: *u8 = sys_mmap(CDC_GEAR_BYTES) 112 cdc_gear_table(tbl) 113 let cap: i64 = n / mn + 2 114 let offs: *i64 = sys_mmap(cap * 8) as *i64 115 let count: i64 = cdc_plan(tbl, b, n, mn, avg, mx, offs, cap) 116 if count < 0 { fg_puts("FG-CDC refused parameters\n" as *u8); return FG_EXIT_USAGE } 117 var lmin: i64 = n 118 var lmax: i64 = 0 119 var forced: i64 = 0 120 var k: i64 = 0 121 while k < count { 122 let l: i64 = offs[k + 1] - offs[k] 123 if l < lmin { lmin = l } 124 if l > lmax { lmax = l } 125 if l == mx { forced = forced + 1 } 126 k = k + 1 127 } 128 // entropy proxy: distinct byte values in the first block (256 = entropy-bearing, a handful = periodic) 129 let seen: *u8 = sys_mmap(256) 130 var d: i64 = 0 131 var i: i64 = 0 132 var lim: i64 = n 133 if lim > FG_BLOCK { lim = FG_BLOCK } 134 while i < lim { let c: i64 = b[i] as i64; if seen[c] == (0 as u8) { seen[c] = 1 as u8; d = d + 1 } i = i + 1 } 135 fg_puts("FG-CHUNKS bytes=" as *u8); fg_putn(n) 136 fg_puts(" min=" as *u8); fg_putn(mn); fg_puts(" avg=" as *u8); fg_putn(avg); fg_puts(" max=" as *u8); fg_putn(mx) 137 fg_puts(" count=" as *u8); fg_putn(count) 138 fg_puts(" len_min=" as *u8); fg_putn(lmin); fg_puts(" len_max=" as *u8); fg_putn(lmax) 139 var mean: i64 = 0 140 if count > 0 { mean = n / count } 141 fg_puts(" len_mean=" as *u8); fg_putn(mean) 142 fg_puts(" forced_at_max=" as *u8); fg_putn(forced); fg_puts("/" as *u8); fg_putn(count) 143 fg_puts(" distinct_bytes_first_block=" as *u8); fg_putn(d) 144 fg_puts("\n" as *u8) 145 return 0 146} 147func main(argc: i64, argv: *i64) -> i64 { 148 if argc < 2 { fg_puts("usage: _cdc_fixture_gen gen <out> <bytes> <seed> | insert <in> <out> <offset> <byte> | chunks <file> <min> <avg> <max>\n" as *u8); return FG_EXIT_USAGE } 149 let verb: *u8 = argv[1] as *u8 150 if verb[0] == (103 as u8) { if argc < 5 { fg_puts("usage: gen <out> <bytes> <seed>\n" as *u8); return FG_EXIT_USAGE } return v_gen(argv[2] as *u8, fg_parse(argv[3] as *u8), fg_parse(argv[4] as *u8)) } 151 if verb[0] == (105 as u8) { if argc < 6 { fg_puts("usage: insert <in> <out> <offset> <byte>\n" as *u8); return FG_EXIT_USAGE } return v_insert(argv[2] as *u8, argv[3] as *u8, fg_parse(argv[4] as *u8), fg_parse(argv[5] as *u8)) } 152 if verb[0] == (99 as u8) { if argc < 6 { fg_puts("usage: chunks <file> <min> <avg> <max>\n" as *u8); return FG_EXIT_USAGE } return v_chunks(argv[2] as *u8, fg_parse(argv[3] as *u8), fg_parse(argv[4] as *u8), fg_parse(argv[5] as *u8)) } 153 fg_puts("usage: gen | insert | chunks\n" as *u8) 154 return FG_EXIT_USAGE 155}