code wiki / _hdl_build / nx_uiq_perf.nx

nx_uiq_perf.nx source

↩ module page · 157 lines · 7273 B

1// nx_uiq_perf.nx -- CLI: DETERMINISTIC Core-Web-Vitals STATIC predictor (the quantitative guardrail). 2// Computes, from a page's source, the render-path costs that CWV field metrics punish -- WITHOUT a render: 3// * render-blocking external stylesheets (<link rel=stylesheet>, not preload) -> delays FCP/LCP 4// * render-blocking scripts (<script src> without async/defer) -> blocks parse, hurts INP/TBT 5// * unsized media (<img>/<video> missing width or height) -> CLS risk (>0.1 fails) 6// * page source weight (bytes) -> transfer proxy 7// Reuses the nx_uiq_* family lib (DRY: io + syscalls) -- the second consumer of nx_uiq_color, growing the family. 8// usage: nx_uiq_perf --kat | <html-file-path> -> JSON {bytes,blocking_css,blocking_js,unsized_media,issues,verdict} 9// HONEST ENVELOPE: STATIC predictors of LCP<=2.5s / INP<=200ms / CLS<=0.1 (web.dev/vitals, p75). Measured 10// LCP/INP/CLS + Speed Index need a real render + field RUM (browser-lane / CDP). This flags the source-visible 11// causes; a PASS here is necessary, not sufficient. license_tier: ORIGINAL expect_exit: 0 12import "nx_uiq_color.nx" 13const K_MAGIC_2097152: i64 = 2097152 14 15// substring present in buf[a..b)? 16func perf_has_in(buf: *u8, a: i64, b: i64, pat: *u8) -> i64 { 17 var pl: i64=0; while pat[pl]!=(0 as u8) { pl=pl+1 } 18 if pl==0 { return 0 } 19 var i: i64=a 20 while i+pl<=b { 21 var j: i64=0; var ok: i64=1 22 while j<pl { if buf[a+ (i-a) +j]!=pat[j] { ok=0; j=pl } else { j=j+1 } } 23 if ok==1 { return 1 } 24 i=i+1 25 } 26 return 0 27} 28// index of the next '>' at/after off (tag end), bounded by n. 29func perf_tagend(buf: *u8, n: i64, off: i64) -> i64 { 30 var i: i64=off; var run: i64=1 31 while run==1 { if i<n { if buf[i]==(62 as u8) { run=0 } else { i=i+1 } } else { run=0 } } 32 return i 33} 34// count <img> tags missing width= or height= (CLS risk). 35func perf_unsized_img(buf: *u8, n: i64) -> i64 { 36 var c: i64=0; var i: i64=0 37 while i+4<n { 38 var hit: i64=0 39 if buf[i]==(60 as u8) { if buf[i+1]==(105 as u8) { if buf[i+2]==(109 as u8) { if buf[i+3]==(103 as u8) { hit=1 } } } } 40 if hit==1 { 41 let e: i64 = perf_tagend(buf,n,i+4) 42 var sized: i64=1 43 if perf_has_in(buf,i+4,e,"width" as *u8)==0 { sized=0 } 44 if perf_has_in(buf,i+4,e,"height" as *u8)==0 { sized=0 } 45 if sized==0 { c=c+1 } 46 i=e 47 } else { i=i+1 } 48 } 49 return c 50} 51// count render-blocking <script src=...> (external, no async/defer). 52func perf_blocking_js(buf: *u8, n: i64) -> i64 { 53 var c: i64=0; var i: i64=0 54 while i+7<n { 55 var hit: i64=0 56 if buf[i]==(60 as u8) { if buf[i+1]==(115 as u8) { if buf[i+2]==(99 as u8) { if buf[i+3]==(114 as u8) { if buf[i+4]==(105 as u8) { if buf[i+5]==(112 as u8) { if buf[i+6]==(116 as u8) { hit=1 } } } } } } } 57 if hit==1 { 58 let e: i64 = perf_tagend(buf,n,i+7) 59 if perf_has_in(buf,i+7,e,"src" as *u8)==1 { 60 var blk: i64=1 61 if perf_has_in(buf,i+7,e,"async" as *u8)==1 { blk=0 } 62 if perf_has_in(buf,i+7,e,"defer" as *u8)==1 { blk=0 } 63 if blk==1 { c=c+1 } 64 } 65 i=e 66 } else { i=i+1 } 67 } 68 return c 69} 70// count render-blocking external stylesheets: <link ... stylesheet ...> (not preload). 71func perf_blocking_css(buf: *u8, n: i64) -> i64 { 72 var c: i64=0; var i: i64=0 73 while i+5<n { 74 var hit: i64=0 75 if buf[i]==(60 as u8) { if buf[i+1]==(108 as u8) { if buf[i+2]==(105 as u8) { if buf[i+3]==(110 as u8) { if buf[i+4]==(107 as u8) { hit=1 } } } } } 76 if hit==1 { 77 let e: i64 = perf_tagend(buf,n,i+5) 78 if perf_has_in(buf,i+5,e,"stylesheet" as *u8)==1 { 79 if perf_has_in(buf,i+5,e,"preload" as *u8)==0 { c=c+1 } 80 } 81 i=e 82 } else { i=i+1 } 83 } 84 return c 85} 86 87// audit -> emits JSON when emit=1; returns the count of CWV-critical issues (blocking_css+blocking_js+unsized). 88func perf_audit(buf: *u8, n: i64, emit: i64) -> i64 { 89 let bc: i64 = perf_blocking_css(buf,n) 90 let bj: i64 = perf_blocking_js(buf,n) 91 let um: i64 = perf_unsized_img(buf,n) 92 let issues: i64 = bc + bj + um 93 if emit==1 { 94 uiq_w("{\"bytes\":" as *u8); uiq_pn(n) 95 uiq_w(",\"blocking_css\":" as *u8); uiq_pn(bc) 96 uiq_w(",\"blocking_js\":" as *u8); uiq_pn(bj) 97 uiq_w(",\"unsized_media\":" as *u8); uiq_pn(um) 98 uiq_w(",\"issues\":" as *u8); uiq_pn(issues) 99 uiq_w(",\"verdict\":\"" as *u8) 100 if issues==0 { uiq_w("PASS" as *u8) } else { uiq_w("FLAG" as *u8) } 101 uiq_w("\"}\n" as *u8) 102 } 103 return issues 104} 105 106// self-test: proves each counter on fixtures with a KNOWN answer (non-vacuous + no false positive). 107func uiq_perf_selftest() -> i64 { 108 var f: i64=0 109 // blocking CSS: one stylesheet link + one preload -> exactly 1 110 let a: *u8 = "<link rel=\"stylesheet\" href=\"a.css\"><link rel=\"preload\" as=\"style\" href=\"b.css\">" as *u8 111 var an: i64=0; while a[an]!=(0 as u8) { an=an+1 } 112 if perf_blocking_css(a,an)!=1 { f=f+1 } 113 // blocking JS: one plain src + one deferred + one inline -> exactly 1 114 let b: *u8 = "<script src=\"x.js\"></script><script src=\"y.js\" defer></script><script>1</script>" as *u8 115 var bn: i64=0; while b[bn]!=(0 as u8) { bn=bn+1 } 116 if perf_blocking_js(b,bn)!=1 { f=f+1 } 117 // unsized img: one bare + one sized -> exactly 1 118 let c: *u8 = "<img src=\"a.png\"><img src=\"b.png\" width=\"10\" height=\"10\">" as *u8 119 var cn: i64=0; while c[cn]!=(0 as u8) { cn=cn+1 } 120 if perf_unsized_img(c,cn)!=1 { f=f+1 } 121 // NEG-CONTROL: inline-css, no ext, no img -> 0 issues (perf-optimal by construction) 122 let d: *u8 = "<style>body{color:#000}</style><p>hi</p>" as *u8 123 var dn: i64=0; while d[dn]!=(0 as u8) { dn=dn+1 } 124 if perf_audit(d,dn,0)!=0 { f=f+1 } 125 return f 126} 127 128func perf_slurp(path: *u8, buf: *u8, cap: i64) -> i64 { 129 let fd: i64 = sys_openat_rd(path) 130 if fd<0 { return 0 } 131 var total: i64=0 132 var nrd: i64=sys_read(fd, buf, cap) 133 while nrd>0 { total=total+nrd; if total>=cap { nrd=0 } else { nrd=sys_read(fd, ((buf as i64)+total) as *u8, cap-total) } } 134 sys_close(fd) 135 return total 136} 137 138func main(argc: i64, argv: *i64) -> i64 { 139 if argc>=2 { 140 let a1: *u8 = argv[1] as *u8 141 if a1[0]==(45 as u8) { 142 uiq_w("=== nx_uiq_perf --kat (static Core-Web-Vitals predictor) ===\n" as *u8) 143 let f: i64 = uiq_perf_selftest() 144 uiq_w("checks failed=" as *u8); uiq_pn(f); uiq_w(" (blocking-css + blocking-js + unsized-img + neg-control)\n" as *u8) 145 if f==0 { uiq_w("VERDICT=GREEN\n" as *u8); sys_exit(0); return 0 } 146 uiq_w("VERDICT=RED\n" as *u8); sys_exit(1); return 1 147 } 148 let cap: i64 = K_MAGIC_2097152 149 let buf: *u8 = sys_mmap(cap) 150 let n: i64 = perf_slurp(a1, buf, cap) 151 if n<=0 { uiq_w("{\"error\":\"cannot read page\"}\n" as *u8); sys_exit(2); return 2 } 152 perf_audit(buf, n, 1) 153 sys_exit(0); return 0 154 } 155 uiq_w("usage: nx_uiq_perf --kat | <html-file-path>\n" as *u8) 156 sys_exit(2); return 2 157}