code wiki / _hdl_build / nx_search_bench.nx
nx_search_bench.nx source
↩ module page · 141 lines · 6493 B
1// nx_search_bench.nx -- REAL head-to-head onsite-search benchmark (operator: benchmark vs a real
2// incumbent, get baseline from Google Scholar). BASELINE = Google Scholar's actual ranked results for
3// "web development" (fetched live via the browse tool) with real citation counts as the authority
4// signal. METRIC = citation-graded nDCG@10 (standard IR), discount table as DATA. Compares Scholar's
5// relevance ranking vs OUR BM25 ranker over the SAME 10 results. HONEST SCOPE: 1 query, 10 docs (a real
6// slice, not full BEIR -- W-BENCH-DATA-001); data + metric REAL, nothing fabricated. Hand-written =
7// motivates X-AUT-GATE-001 (team authors benchmarks). license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc)
10const K_MAGIC_22000000: i64 = 22000000
11const K_MAGIC_1269: i64 = 1269
12const K_MAGIC_1717: i64 = 1717
13
14func sb_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
15// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer
16// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the
17// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls).
18// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign.
19func sb_n(v: i64) -> i64 { nxi_out(v); return 0 }
20
21func sb_doclen(s: *u8) -> i64 { var n: i64=0; var t: i64=0; var inw: i64=0; while s[n]!=(0 as u8){ if s[n]==(32 as u8){inw=0} else { if inw==0{t=t+1;inw=1} } n=n+1 } return t }
22
23func sb_tok_end(s: *u8, start: i64) -> i64 { var e: i64=start; var fe: i64=1; while fe==1 { if s[e]==(0 as u8){fe=0} else { if s[e]==(32 as u8){fe=0} else {e=e+1} } } return e }
24
25func sb_tf(s: *u8, term: *u8) -> i64 {
26 var tf: i64=0; var i: i64=0
27 var tl: i64=0; while term[tl]!=(0 as u8){tl=tl+1}
28 var go: i64=1
29 while go==1 {
30 while s[i]==(32 as u8) { i=i+1 }
31 if s[i]==(0 as u8) { go=0 } else {
32 let e: i64 = sb_tok_end(s, i)
33 let ln: i64 = e - i
34 var mt: i64 = 0
35 if ln == tl { mt=1; var q: i64=0; while q<tl { if s[i+q]!=term[q]{mt=0} q=q+1 } }
36 if mt==1 { tf=tf+1 }
37 i = e
38 if s[i]==(0 as u8){ go=0 }
39 }
40 }
41 return tf
42}
43
44func sb_bm25(tf: i64, doclen: i64, avgdl: i64) -> i64 {
45 if avgdl<=0 { return 0 }
46 let ratio: i64=(doclen*1000)/avgdl
47 let denom: i64=tf*1000+300+(900*ratio)/1000
48 if denom<=0 { return 0 }
49 return (tf*K_MAGIC_22000000)/denom
50}
51
52// fill score[] with BM25(web)+BM25(development) per title
53func sb_score_all(titles: *i64, n: i64, score: *i64) -> i64 {
54 var tot: i64=0; var i: i64=0
55 let dls: *i64 = sys_mmap(8*32) as *i64
56 while i<n { dls[i]=sb_doclen((titles[i]) as *u8); tot=tot+dls[i]; i=i+1 }
57 let avgdl: i64 = tot/n
58 i=0
59 while i<n {
60 let twf: i64=sb_tf((titles[i]) as *u8, "web" as *u8)
61 let tdf: i64=sb_tf((titles[i]) as *u8, "development" as *u8)
62 score[i]=sb_bm25(twf,dls[i],avgdl)+sb_bm25(tdf,dls[i],avgdl)
63 i=i+1
64 }
65 return 0
66}
67
68// selection sort: fill ord[] with title indices, score descending
69func sb_rank(score: *i64, n: i64, ord: *i64) -> i64 {
70 let used: *i64 = sys_mmap(8*32) as *i64
71 var i: i64=0; while i<n { used[i]=0; i=i+1 }
72 var r: i64=0
73 while r<n {
74 var best: i64 = 0 - 1
75 var bs: i64 = 0 - 1
76 var j: i64=0
77 while j<n { if used[j]==0 { if score[j]>bs { bs=score[j]; best=j } } j=j+1 }
78 ord[r]=best; used[best]=1; r=r+1
79 }
80 return 0
81}
82
83// DCG over a ranking order: sum gain[order[r]] * disc[r] / 1000
84func sb_dcg(gain: *i64, order: *i64, disc: *i64, n: i64) -> i64 {
85 var d: i64=0; var r: i64=0
86 while r<n { d = d + (gain[order[r]] * disc[r]) / 1000; r=r+1 }
87 return d
88}
89
90func main() -> i64 {
91 let N: i64 = 10
92 let titles: *i64 = sys_mmap(8*16) as *i64
93 titles[0]="php and mysql web development" as *u8 as i64
94 titles[1]="a systematic review of usability evaluation in web development" as *u8 as i64
95 titles[2]="evolutionary web development" as *u8 as i64
96 titles[3]="user centered web development" as *u8 as i64
97 titles[4]="flask web development" as *u8 as i64
98 titles[5]="web design a key factor for the website success" as *u8 as i64
99 titles[6]="web design" as *u8 as i64
100 titles[7]="python web development with django" as *u8 as i64
101 titles[8]="web development estimating quick to market software" as *u8 as i64
102 titles[9]="collaborative web development strategies and best practices for web teams" as *u8 as i64
103 let cites: *i64 = sys_mmap(8*16) as *i64
104 cites[0]=K_MAGIC_1269; cites[1]=130; cites[2]=161; cites[3]=191; cites[4]=K_MAGIC_1717
105 cites[5]=264; cites[6]=291; cites[7]=242; cites[8]=330; cites[9]=169
106 let disc: *i64 = sys_mmap(8*16) as *i64
107 disc[0]=1000; disc[1]=631; disc[2]=500; disc[3]=431; disc[4]=387
108 disc[5]=356; disc[6]=333; disc[7]=315; disc[8]=301; disc[9]=289
109
110 let sch: *i64 = sys_mmap(8*16) as *i64
111 var i: i64=0; while i<N { sch[i]=i; i=i+1 }
112
113 let score: *i64 = sys_mmap(8*16) as *i64
114 sb_score_all(titles, N, score)
115 let ours: *i64 = sys_mmap(8*16) as *i64
116 sb_rank(score, N, ours)
117
118 let idc: *i64 = sys_mmap(8*16) as *i64
119 i=0; while i<N { idc[i]=cites[i]; i=i+1 }
120 i=0; while i<N { var j: i64=i+1; while j<N { if idc[j]>idc[i] { let t: i64=idc[i]; idc[i]=idc[j]; idc[j]=t } j=j+1 } i=i+1 }
121 let ideal: *i64 = sys_mmap(8*16) as *i64
122 i=0; while i<N { ideal[i]=i; i=i+1 }
123
124 let dcg_sch: i64 = sb_dcg(cites, sch, disc, N)
125 let dcg_our: i64 = sb_dcg(cites, ours, disc, N)
126 let dcg_idl: i64 = sb_dcg(idc, ideal, disc, N)
127 var ndcg_sch: i64=0
128 var ndcg_our: i64=0
129 if dcg_idl>0 { ndcg_sch=(dcg_sch*1000)/dcg_idl }
130 if dcg_idl>0 { ndcg_our=(dcg_our*1000)/dcg_idl }
131
132 sb_w("SEARCH-BENCH query=web-development corpus=GoogleScholar-top10 metric=citation-graded-nDCG10\n" as *u8)
133 sb_w(" incumbent_GoogleScholar nDCG_permil=" as *u8); sb_n(ndcg_sch); sb_w("\n" as *u8)
134 sb_w(" ours_BM25_over_titles nDCG_permil=" as *u8); sb_n(ndcg_our); sb_w("\n" as *u8)
135 var verdict: *u8 = "BEHIND" as *u8
136 if ndcg_our > ndcg_sch { verdict="AHEAD" as *u8 }
137 if ndcg_our == ndcg_sch { verdict="PARITY" as *u8 }
138 sb_w(" HEAD-TO-HEAD=" as *u8); sb_w(verdict); sb_w(" (real data+metric; BM25-titles is the FLOOR, 2026 exceed=hybrid+rerank W-SRCH-EX-001)\n" as *u8)
139 sys_exit(0)
140 return 0
141}