ostia 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -176,6 +176,52 @@ rest sharing a process). `--jobs` then pools across those per-task processes the
176
176
  it pools across per-file ones, so pair a higher `--jobs` with `--isolate` deliberately -
177
177
  overhead now scales with task count, not file count.
178
178
 
179
+ `--gc` calls `Bun.gc(true)` between trials (default: off, which hides allocation cost as
180
+ Bun/V8 batch calls together and amortize it away). `task(name, fn, { gc })` /
181
+ `group(name, fn, { gc })` override the suite-wide default per task or group, the same
182
+ override pattern as `isolate` - useful when a few allocation-heavy tasks need GC settled
183
+ between trials but the rest of the suite doesn't.
184
+
185
+ `--preload PATH` (repeatable) imports a script before each suite file loads, in the same
186
+ subprocess - the same shape as Bun's own `--preload` / `bunfig.toml`'s `preload` array. Use
187
+ it to install globals a suite needs at import time (jsdom's `document`/`window`) or register
188
+ a `Bun.plugin()` file-loader (e.g. compiling `.svelte`/`.vue` SFCs) before the suite's own
189
+ top-level code runs. Multiple `--preload` scripts run in the order given, so state one
190
+ installs (a plugin registration, a global) is visible to the next and to the suite itself.
191
+ ostia ships none of this itself - just the hook point (for a full jsdom/happy-dom global
192
+ setup or a `Bun.plugin()` component-compile hook, see
193
+ [docs/preload-recipes.md](docs/preload-recipes.md)):
194
+
195
+ ```ts
196
+ // bench/jsdom-setup.ts
197
+ import { JSDOM } from "jsdom"
198
+ const dom = new JSDOM("<!doctype html>")
199
+ Object.assign(globalThis, { document: dom.window.document, window: dom.window })
200
+ ```
201
+
202
+ ```sh
203
+ ostia bench --preload ./bench/jsdom-setup.ts bench/*.dom.bench.ts
204
+ ```
205
+
206
+ `--bun-flags FLAGS` (repeatable, space-separated flags within one value are all appended)
207
+ passes extra flags through to the `bun` invocation that spawns each suite file - the fix for
208
+ packages whose `package.json` `exports` map branches on a resolution condition Bun doesn't
209
+ set by default. Svelte 5's `exports` map, for example, is `{ "browser": "./src/index-client.js",
210
+ "default": "./src/index-server.js" }`: without `--conditions browser`, Bun resolves `default`
211
+ (the server-rendering build), and mounting a component via `@testing-library/svelte` throws
212
+ `lifecycle_function_unavailable` since `mount()` isn't available server-side. The same applies
213
+ to Vue and other dual-target frameworks:
214
+
215
+ ```sh
216
+ ostia bench --bun-flags="--conditions=browser" bench/*.dom.bench.ts
217
+ ```
218
+
219
+ Unlike `BUN_OPTIONS` (an env var Bun's CLI reads to prepend flags, which only reaches the
220
+ spawned suite process today because ostia's `Bun.spawn()` happens to inherit `process.env`),
221
+ `--bun-flags` is a declared, documented integration point that doesn't depend on the parent
222
+ shell's environment.
223
+
224
+
179
225
  ```
180
226
  Command Mean [ms] Min…Max [ms] Relative
181
227
  --------------------------------------------------------------------------------------
@@ -370,6 +416,7 @@ import {
370
416
  bench,
371
417
  group,
372
418
  task,
419
+ range,
373
420
  compareDocuments,
374
421
  renderers,
375
422
  saveDocument,
@@ -434,6 +481,19 @@ group("parse", () => {
434
481
  That is the whole registration surface: `group()` and `task()`. Presentation lives in
435
482
  the renderers (`--format`), not in the suite file.
436
483
 
484
+ All module-scope code in a suite file runs up front, before any task is sampled -
485
+ there's no hook that runs a task's own setup immediately before its sampling and
486
+ its teardown immediately after, the way mitata's generator-based `bench()` drove
487
+ one case to completion before starting the next. If a suite builds more than one
488
+ instance of something stateful (a mounted UI component, an open connection, a
489
+ server) at module scope, every instance already exists by the time any task
490
+ samples - so a query has to be scoped to the instance it belongs to, not written
491
+ against a global/ambient lookup that assumes it's the only one alive. Porting a
492
+ mitata suite that opens a component's menu and queries `getByRole(...)`
493
+ unscoped, for example, breaks once a second instance of that component exists
494
+ in the document; scope the query with something like `within(instance.container)`
495
+ instead.
496
+
437
497
  Both take an optional `description` that flows into the document
438
498
  (`Workload.description` / `Workload.groupDescription`) and into `--format minimal`, so
439
499
  what a number measures and why travels with the data instead of living only in a
@@ -463,6 +523,29 @@ group("parse", () => {
463
523
  })
464
524
  ```
465
525
 
526
+ ### `range(start, end, multiplier?)` → `number[]`
527
+
528
+ Geometric sweep points for parameterizing `task()` over a size dimension - mitata's
529
+ `.range(name, start, end, multiplier)` point generation (default multiplier `8`, always
530
+ ending on `end` even if the last step overshot it), without the name templating: build
531
+ the task name yourself in the loop.
532
+
533
+ ```ts
534
+ import { group, task, range } from "ostia"
535
+
536
+ group("parse", () => {
537
+ for (const size of range(100, 10_000)) {
538
+ const input = buildInput(size) // setup, runs once per point, unmeasured
539
+ task(`${size} items`, () => parse(input))
540
+ }
541
+ })
542
+ ```
543
+
544
+ ```ts
545
+ range(100, 10_000) // -> [100, 800, 6400, 10000]
546
+ range(100, 100_000) // -> [100, 800, 6400, 51200, 100000]
547
+ ```
548
+
466
549
  ```ts
467
550
  // demo.ts
468
551
  import { bench } from "ostia"
@@ -0,0 +1,21 @@
1
+ // @bun
2
+ import{h,e,r,u,T,i,b,I,s,x,t,l,p}from"./chunk-zrck2q0b.js";function Le(o){return o.startsWith("file://")?o.slice(7):o}function ae(o,U,c){let R=o.nodes,m=R.length,C=new Map,N=[],v=new Map,D=new Int32Array(m);for(let A=0;A<m;A++){let F=R[A],M=F.callFrame,H=Le(M.url),Y=C.get(M.functionName);if(Y===void 0)Y=new Map,C.set(M.functionName,Y);let q=Y.get(H);if(q===void 0)q=N.length,Y.set(H,q),N.push({key:e("fr",M.functionName,H),name:M.functionName,url:H||void 0,line:M.lineNumber>=0?M.lineNumber:void 0,col:M.columnNumber>=0?M.columnNumber:void 0});D[A]=q,v.set(F.id,A)}let W=Array(m);for(let A=0;A<m;A++){let F=R[A];W[A]={id:F.id,frameIx:D[v.get(F.id)],children:F.children??[]}}let O=new Float64Array(m),E=new Float64Array(m),{samples:j,timeDeltas:z}=o;for(let A=0;A<j.length;A++){let F=v.get(j[A]);if(F===void 0)continue;O[F]+=z[A]??0,E[F]+=1}let V=new Int32Array(m).fill(-1);for(let A=0;A<m;A++){let F=R[A].children;if(!F)continue;for(let M of F){let H=v.get(M);if(H!==void 0)V[H]=A}}let _=[],J=[];for(let A=m-1;A>=0;A--)if(V[A]===-1)J.push(A);while(J.length>0){let A=J.pop();_.push(A);let F=R[A].children;if(!F)continue;for(let M of F){let H=v.get(M);if(H!==void 0&&V[H]===A)J.push(H)}}let K=new Float64Array(m);for(let A=_.length-1;A>=0;A--){let F=_[A];K[F]+=O[F];let M=V[F];if(M>=0)K[M]+=K[F]}let G=Array(N.length),L=[];for(let A=0;A<m;A++){let F=W[A].frameIx,M=G[F];if(M)M.selfUs+=O[A],M.totalUs+=K[A],M.samples+=E[A];else{let H={frameIx:F,selfUs:O[A],totalUs:K[A],samples:E[A]};G[F]=H,L.push(H)}}return{origin:U,samplingIntervalUs:c,frames:N,nodes:W,totals:L.sort((A,F)=>F.selfUs-A.selfUs),samples:{nodeIds:o.samples,timeDeltasUs:o.timeDeltas}}}function He(o,U,c,R){let m=["--cpu-prof","--cpu-prof-dir",U,"--cpu-prof-name",c,"--cpu-prof-interval",String(R)],C=o[0];if(C==="bun"||C?.endsWith("/bun"))return[C,...m,...o.slice(1)];return o}async function ge(o){let U=`${o.artifactDir}/${o.fileName}`,c=o.argv[0],R=c==="bun"||c?.endsWith("/bun"),m=He(o.argv,o.artifactDir,o.fileName,o.intervalUs),C=R?o.env:{...process.env,...o.env,BUN_OPTIONS:`--cpu-prof --cpu-prof-dir ${o.artifactDir} --cpu-prof-name ${o.fileName} --cpu-prof-interval ${o.intervalUs}`},N=Bun.nanoseconds(),D=await Bun.spawn(m,{cwd:o.cwd,env:C,stdout:"ignore",stderr:"ignore",stdin:"ignore"}).exited,W=Bun.nanoseconds()-N,O=Bun.file(U);if(!await O.exists())return{diagnosticWallNs:W,exitCode:D,warnings:[{code:"artifact-missing",message:`Expected a .cpuprofile at ${U} after exit ${D}, found nothing. The workload's argv[0] must be a \`bun\` binary for CPU capture.`,data:{artifactPath:U,argv:o.argv}}]};let E=await O.json(),j=ae(E,"cpu-prof",o.intervalUs),z=E.samples.length===0?[{code:"empty-profile",message:"CPU capture produced zero samples."}]:[];return{diagnosticWallNs:W,exitCode:D,artifactPath:U,cpu:j,warnings:z}}function he(o,U="heap-prof"){let{node_fields:c,node_types:R}=o.snapshot.meta,m=c.indexOf("type"),C=c.indexOf("self_size"),N=c.length,v=R[0];if(m===-1||C===-1||!Array.isArray(v))return{origin:U,typeCounts:[],objectCount:o.snapshot.node_count};let D=v.length,W=Array(D),O=new Map,E=[],j=0,z=o.nodes,V=z.length;for(let L=0;L<V;L+=N){let A=z[L+m],F=z[L+C]??0;j+=F;let M;if(A>=0&&A<D){if(M=W[A],M===void 0)M={type:v[A],count:0,bytes:0},W[A]=M,E.push(M)}else{let H=`unknown(${A})`;if(M=O.get(H),M===void 0)M={type:H,count:0,bytes:0},O.set(H,M),E.push(M)}M.count++,M.bytes+=F}let _=E.sort((L,A)=>A.count-L.count),J=_.slice(0,20),K=_.slice(20),G=J.map(({type:L,count:A,bytes:F})=>({type:L,count:A,retainedBytes:F}));if(K.length>0){let L=0,A=0;for(let F of K)L+=F.count,A+=F.bytes;G.push({type:"other",count:L,retainedBytes:A})}return{origin:U,heapSizeBytes:j,objectCount:o.snapshot.node_count,typeCounts:G}}function Je(o,U,c){let R=["--heap-prof","--heap-prof-dir",U,"--heap-prof-name",c],m=o[0];if(m==="bun"||m?.endsWith("/bun"))return[m,...R,...o.slice(1)];return o}async function be(o){let U=`${o.artifactDir}/${o.fileName}`,c=o.argv[0],R=c==="bun"||c?.endsWith("/bun"),m=Je(o.argv,o.artifactDir,o.fileName),C=R?o.env:{...process.env,...o.env,BUN_OPTIONS:`--heap-prof --heap-prof-dir ${o.artifactDir} --heap-prof-name ${o.fileName}`},N=Bun.nanoseconds(),D=await Bun.spawn(m,{cwd:o.cwd,env:C,stdout:"ignore",stderr:"ignore",stdin:"ignore"}).exited,W=Bun.nanoseconds()-N,O=Bun.file(U);if(!await O.exists())return{diagnosticWallNs:W,exitCode:D,warnings:[{code:"artifact-missing",message:`Expected a heap snapshot at ${U} after exit ${D}, found nothing. The workload's argv[0] must be a \`bun\` binary for heap capture.`,data:{artifactPath:U,argv:o.argv}}]};let E=await O.json(),j=he(E,"heap-prof");return{diagnosticWallNs:W,exitCode:D,artifactPath:U,heap:j,warnings:[]}}import{Session as ze}from"inspector/promises";var Ve=1000;async function ye(o,U={}){let c=U.intervalUs??Ve,R=new ze;R.connect();let m=Bun.nanoseconds();try{await R.post("Profiler.enable"),await R.post("Profiler.setSamplingInterval",{interval:c}),await R.post("Profiler.start");let C=await o(),{profile:N}=await R.post("Profiler.stop"),v=Bun.nanoseconds()-m,D=ae(N,"inspector",c);return{result:C,cpu:D,diagnosticWallNs:v}}finally{R.disconnect()}}import{profile as Ge}from"bun:jsc";var Ke=new Map([["LLInt","llint"],["Baseline","baseline"],["DFG","dfg"],["FTL","ftl"]]),we=4294967295;function xe(o,U){let c=U??o.interval*1e6,R=new Map,m=[];function C(M,H,Y,q){let Q=R.get(M);if(Q===void 0)Q=new Map,R.set(M,Q);let X=H??"",ee=Q.get(X);if(ee===void 0)ee=m.length,Q.set(X,ee),m.push({key:e("fr",M,X),name:M,url:H,line:Y,col:q});return ee}function N(M){let H=M.line===we,Y=H?void 0:M.line-1,q=H||M.column===we?void 0:M.column-1;return C(M.name,M.sourceURL,Y,q)}let v=C("(root)",void 0,void 0,void 0),D=1,W={id:0,frameIx:v,children:new Map,selfUs:0,samples:0,totalUs:0},O=new Map([[0,W]]),E={llint:0,baseline:0,dfg:0,ftl:0},j=new Map,z=[],V=[];for(let M of o.traces){let H=M.frames,Y=W;for(let X=H.length-1;X>=0;X--){let ee=N(H[X]),re=Y.children.get(ee);if(!re)re={id:D++,frameIx:ee,children:new Map,selfUs:0,samples:0,totalUs:0},Y.children.set(ee,re),O.set(re.id,re);Y=re}Y.selfUs+=c,Y.samples+=1,z.push(Y.id),V.push(c);let q=H[0],Q=q&&Ke.get(q.category);if(Q){E[Q]++;let X=j.get(Q)??new Map;X.set(Y.frameIx,(X.get(Y.frameIx)??0)+1),j.set(Q,X)}}function _(M){let H=M.selfUs;for(let Y of M.children.values())H+=_(Y);return M.totalUs=H,H}_(W);let J=new Map;function K(M){let H=J.get(M.frameIx);if(H)H.selfUs+=M.selfUs,H.totalUs+=M.totalUs,H.samples+=M.samples;else J.set(M.frameIx,{frameIx:M.frameIx,selfUs:M.selfUs,totalUs:M.totalUs,samples:M.samples});for(let Y of M.children.values())K(Y)}K(W);let G=[...O.values()].map((M)=>({id:M.id,frameIx:M.frameIx,children:[...M.children.values()].map((H)=>H.id)})),L={origin:"jsc-profile",samplingIntervalUs:c,frames:m,nodes:G,totals:[...J.values()].sort((M,H)=>H.selfUs-M.selfUs),samples:{nodeIds:z,timeDeltasUs:V}},A=[...j.entries()].flatMap(([M,H])=>[...H.entries()].sort((Y,q)=>q[1]-Y[1]).slice(0,3).map(([Y,q])=>({tier:M,frameKey:m[Y].key,samples:q})));return{cpu:L,jit:{origin:"jsc-profile",tiers:E,topFramesByTier:A}}}var Ye=1000;async function Re(o,U={}){let c=U.intervalUs??Ye,R,m=Bun.nanoseconds(),C=await Ge(async()=>(R=await o(),R),c),N=Bun.nanoseconds()-m,{cpu:v,jit:D}=xe(C.stackTraces,c);return{result:R,cpu:v,jit:D,diagnosticWallNs:N}}async function le(o){let U=Bun.nanoseconds(),c=Bun.spawn(o.argv,{cwd:o.cwd,env:o.env,stdout:"ignore",stderr:"ignore",stdin:"ignore"}),R=await c.exited,m=Bun.nanoseconds(),C=c.resourceUsage?.();return{wallNs:m-U,exitCode:R,userNs:C?Number(C.cpuTime.user)*1000:void 0,systemNs:C?Number(C.cpuTime.system)*1000:void 0,maxRssBytes:C?.maxRSS}}function Pe(o){return o.trim().split(/\s+/).filter(Boolean)}var qe=10,Qe=3000000000,Xe=3;async function g(o){let U=o.warmup??Xe;for(let O=0;O<U;O++)await le(o);let c=[],R=o.runs??o.minRuns??qe,m=o.runs!==void 0?0:o.minTotalNs??Qe,C=0,N=0;while(N<R||C<m){let O=await le(o);if(c.push({i:N,wallNs:O.wallNs,exitCode:O.exitCode,userNs:O.userNs,systemNs:O.systemNs,maxRssBytes:O.maxRssBytes}),C+=O.wallNs,N++,o.runs!==void 0&&N>=o.runs)break}let v=c.map((O)=>O.wallNs),D=l(v),W=p(D,c.map((O)=>O.exitCode));return{trials:c,timing:D,warnings:W}}var Te=new URL("./runner.ts",import.meta.url).pathname,Ze="node_modules/.cache/ostia";function w(){return Math.max(1,navigator.hardwareConcurrency||1)}async function en(o,U){let c=new Set;for(let R of o){let m=new Bun.Glob(R);for await(let C of m.scan({cwd:U,absolute:!1}))c.add(C)}return[...c].sort()}function nn(o){if(o===void 0)return;return o==="auto"?w():o}async function P(o,U,c=process.cwd()){return{suites:o.suites.length>0?o.suites:U?.suites?await en(U.suites,c):[],timeBudgetMs:o.timeBudgetMs??U?.timeBudgetMs,minSamples:o.minSamples??U?.minSamples,jobs:o.jobs??nn(U?.jobs),gc:o.gc||(U?.gc??!1),filter:o.filter??U?.filter,isolate:o.isolate||(U?.isolate??!1),preload:o.preload.length>0?o.preload:U?.preload??[],bunFlags:o.bunFlags,outDir:o.outDir??U?.outDir,cwd:c}}async function d(o){let c=`${o.outDir??Ze}/bench-tmp`,R=o.cwd??process.cwd(),m=Math.max(1,Math.floor(o.jobs??1)),C={timeBudgetMs:o.timeBudgetMs,minSamples:o.minSamples,gc:o.gc},N=o.suites.map((O)=>O.startsWith("/")?O:`${R}/${O}`),v=(o.preload??[]).map((O)=>O.startsWith("/")?O:`${R}/${O}`),D=o.bunFlags??[],W=async(O,E)=>{let j=new Set,z=0,V,_=async()=>{while(V===void 0&&z<O.length){let J=z++;try{let K=Bun.spawn(O[J],{cwd:R,stdout:"inherit",stderr:"inherit",stdin:"ignore"});j.add(K);let G=await K.exited;if(j.delete(K),G!==0)throw Error(`Bench suite failed: ${E(J)} (runner exited ${G})`)}catch(K){V??=K instanceof Error?K:Error(String(K));for(let G of j)G.kill()}}};if(await Promise.all(Array.from({length:Math.min(m,O.length)},_)),V)throw V};try{let O=N.map((F)=>`${c}/${e("bench-plan",F)}.json`),E=N.map((F)=>`${c}/${e("bench-primary",F)}.json`),j=N.map((F,M)=>["bun",...D,Te,F,E[M],JSON.stringify({...C,filter:o.filter,isolate:o.isolate,preload:v,planPath:O[M]})]);await W(j,(F)=>o.suites[F]);let z=await Promise.all(O.map(async(F)=>{let{tasks:M}=await Bun.file(F).json();return M})),V=await Promise.all(E.map(t)),_=[];for(let F=0;F<z.length;F++)for(let M of z[F])if(M.isolate)_.push({suiteIndex:F,taskIds:[M.id]});let J=_.map((F,M)=>`${c}/${e("bench-item",N[F.suiteIndex],M)}.json`),K=_.map((F,M)=>["bun",...D,Te,N[F.suiteIndex],J[M],JSON.stringify({...C,taskIds:F.taskIds,preload:v,markIsolated:!0})]);await W(K,(F)=>o.suites[_[F].suiteIndex]);let G=await Promise.all(J.map(t)),L=[],A=[];for(let F=0;F<z.length;F++){let M=V[F],H=0,Y=new Map;_.forEach((q,Q)=>{if(q.suiteIndex===F)Y.set(q.taskIds[0],G[Q])});for(let q of z[F])if(q.isolate){let Q=Y.get(q.id);L.push(Q.workloads[0]),A.push(Q.runs[0])}else L.push(M.workloads[H]),A.push(M.runs[H]),H++}return r(L,A)}finally{await Bun.spawn(["rm","-rf",c]).exited}}function S(o,U,c=8){if(c<=1)throw RangeError(`range: multiplier must be > 1, got ${c}`);if(o<=0)throw RangeError(`range: start must be > 0, got ${o}`);let R=[];for(let m=o;m<=U;m*=c)R.push(m);if(!R.includes(U))R.push(U);return R}var a={timingPct:5,frameSelfPct:10,heapTypePct:10,minFrameSelfUs:1000};function ce(o,U){if(o===0)return U===0?0:1/0;return(U-o)/o*100}function se(o,U,c){return o.runs.find((R)=>R.workloadId===U&&R.phase===c)}function f(o,U,c=a){let R=new Set(U.workloads.map((C)=>C.id)),m=[];for(let C of o.workloads){if(!R.has(C.id))continue;let N=y(o,U,C.id,c);if(N)m.push(N)}return m}function y(o,U,c,R=a){let m=se(o,c,"timing"),C=se(U,c,"timing"),N=se(o,c,"cpu"),v=se(U,c,"cpu"),D=se(o,c,"heap"),W=se(U,c,"heap"),O=m?.id??N?.id??D?.id,E=C?.id??v?.id??W?.id;if(!O||!E)return;let j=!1,z;if(m?.timing&&C?.timing){let J=ce(m.timing.median,C.timing.median),K=ce(m.timing.mean,C.timing.mean),G=J>R.timingPct?"regressed":J<-R.timingPct?"improved":"unchanged";if(G==="regressed")j=!0;z={medianDeltaPct:J,meanDeltaPct:K,verdict:G}}let V;if(N?.cpu&&v?.cpu){let J=new Map(N.cpu.totals.map((F)=>[N.cpu.frames[F.frameIx].key,F])),K=new Map(v.cpu.totals.map((F)=>[v.cpu.frames[F.frameIx].key,F])),G=new Map(N.cpu.frames.map((F)=>[F.key,F.name])),L=new Map(v.cpu.frames.map((F)=>[F.key,F.name]));V=[...new Set([...J.keys(),...K.keys()])].map((F)=>{let M=J.get(F)?.selfUs??0,H=K.get(F)?.selfUs??0;return{frameKey:F,name:L.get(F)??G.get(F)??F,baseSelfUs:M,candSelfUs:H,deltaPct:ce(M,H)}}).sort((F,M)=>Math.abs(M.deltaPct)-Math.abs(F.deltaPct));for(let F of V)if((F.baseSelfUs>=R.minFrameSelfUs||F.candSelfUs>=R.minFrameSelfUs)&&F.deltaPct>R.frameSelfPct)j=!0}let _;if(D?.heap&&W?.heap){let J=new Map(D.heap.typeCounts.map((L)=>[L.type,L])),K=new Map(W.heap.typeCounts.map((L)=>[L.type,L]));_=[...new Set([...J.keys(),...K.keys()])].map((L)=>{let A=J.get(L),F=K.get(L);return{type:L,baseCount:A?.count??0,candCount:F?.count??0,baseBytes:A?.retainedBytes,candBytes:F?.retainedBytes,deltaPct:ce(A?.count??0,F?.count??0)}}).sort((L,A)=>Math.abs(A.deltaPct)-Math.abs(L.deltaPct));for(let L of _)if(L.deltaPct>R.heapTypePct)j=!0}return{id:e("cmp",O,E),baselineRunId:O,candidateRunId:E,timing:z,frames:V,heapTypes:_,thresholds:R,verdict:j?"fail":"pass"}}function ne(o,U){if(U){let c=o.runs.find((R)=>R.id===U);return c?.cpu?[c]:[]}return o.runs.filter((c)=>c.phase==="cpu"&&c.cpu)}function oe(o){let U=o.nodes,c=U.length,R=tn(o),m=new Int32Array(c).fill(-1);for(let D=0;D<c;D++)for(let W of U[D].children){let O=R(W);if(O!==-1)m[O]=D}let C=[];for(let D=0;D<c;D++)if(m[D]===-1)C.push(D);let N=[],v=[];for(let D=C.length-1;D>=0;D--)v.push(C[D]);while(v.length>0){let D=v.pop();N.push(D);for(let W of U[D].children){let O=R(W);if(O!==-1&&m[O]===D)v.push(O)}}return{count:c,indexOf:R,parentIx:m,roots:C,order:N}}function tn(o){let U=o.nodes,c=U.length,R=1/0,m=-1/0,C=!0;for(let v=0;v<c;v++){let D=U[v].id;if(!Number.isInteger(D)){C=!1;break}if(D<R)R=D;if(D>m)m=D}if(C&&c>0&&m-R<c*4+64){let v=m-R+1,D=new Int32Array(v).fill(-1);for(let W=0;W<c;W++)D[U[W].id-R]=W;return(W)=>{let O=W-R;return O>=0&&O<v?D[O]:-1}}let N=new Map;for(let v=0;v<c;v++)N.set(U[v].id,v);return(v)=>N.get(v)??-1}function $e(o,U){let{count:c,indexOf:R,parentIx:m,order:C}=U,N=new Float64Array(c),v=new Float64Array(c),D=o.samples?.nodeIds??[],W=o.samples?.timeDeltasUs??[];for(let E=0;E<D.length;E++){let j=R(D[E]);if(j===-1)continue;N[j]+=W[E]??0,v[j]+=1}let O=new Float64Array(c);for(let E=C.length-1;E>=0;E--){let j=C[E];O[j]+=N[j];let z=m[j];if(z>=0)O[z]+=O[j]}return{selfUs:N,totalUs:O,samples:v}}var ke={name:"collapsed",async render(o,U={}){return{files:ne(o,U.runId).map((m)=>{let C=m.cpu,{nodes:N,frames:v}=C,D=oe(C),W=Array(D.count);for(let V of D.order){let _=v[N[V].frameIx].name||"(anonymous)",J=D.parentIx[V];W[V]=J===-1?_:`${W[J]};${_}`}let O=new Float64Array(D.count),E=[],j=C.samples?.nodeIds??[];for(let V=0;V<j.length;V++){let _=D.indexOf(j[V]);if(_===-1)continue;if(O[_]++===0)E.push(_)}let z=Array(E.length);for(let V=0;V<E.length;V++){let _=E[V];z[V]=`${W[_]} ${O[_]}`}return{path:`${m.id}.collapsed.txt`,content:z.join(`
3
+ `)+(z.length>0?`
4
+ `:"")}})}}};var Ie={name:"cpuprofile",async render(o,U={}){let c=ne(o,U.runId),R=[],m=[];for(let C of c){if(C.cpu?.origin!=="cpu-prof"&&C.cpu?.origin!=="inspector"){m.push(`${C.id} (origin ${C.cpu?.origin??"unknown"} has no .cpuprofile artifact to pass through)`);continue}let N=C.artifacts.find((D)=>D.kind==="cpuprofile");if(!N){m.push(`${C.id} (no cpuprofile artifact recorded on this run)`);continue}let v=Bun.file(N.path);if(!await v.exists()){m.push(`${C.id} (artifact missing on disk: ${N.path})`);continue}R.push({path:`${C.id}.cpuprofile`,content:await v.text()})}if(R.length===0&&m.length>0)return{text:`No .cpuprofile artifacts available:
5
+ ${m.map((C)=>` - ${C}`).join(`
6
+ `)}
7
+ `};return{files:R}}};var ve={name:"json",async render(o){return{text:x(o)}}};var Ce={name:"jsonl",async render(o){let{runs:U,...c}=o;return{text:`${[h(c),...U.map((m)=>h(m))].join(`
8
+ `)}
9
+ `}}};function te(o){return(o/1e6).toFixed(3)}function ue(o){return o?.label??o?.command?.join(" ")??o?.entry?.task??o?.id??"unknown"}var Ne=10,Ue=10,De={name:"markdown",async render(o){let U=new Map(o.workloads.map((m)=>[m.id,m])),c=[];c.push("# Profile Report",""),c.push(`Bun ${o.bunVersion} \xB7 ostia ${o.toolVersion} \xB7 ${o.platform.os}/${o.platform.arch} \xB7 ${o.createdAt}`,"");let R=o.runs.filter((m)=>m.phase==="timing"&&m.timing!==void 0);if(R.length>0){c.push("## Timing",""),c.push("| Command | Mean \xB1 SD (ms) | Min\u2026Max (ms) | Median (ms) |","|---|---|---|---|");for(let C of R){let N=ue(U.get(C.workloadId)),v=C.timing;c.push(`| ${N} | ${te(v.mean)} \xB1 ${te(v.stddev)} | ${te(v.min)}\u2026${te(v.max)} | ${te(v.median)} |`)}c.push("");let m=R.filter((C)=>C.warnings.length>0);if(m.length>0){c.push("### Warnings","");for(let C of m){let N=ue(U.get(C.workloadId));for(let v of C.warnings)c.push(`- **${N}**: ${v.message} (\`${v.code}\`)`)}c.push("")}}for(let m of o.runs){if(m.phase!=="cpu"&&m.phase!=="heap")continue;let C=ue(U.get(m.workloadId));if(m.phase==="cpu"){if(c.push(`## CPU capture - ${C}`,""),c.push(`instrumented, diagnostic wall ${te(m.diagnosticWallNs??0)}ms`,""),m.cpu){c.push(`origin: \`${m.cpu.origin}\`, interval: ${m.cpu.samplingIntervalUs}\xB5s`,""),c.push("| Self % | Self (ms) | Total (ms) | Frame |","|---|---|---|---|");let N=m.cpu.totals.reduce((v,D)=>v+D.selfUs,0)||1;for(let v of m.cpu.totals.slice(0,Ne)){let D=m.cpu.frames[v.frameIx],W=(v.selfUs/N*100).toFixed(1);c.push(`| ${W}% | ${(v.selfUs/1000).toFixed(2)} | ${(v.totalUs/1000).toFixed(2)} | ${D?.name||"(anonymous)"} |`)}if(c.push(""),m.jit){let v=m.jit.tiers;c.push(`JIT tiers: LLInt ${v.llint} \xB7 Baseline ${v.baseline} \xB7 DFG ${v.dfg} \xB7 FTL ${v.ftl}`,"")}}}else if(c.push(`## Heap snapshot - ${C}`,""),c.push(`instrumented, diagnostic wall ${te(m.diagnosticWallNs??0)}ms`,""),m.heap){c.push(`${m.heap.objectCount??"?"} objects, ${((m.heap.heapSizeBytes??0)/1e6).toFixed(2)}MB`,""),c.push("| Count | Type |","|---|---|");for(let N of m.heap.typeCounts.slice(0,Ue))c.push(`| ${N.count} | ${N.type} |`);c.push("")}for(let N of m.artifacts)c.push(`- artifact: \`${N.path}\``);for(let N of m.warnings)c.push(`- ! ${N.message} (\`${N.code}\`)`);if(m.artifacts.length>0||m.warnings.length>0)c.push("")}if(o.comparisons&&o.comparisons.length>0){c.push("## Comparisons","");for(let m of o.comparisons){let C=o.runs.find((v)=>v.id===m.candidateRunId),N=ue(C?U.get(C.workloadId):void 0);if(c.push(`### ${m.verdict==="pass"?"\u2713":"\u2717"} ${N}`,""),m.timing){let v=m.timing.medianDeltaPct>0?"+":"";c.push(`- timing: ${v}${m.timing.medianDeltaPct.toFixed(1)}% median (**${m.timing.verdict}**)`)}for(let v of m.frames?.slice(0,Ne)??[]){if(Math.abs(v.deltaPct)<0.5)continue;let D=v.deltaPct>0?"+":"";c.push(`- frame \`${v.name}\`: ${D}${v.deltaPct.toFixed(1)}% self-time (${(v.baseSelfUs/1000).toFixed(2)}ms \u2192 ${(v.candSelfUs/1000).toFixed(2)}ms)`)}for(let v of m.heapTypes?.slice(0,Ue)??[]){if(Math.abs(v.deltaPct)<0.5)continue;let D=v.deltaPct>0?"+":"";c.push(`- heap \`${v.type}\`: ${D}${v.deltaPct.toFixed(1)}% count (${v.baseCount} \u2192 ${v.candCount})`)}c.push("")}}return{text:c.join(`
10
+ `)}}};var rn=15;function me(o){return`n${o}`}function sn(o,U,c){return`${(o||"(anonymous)").replace(/"/g,"'")} (self ${(U/1000).toFixed(2)}ms, total ${(c/1000).toFixed(2)}ms)`}function on(o,U,c,R){let m=[];if(R<=0)return m;for(let C=0;C<U;C++){if(C===c)continue;let N=o[C];if(m.length===R&&N<=o[m[R-1]])continue;let v=m.length;while(v>0&&o[m[v-1]]<N)v--;if(m.splice(v,0,C),m.length>R)m.pop()}return m}var Fe={name:"mermaid",async render(o,U={}){let c=U.topN??rn;return{files:ne(o,U.runId).map((C)=>{let N=C.cpu,{nodes:v,frames:D}=N,W=oe(N),{selfUs:O,totalUs:E}=$e(N,W),{parentIx:j}=W,z=W.roots[0]??-1,V=on(O,W.count,z,c),_=new Set(z!==-1?[z]:[]),J=[];for(let G of V){J.length=0;for(let L=G;L!==-1;L=j[L])J.push(L);for(let L=J.length-1;L>=0;L--)_.add(J[L])}let K=["graph TD"];for(let G of _){let L=v[G].id;K.push(` ${me(L)}["${sn(D[v[G].frameIx].name,O[G],E[G])}"]`)}for(let G of _){let L=j[G];if(L!==-1&&_.has(L))K.push(` ${me(v[L].id)} --> ${me(v[G].id)}`)}return{path:`${C.id}.mermaid.md`,content:`${K.join(`
11
+ `)}
12
+ `}})}}};function Me(o){if(!o?.entry)return;if(o.entry.group!==void 0)return o.entry.group;let U=o.entry.task,c=U.lastIndexOf("/");return c===-1?void 0:U.slice(0,c)}function pe(o){let U=Math.min(...o.map((m)=>m.run.timing.median)),c=new Map;for(let m of o){let C=Me(m.workload);if(C===void 0)continue;let N=c.get(C);if(N)N.push(m);else c.set(C,[m])}let R=new Map;for(let m of o){let C=Me(m.workload);if(C===void 0){R.set(m,U);continue}let N=c.get(C)??[m],v=N.find((D)=>D.workload?.baseline);R.set(m,v?v.run.timing.median:Math.min(...N.map((D)=>D.run.timing.median)))}return R}function Z(o){return Number.isFinite(o)?Number(o.toPrecision(6)):o}function an(o,U){return o?.entry?.task??o?.label??o?.command?.join(" ")??U.workloadId}function cn(o){let U=new Map(o.workloads.map((C)=>[C.id,C])),c=o.runs.filter((C)=>C.phase==="timing"&&C.timing!==void 0).map((C)=>({run:C,workload:U.get(C.workloadId)})),R=c.length>1?pe(c):void 0,m=new Map((o.comparisons??[]).map((C)=>[C.candidateRunId,C]));return c.map((C)=>{let{run:N,workload:v}=C,D=N.timing,W={task:an(v,N),unit:"ns",samples:D.samples.length,mean:Z(D.mean),median:Z(D.median),stddev:Z(D.stddev),stddevPct:Z(D.mean===0?0:D.stddev/D.mean*100),min:Z(D.min),max:Z(D.max),warnings:N.warnings.map((E)=>E.data?{code:E.code,data:E.data}:{code:E.code})};if(v?.entry?.group!==void 0)W.group=v.entry.group;if(v?.description!==void 0)W.description=v.description;if(v?.groupDescription!==void 0)W.groupDescription=v.groupDescription;if(R)W.relative=Z(D.median/(R.get(C)??D.median));if(v?.baseline)W.baseline=!0;let O=m.get(N.id);if(O?.timing)W.delta={medianPct:Z(O.timing.medianDeltaPct),meanPct:Z(O.timing.meanDeltaPct),verdict:O.timing.verdict,pass:O.verdict==="pass"};return W})}var Se={name:"minimal",async render(o){let U=cn(o).map((c)=>JSON.stringify(c));return{text:U.length>0?`${U.join(`
13
+ `)}
14
+ `:""}}};var un="https://www.speedscope.app/file-format-schema.json";function Be(o){return o?.label??o?.command?.join(" ")??o?.entry?.task??"profile"}var Oe={name:"speedscope",async render(o,U={}){let c=ne(o,U.runId),R=new Map(o.workloads.map((C)=>[C.id,C]));return{files:c.map((C)=>{let N=C.cpu,{nodes:v}=N,D=oe(N),W=N.samples?.nodeIds??[],O=N.samples?.timeDeltasUs??[],E=Array(D.count);for(let _ of D.order){let J=D.parentIx[_],K=v[_].frameIx;E[_]=J===-1?[K]:[...E[J],K]}let j=Array(W.length);for(let _=0;_<W.length;_++){let J=D.indexOf(W[_]);j[_]=J===-1?[]:E[J]}let z=0;for(let _=0;_<O.length;_++)z+=O[_];let V={$schema:un,exporter:"ostia",name:Be(R.get(C.workloadId)),activeProfileIndex:0,shared:{frames:N.frames.map((_)=>({name:_.name||"(anonymous)",file:_.url,line:_.line!==void 0?_.line+1:void 0}))},profiles:[{type:"sampled",name:Be(R.get(C.workloadId)),unit:"microseconds",startValue:0,endValue:z,samples:j,weights:O}]};return{path:`${C.id}.speedscope.json`,content:`${JSON.stringify(V,null,2)}
15
+ `}})}}};function ie(o){return(o/1e6).toFixed(3)}function de(o){return o.label??o.command?.join(" ")??o.entry?.task??o.id}var Ee={name:"table",async render(o){let U=o.runs.filter((E)=>E.phase==="timing"&&E.timing!==void 0),c=new Map(o.workloads.map((E)=>[E.id,E]));if(U.length===0){let E=We(o,c);return{text:E.length>0?`${E.join(`
16
+ `)}
17
+ `:`(no timing runs)
18
+ `}}let R=U.map((E)=>{let j=c.get(E.workloadId);return{run:E,workload:j,label:j?de(j):E.workloadId}}),m=R.length>1,C=pe(R),N=[],v=Math.max(7,...R.map((E)=>E.label.length)),D=m?`${"Command".padEnd(v)} Mean [ms] Min\u2026Max [ms] Relative`:`${"Command".padEnd(v)} Mean [ms] Min\u2026Max [ms]`;N.push(D),N.push("-".repeat(D.length));for(let E of R){let{run:j,label:z,workload:V}=E,_=j.timing,J=`${ie(_.mean)} \xB1 ${ie(_.stddev)}`,K=`${ie(_.min)}\u2026${ie(_.max)}`,G=`${z.padEnd(v)} ${J.padEnd(15)} ${K.padEnd(18)}`;if(m){let L=_.median/(C.get(E)??_.median);if(L===1)G+=V?.baseline?" 1.00\xD7 (baseline)":" 1.00\xD7";else if(L>1)G+=` ${L.toFixed(2)}\xD7 slower`;else G+=` ${(1/L).toFixed(2)}\xD7 faster`}N.push(G);for(let L of j.warnings)N.push(` ! ${L.message}`)}let W=ln(o,c);if(W.length>0)N.push(""),N.push(...W);let O=We(o,c);if(O.length>0)N.push(""),N.push(...O);return{text:`${N.join(`
19
+ `)}
20
+ `}}};function pn(o,U,c){let R=o.runs.find((C)=>C.id===c),m=R?U.get(R.workloadId):void 0;return m?de(m):c}function We(o,U){if(!o.comparisons||o.comparisons.length===0)return[];let c=[];for(let R of o.comparisons){let m=pn(o,U,R.candidateRunId),C=R.verdict==="pass"?"\u2713":"\u2717";if(c.push(`${C} ${m}`),R.timing){let N=R.timing.medianDeltaPct>0?"+":"";c.push(` timing: ${N}${R.timing.medianDeltaPct.toFixed(1)}% median (${R.timing.verdict})`)}if(R.frames)for(let N of R.frames.slice(0,Ae)){if(Math.abs(N.deltaPct)<0.5)continue;let v=N.deltaPct>0?"+":"";c.push(` frame ${N.name}: ${v}${N.deltaPct.toFixed(1)}% self-time (${(N.baseSelfUs/1000).toFixed(2)}ms -> ${(N.candSelfUs/1000).toFixed(2)}ms)`)}if(R.heapTypes)for(let N of R.heapTypes.slice(0,je)){if(Math.abs(N.deltaPct)<0.5)continue;let v=N.deltaPct>0?"+":"";c.push(` heap ${N.type}: ${v}${N.deltaPct.toFixed(1)}% count (${N.baseCount} -> ${N.candCount})`)}}return c}var Ae=5,je=5;function ln(o,U){let c=[];for(let R of o.runs){if(R.phase!=="cpu"&&R.phase!=="heap")continue;let m=U.get(R.workloadId),C=m?de(m):R.workloadId;if(R.phase==="cpu")if(R.cpu){c.push(`CPU capture - ${C} (instrumented, ${R.cpu.samplingIntervalUs}\xB5s interval, diagnostic wall ${ie(R.diagnosticWallNs??0)}ms)`);let N=R.cpu.totals.reduce((v,D)=>v+D.selfUs,0)||1;for(let v of R.cpu.totals.slice(0,Ae)){let D=R.cpu.frames[v.frameIx],W=(v.selfUs/N*100).toFixed(1);c.push(` ${W.padStart(5)}% ${(v.selfUs/1000).toFixed(2).padStart(8)}ms self ${D?.name??"?"}`)}}else c.push(`CPU capture - ${C} (instrumented, no evidence captured)`);else if(R.heap){let N=((R.heap.heapSizeBytes??0)/1e6).toFixed(2);c.push(`Heap snapshot - ${C} (instrumented, ${R.heap.objectCount??"?"} objects, ${N}MB)`);for(let v of R.heap.typeCounts.slice(0,je))c.push(` ${String(v.count).padStart(6)} ${v.type}`)}else c.push(`Heap snapshot - ${C} (instrumented, no evidence captured)`);for(let N of R.artifacts)c.push(` artifact: ${N.path}`);for(let N of R.warnings)c.push(` ! ${N.message}`)}return c}var n={table:Ee,json:ve,markdown:De,jsonl:Ce,minimal:Se,collapsed:ke,mermaid:Fe,speedscope:Oe,cpuprofile:Ie};var mn="node_modules/.cache/ostia",fe=1000;async function k(o){let U=s({runs:o.runs??null,warmup:o.warmup??null,cpu:o.cpu??!1,heap:o.heap??!1,cpuIntervalUs:o.cpuIntervalUs??fe}),R=`${o.outDir??mn}/artifacts`,m=[],C=[];for(let N of o.commands){let v=Array.isArray(N)?N:Pe(N),D=u(v,Array.isArray(N)?void 0:N);m.push(D);let W=await g({argv:v,cwd:o.cwd,env:o.env,runs:o.runs,warmup:o.warmup}),O=i({workload:D,configFingerprint:U,trials:W.trials,timing:W.timing,warnings:W.warnings});if(C.push(O),o.cpu){let E=`${O.id}-cpu.cpuprofile`,j=await ge({argv:v,cwd:o.cwd,env:o.env,artifactDir:R,fileName:E,intervalUs:o.cpuIntervalUs??fe});C.push(await _e({workload:D,phase:"cpu",configFingerprint:U,diagnosticWallNs:j.diagnosticWallNs,exitCode:j.exitCode,cpu:j.cpu,artifactPath:j.artifactPath,artifactKind:"cpuprofile",warnings:j.warnings}))}if(o.heap){let E=`${O.id}-heap.heapsnapshot`,j=await be({argv:v,cwd:o.cwd,env:o.env,artifactDir:R,fileName:E});C.push(await _e({workload:D,phase:"heap",configFingerprint:U,diagnosticWallNs:j.diagnosticWallNs,exitCode:j.exitCode,heap:j.heap,artifactPath:j.artifactPath,artifactKind:"heapsnapshot",warnings:j.warnings}))}}return r(m,C)}async function _e(o){let U=`${o.workload.id}-${o.phase}-${o.configFingerprint}`,c=o.artifactPath?[await I(U,o.artifactKind,o.artifactPath)]:[];return b({workload:o.workload,phase:o.phase,configFingerprint:o.configFingerprint,diagnosticWallNs:o.diagnosticWallNs,exitCode:o.exitCode,cpu:o.cpu,heap:o.heap,warnings:o.warnings,artifacts:c})}async function B(o,U={}){let c=T(o),R=s({intervalUs:U.intervalUs??fe,origin:U.origin??"inspector"}),m=(W)=>W.samples?.nodeIds.length===0?[{code:"empty-profile",message:"In-process capture produced zero samples."}]:[];if(U.origin==="jsc"){let{result:W,cpu:O,jit:E,diagnosticWallNs:j}=await Re(o,U),z=b({workload:c,phase:"cpu",configFingerprint:R,diagnosticWallNs:j,cpu:O,jit:E,warnings:m(O),artifacts:[]});return{result:W,run:z}}let{result:C,cpu:N,diagnosticWallNs:v}=await ye(o,U),D=b({workload:c,phase:"cpu",configFingerprint:R,diagnosticWallNs:v,cpu:N,warnings:m(N),artifacts:[]});return{result:C,run:D}}
21
+ export{w,P,d,a,f,y,g,S,n,k,B};
@@ -0,0 +1,4 @@
1
+ // @bun
2
+ function h(n){return JSON.stringify(O(n))}function O(n){if(Array.isArray(n))return n.map(O);if(n!==null&&typeof n==="object"){let a={};for(let d of Object.keys(n).sort())a[d]=O(n[d]);return a}return n}function e(n,...a){let d=Bun.CryptoHasher.hash("sha256",h(a),"hex");return`${n}_${d.slice(0,16)}`}var c="0.1.0";function r(n,a){return{schemaVersion:1,toolVersion:c,bunVersion:Bun.version,platform:{os:process.platform,arch:process.arch},createdAt:new Date().toISOString(),workloads:n,runs:a}}function u(n,a){return{id:e("wl","subprocess",n,process.cwd()),kind:"subprocess",command:n,label:a}}function T(n,a){return{id:e("wl","inprocess",n.name,n.toString()),kind:"inprocess",label:a}}function C(n,a,d={}){return{id:e("wl","inprocess-entry",n,a),kind:"inprocess",entry:{file:n,task:a,...d.group!==void 0&&{group:d.group}},...d.label!==void 0&&{label:d.label},...d.baseline!==void 0&&{baseline:d.baseline},...d.description!==void 0&&{description:d.description},...d.groupDescription!==void 0&&{groupDescription:d.groupDescription},...d.isolated!==void 0&&{isolated:d.isolated}}}function i(n){return{id:e("run",n.workload.id,"timing",n.configFingerprint,Bun.version,c),workloadId:n.workload.id,phase:"timing",instrumented:!1,configFingerprint:n.configFingerprint,trials:n.trials,timing:n.timing,warnings:n.warnings,artifacts:[],memory:Q(n.trials)}}function Q(n){let a=n.map((d)=>d.maxRssBytes).filter((d)=>d!==void 0);if(a.length===0)return;return{origin:"resourceUsage",perTrial:n.map((d)=>({rssBytes:d.maxRssBytes})),maxRssBytes:Math.max(...a)}}function b(n){return{id:e("run",n.workload.id,n.phase,n.configFingerprint,Bun.version,c),workloadId:n.workload.id,phase:n.phase,instrumented:!0,configFingerprint:n.configFingerprint,trials:[{i:0,wallNs:n.diagnosticWallNs,exitCode:n.exitCode}],diagnosticWallNs:n.diagnosticWallNs,cpu:n.cpu,heap:n.heap,jit:n.jit,warnings:n.warnings,artifacts:n.artifacts}}async function I(n,a,d){let f=await Bun.file(d).arrayBuffer(),k=new Bun.CryptoHasher("sha256");return k.update(f),{id:e("art",n,a,d),kind:a,path:d,sha256:k.digest("hex"),bytes:f.byteLength}}function s(n){return e("cfg",n)}function x(n){return`${JSON.stringify(O(n),null,2)}
3
+ `}async function o(n,a){await Bun.write(a,x(n))}async function t(n){let a=await Bun.file(n).text();return JSON.parse(a)}var G=[],W;function U(n,a,d){let g=W;W={name:n,description:d?.description,isolate:d?.isolate,gc:d?.gc};try{a()}finally{W=g}}function M(n,a,d){G.push({groupName:W?.name,groupDescription:W?.description,groupIsolate:W?.isolate,groupGc:W?.gc,name:n,fn:a,baseline:d?.baseline,opts:d})}function N(){return G}function v(){G.length=0,W=void 0}function m(n){return n.groupName?`${n.groupName}/${n.name}`:n.name}function R(n,a){return n.opts?.isolate??n.groupIsolate??a}function D(n,a){return n.opts?.gc??n.groupGc??a}function F(n,a){if(!a)return[...n];let d=new RegExp(a);return n.filter((g)=>d.test(m(g)))}function l(n){if(n.length===0)throw Error("computeTimingStats: samples must be non-empty");let a=n.length,d=L(n),g=0;for(let y=0;y<a;y++)g+=n[y];let f=g/a,k=B(d,0.5),w=0;for(let y=0;y<a;y++){let S=n[y]-f;w+=S*S}let P=Math.sqrt(w/a),H=d[0],E=d[a-1],q=B(d,0.25),_=B(d,0.75),A=_-q,z=q-1.5*A,V=_+1.5*A,K=q-3*A,Z=_+3*A,J=0,j=0;for(let y=0;y<a;y++){let S=n[y];if(S<K||S>Z)j++;else if(S<z||S>V)J++}return{unit:"ns",samples:n,mean:f,median:k,stddev:P,min:H,max:E,outliers:{mild:J,severe:j}}}function L(n){let a=new Float64Array(n.length);return a.set(n),a.sort(),a}function B(n,a){let d=n.length;if(d===1)return n[0];let g=a*(d-1),f=Math.floor(g),k=Math.ceil(g);if(f===k)return n[f];let w=g-f;return n[f]*(1-w)+n[k]*w}var X=5000000,Y=200;function p(n,a,d="subprocess"){let g=[],f=n.samples[0];if(f!==void 0){let w=L(n.samples),P=B(w,0.25),E=B(w,0.75)-P;if(f>n.median+3*E&&E>0)g.push({code:"slow-first-run",message:`First run took ${(f/1e6).toFixed(2)}ms, much slower than the median ${(n.median/1e6).toFixed(2)}ms. Consider more warmup.`,data:{firstNs:f,medianNs:n.median}})}if(n.outliers.mild+n.outliers.severe>0)g.push({code:"outliers-detected",message:`${n.outliers.mild+n.outliers.severe} outlier(s) detected (${n.outliers.severe} severe, ${n.outliers.mild} mild).`,data:n.outliers});if(d==="subprocess"&&n.median<X)g.push({code:"fast-command",message:`Median run time (${(n.median/1e6).toFixed(3)}ms) is very fast; results may be dominated by spawn overhead.`,data:{medianNs:n.median}});if(d==="inprocess"&&n.median<Y)g.push({code:"below-timer-resolution",message:`Median run time (${n.median.toFixed(0)}ns) is close to timer resolution; consider a larger batch size or a coarser operation.`,data:{medianNs:n.median}});let k=a.filter((w)=>w!==void 0&&w!==0);if(k.length>0)g.push({code:"nonzero-exit",message:`${k.length} of ${a.length} trial(s) exited non-zero.`,data:{exitCodes:k}});return g}
4
+ export{h,e,c,r,u,T,C,i,b,I,s,x,o,t,l,p,U,M,N,v,m,R,D,F};
package/cli.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- import{x,d,a,f,w,g,n,y}from"./chunk-gsjgejr1.js";import{e,c,r,u,i,s,o,t}from"./chunk-y1gkhb0y.js";function q(p){return e("cache",p.workloadId,p.phase,p.configFingerprint,p.bunVersion,p.toolVersion,p.instrumented,p.inputsDigest??null)}async function _(p,l=process.cwd()){if(p.length===0)return;let m=new Set;for(let b of p){let P=new Bun.Glob(b);for await(let j of P.scan({cwd:l,absolute:!1}))m.add(j)}let k=[...m].sort(),h=await Promise.all(k.map(async(b)=>{let P=await Bun.file(`${l}/${b}`).arrayBuffer();return{path:b,sha256:Bun.CryptoHasher.hash("sha256",P,"hex")}}));return e("inputs",h)}function L(p,l){return`${p}/cache/${l}.json`}async function M(p,l){let m=Bun.file(L(p,l));if(!await m.exists())return;return await m.json()}async function W(p,l,m){await Bun.write(L(p,l),`${JSON.stringify(m,null,2)}
4
- `)}var X="node_modules/.cache/ostia",Q=".ostia/baselines",Y={runs:null,warmup:3,outDir:X,baselineDir:Q,baseline:"main",cpuIntervalUs:1000,thresholds:a,workloads:[]};async function V(p="ostia.config.json"){let l=Bun.file(p);if(!await l.exists())return;let m=await l.json();return{...Y,...m,thresholds:{...a,...m.thresholds??{}}}}function z(p,l){return`${p.baselineDir}/${l??p.baseline}.json`}class T extends Error{path;constructor(p){super(`No baseline document at ${p}. Create one with: ostia run --export-json ${p} <command...>`);this.path=p}}async function K(p){let{config:l}=p,m=z(l,p.baselineName);if(!await Bun.file(m).exists())throw new T(m);let h=await t(m),b=[],P=0,j=0,D=0;for(let C of l.workloads){let A=u(C.command,C.label),v=await _(C.inputs??[]),U=s({runs:l.runs,warmup:l.warmup}),H=q({workloadId:A.id,phase:"timing",configFingerprint:U,bunVersion:Bun.version,toolVersion:c,instrumented:!1,inputsDigest:v}),J=p.full?void 0:await M(l.outDir,H),S,B;if(J)S=J,B="cached",j++;else{P++;let O=await g({argv:C.command,runs:l.runs??void 0,warmup:l.warmup});S=i({workload:A,configFingerprint:U,trials:O.trials,timing:O.timing,warnings:O.warnings}),await W(l.outDir,H,S),B="executed",D++}b.push({workload:A,status:B,run:S})}let R=r(b.map((C)=>C.workload),b.map((C)=>C.run)),N=0,E=0,F=0;for(let C of b){let A=w(h,R,C.workload.id,l.thresholds);if(!A){F++;continue}if(C.comparison=A,A.verdict==="pass")N++;else E++}return R.comparisons=b.map((C)=>C.comparison).filter((C)=>C!==void 0),{document:R,summary:{total:l.workloads.length,affected:P,cached:j,executed:D,passed:N,regressed:E,missingBaseline:F,results:b}}}function G(p){let l=[];if(l.push(`${p.total} workloads`),l.push(`${p.affected} affected by this change`),l.push(`${p.cached} cached`),l.push(`${p.executed} executed`),p.missingBaseline>0)l.push(`${p.missingBaseline} skipped (no matching baseline workload)`);let m=p.results.filter((k)=>k.comparison?.verdict==="fail").map((k)=>{let h=k.comparison.timing,b=k.workload.label??k.workload.command?.join(" ")??k.workload.id;return h?`${h.medianDeltaPct>0?"+":""}${h.medianDeltaPct.toFixed(1)}% median on ${b}`:b});return l.push(`${p.passed} passed ${p.regressed} regressed${m.length>0?` (${m.join(", ")})`:""}`),l.push(""),l.push(`Profile CI: ${p.regressed>0?"\u2717":"\u2713"}`),`${l.join(`
3
+ import{w,P,d,a,f,y,g,n,k}from"./chunk-3qbcj1m9.js";import{e,c,r,u,i,s,o,t}from"./chunk-zrck2q0b.js";function L(p){return e("cache",p.workloadId,p.phase,p.configFingerprint,p.bunVersion,p.toolVersion,p.instrumented,p.inputsDigest??null)}async function W(p,l=process.cwd()){if(p.length===0)return;let m=new Set;for(let b of p){let C=new Bun.Glob(b);for await(let j of C.scan({cwd:l,absolute:!1}))m.add(j)}let x=[...m].sort(),h=await Promise.all(x.map(async(b)=>{let C=await Bun.file(`${l}/${b}`).arrayBuffer();return{path:b,sha256:Bun.CryptoHasher.hash("sha256",C,"hex")}}));return e("inputs",h)}function z(p,l){return`${p}/cache/${l}.json`}async function M(p,l){let m=Bun.file(z(p,l));if(!await m.exists())return;return await m.json()}async function V(p,l,m){await Bun.write(z(p,l),`${JSON.stringify(m,null,2)}
4
+ `)}var Y="node_modules/.cache/ostia",ee=".ostia/baselines",te={runs:null,warmup:3,outDir:Y,baselineDir:ee,baseline:"main",cpuIntervalUs:1000,thresholds:a,workloads:[]};async function q(p="ostia.config.json"){let l=Bun.file(p);if(!await l.exists())return;let m=await l.json();return{...te,...m,thresholds:{...a,...m.thresholds??{}}}}function G(p,l){return`${p.baselineDir}/${l??p.baseline}.json`}class U extends Error{path;constructor(p){super(`No baseline document at ${p}. Create one with: ostia run --export-json ${p} <command...>`);this.path=p}}async function K(p){let{config:l}=p,m=G(l,p.baselineName);if(!await Bun.file(m).exists())throw new U(m);let h=await t(m),b=[],C=0,j=0,F=0;for(let R of l.workloads){let E=u(R.command,R.label),N=await W(R.inputs??[]),I=s({runs:l.runs,warmup:l.warmup}),S=L({workloadId:E.id,phase:"timing",configFingerprint:I,bunVersion:Bun.version,toolVersion:c,instrumented:!1,inputsDigest:N}),_=p.full?void 0:await M(l.outDir,S),O,H;if(_)O=_,H="cached",j++;else{C++;let J=await g({argv:R.command,runs:l.runs??void 0,warmup:l.warmup});O=i({workload:E,configFingerprint:I,trials:J.trials,timing:J.timing,warnings:J.warnings}),await V(l.outDir,S,O),H="executed",F++}b.push({workload:E,status:H,run:O})}let D=r(b.map((R)=>R.workload),b.map((R)=>R.run)),v=0,B=0,A=0;for(let R of b){let E=y(h,D,R.workload.id,l.thresholds);if(!E){A++;continue}if(R.comparison=E,E.verdict==="pass")v++;else B++}return D.comparisons=b.map((R)=>R.comparison).filter((R)=>R!==void 0),{document:D,summary:{total:l.workloads.length,affected:C,cached:j,executed:F,passed:v,regressed:B,missingBaseline:A,results:b}}}function Z(p){let l=[];if(l.push(`${p.total} workloads`),l.push(`${p.affected} affected by this change`),l.push(`${p.cached} cached`),l.push(`${p.executed} executed`),p.missingBaseline>0)l.push(`${p.missingBaseline} skipped (no matching baseline workload)`);let m=p.results.filter((x)=>x.comparison?.verdict==="fail").map((x)=>{let h=x.comparison.timing,b=x.workload.label??x.workload.command?.join(" ")??x.workload.id;return h?`${h.medianDeltaPct>0?"+":""}${h.medianDeltaPct.toFixed(1)}% median on ${b}`:b});return l.push(`${p.passed} passed ${p.regressed} regressed${m.length>0?` (${m.join(", ")})`:""}`),l.push(""),l.push(`Profile CI: ${p.regressed>0?"\u2717":"\u2713"}`),`${l.join(`
5
5
  `)}
6
- `}async function I(p,l){if(p.text)process.stdout.write(p.text);if(!p.files||p.files.length===0)return;if(l)for(let m of p.files){let k=m.path?`${l}/${m.path}`:l;await Bun.write(k,m.content),process.stdout.write(`wrote ${k}
6
+ `}async function T(p,l){if(p.text)process.stdout.write(p.text);if(!p.files||p.files.length===0)return;if(l)for(let m of p.files){let x=m.path?`${l}/${m.path}`:l;await Bun.write(x,m.content),process.stdout.write(`wrote ${x}
7
7
  `)}else if(p.files.length===1)process.stdout.write(p.files[0].content);else for(let m of p.files)process.stdout.write(`--- ${m.path??"(unnamed)"} ---
8
8
  ${m.content}
9
- `)}var ee=`ostia run [flags] <command...>
9
+ `)}var se=`ostia run [flags] <command...>
10
10
 
11
11
  Run one or more commands N times with warmup and report timing statistics.
12
12
 
@@ -30,7 +30,7 @@ Examples:
30
30
  ostia run --runs 25 --warmup 3 "bun a.ts" "bun b.ts"
31
31
  ostia run --cpu --heap "bun src/server.ts"
32
32
  ostia run --format json "bun a.ts"
33
- `,te=`ostia bench [flags] <suite.ts...>
33
+ `,X=`ostia bench [flags] <suite.ts...>
34
34
 
35
35
  Run in-process benchmark suites (registered via group()/task()). Each suite file runs
36
36
  in its own spawned child process (isolated from CLI startup state).
@@ -49,7 +49,8 @@ Flags:
49
49
  Concurrent CPU-bound processes contend for cores, caches and turbo
50
50
  headroom, so numbers taken at --jobs > 1 are noisier and not
51
51
  like-for-like with a baseline measured at 1. "auto" = CPU count.
52
- --gc Bun.gc(true) between trials (default: off - hides allocation cost)
52
+ --gc Bun.gc(true) between trials (default: off - hides allocation cost).
53
+ Per-task { gc } / per-group { gc } override this default.
53
54
  --filter REGEX only run tasks whose "group/name" id matches this regex (substring,
54
55
  case-sensitive; unmatched tasks are skipped, not timed)
55
56
  --isolate give every task its own subprocess instead of sharing its suite
@@ -59,6 +60,15 @@ Flags:
59
60
  --jobs then pools across those per-task processes, so pair a
60
61
  higher --jobs with --isolate deliberately: overhead now scales
61
62
  with task count, not file count.
63
+ --preload PATH script imported before each suite file loads, in the same
64
+ subprocess (repeatable; runs in the order given). Use it to
65
+ install globals (jsdom's document/window) or register a
66
+ Bun.plugin() file-loader before the suite's own code runs.
67
+ --bun-flags FLAGS extra flags passed through to the \`bun\` invocation that runs each
68
+ suite file (repeatable; space-separated flags in one value are all
69
+ appended). Useful for packages whose exports map branches on a
70
+ resolution condition Bun doesn't set by default, e.g. Svelte/Vue's
71
+ "browser" vs "default" build: --bun-flags="--conditions=browser"
62
72
  --out-dir PATH directory for scratch IPC files (default: node_modules/.cache/ostia)
63
73
  --export-json PATH write the full ProfileDocument to PATH
64
74
  --format FORMAT table | json | jsonl | markdown | minimal (default: table)
@@ -75,16 +85,38 @@ Suite files register tasks like:
75
85
  task("small input", () => parse(smallBuf))
76
86
  task("full pipeline", () => build(), { timeBudgetMs: 2000, minSamples: 10 })
77
87
  }, { description: "parser throughput on representative inputs" })
78
- Per-task options override --time-budget / --min-samples for that task only.
88
+ Per-task options override --time-budget / --min-samples / --gc / --isolate for that task
89
+ only; per-group { gc } / { isolate } set the default for every task in that group.
79
90
  Optional { description } on group() and task() flows into the document (Workload.description
80
91
  / Workload.groupDescription) so the intent travels with the numbers.
81
92
 
93
+ Sweep a size dimension with range(start, end, multiplier?) (mitata's .range() point
94
+ generation, default multiplier 8, always ending on the end value):
95
+ import { group, task, range } from "<pkg>"
96
+ group("parse", () => {
97
+ for (const size of range(100, 10_000)) {
98
+ const input = buildInput(size) // setup, runs once per point, unmeasured
99
+ task(\`\${size} items\`, () => parse(input))
100
+ }
101
+ })
102
+
103
+ Project defaults: with no suite files given on the command line, ostia falls back to
104
+ ostia.config.json's "bench" section in the current directory - suites is a list of globs
105
+ (expanded with Bun.Glob), the rest are the same defaults as their matching flag:
106
+ { "bench": { "suites": ["bench/**/*.bench.ts"], "preload": ["./bench/setup.ts"], "jobs": "auto" } }
107
+ Any suite files given on the command line replace (not merge with) the config's "suites"
108
+ list; every other flag/config field is overridden individually, so "ostia bench --jobs 1"
109
+ still works as a one-off override without editing the config.
110
+
82
111
  Examples:
83
112
  ostia bench benches/parse.ts
84
113
  ostia bench --time-budget 1000 --min-samples 50 benches/*.ts
85
114
  ostia bench benches/*.ts --filter parse
86
115
  ostia bench benches/*.ts --jobs auto --format minimal
87
- `,Z=`ostia compare <base.json> <candidate.json>
116
+ ostia bench --preload ./bench/jsdom-setup.ts benches/*.dom.bench.ts
117
+ ostia bench --bun-flags="--conditions=browser" bench/*.dom.bench.ts
118
+ ostia bench # picks up suites/preload/jobs from ostia.config.json
119
+ `,Q=`ostia compare <base.json> <candidate.json>
88
120
  ostia compare <candidate.json> --baseline <path.json>
89
121
 
90
122
  Compare two ProfileDocuments (matched by workload id) and rank timing/frame/heap deltas.
@@ -102,7 +134,7 @@ Examples:
102
134
  `,re=`ostia report <document.json> [--format table|json|markdown|jsonl|minimal]
103
135
 
104
136
  Render a saved ProfileDocument.
105
- `,se=`ostia viz <document.json> --format FORMAT [--run <id>] [--out-dir PATH]
137
+ `,ne=`ostia viz <document.json> --format FORMAT [--run <id>] [--out-dir PATH]
106
138
 
107
139
  Render CPU evidence from a saved ProfileDocument as a visualization artifact. Files,
108
140
  not a GUI - hand the output to speedscope.app, flamegraph.pl, or
@@ -123,7 +155,7 @@ Flags:
123
155
  Examples:
124
156
  ostia viz run.json --format speedscope --out-dir node_modules/.cache/ostia/viz
125
157
  ostia viz run.json --format collapsed | flamegraph.pl > flame.svg
126
- `,ne=`ostia ci [--full] [--baseline NAME]
158
+ `,oe=`ostia ci [--full] [--baseline NAME]
127
159
 
128
160
  Load ostia.config.json, run configured workloads (reusing cached results when their
129
161
  fingerprint is unchanged), compare against the named baseline, and gate on regressions.
@@ -136,22 +168,22 @@ Flags:
136
168
  --help show this message
137
169
 
138
170
  Exit codes: 0 pass, 1 regression, 2 harness error (missing config/baseline, spawn failure).
139
- `;function oe(p){let l=[],m,k,h=!1,b=!1,P,j,D,R="table",N=!1,E=!1;for(let F=0;F<p.length;F++){let C=p[F];switch(C){case"--runs":m=Number(p[++F]);break;case"--warmup":k=Number(p[++F]);break;case"--cpu":h=!0;break;case"--heap":b=!0;break;case"--cpu-interval":P=Number(p[++F]);break;case"--out-dir":j=p[++F];break;case"--export-json":D=p[++F];break;case"--format":R=p[++F];break;case"--quiet":N=!0;break;case"--help":case"-h":E=!0;break;default:l.push(C)}}return{commands:l,runs:m,warmup:k,cpu:h,heap:b,cpuIntervalUs:P,outDir:j,exportJson:D,format:R,quiet:N,help:E}}async function ae(p){let l=oe(p);if(l.help||l.commands.length===0)return process.stdout.write(ee),l.help?0:2;if(!(l.format in n))return process.stderr.write(`Unknown --format "${l.format}". Expected one of: ${Object.keys(n).join(", ")}
140
- `),2;let m;try{m=await y({commands:l.commands,runs:l.runs,warmup:l.warmup,cpu:l.cpu,heap:l.heap,cpuIntervalUs:l.cpuIntervalUs,outDir:l.outDir})}catch(h){return process.stderr.write(`Run failed: ${h instanceof Error?h.message:String(h)}
141
- `),2}if(l.exportJson)await o(m,l.exportJson);if(!l.quiet){let b=await n[l.format].render(m,{});await I(b)}return m.runs.some((h)=>h.trials.some((b)=>b.exitCode!==void 0&&b.exitCode!==0))?1:0}function ie(p){let l=[],m,k,h,b=!1,P,j=!1,D,R,N="table",E=!1,F=!1;for(let C=0;C<p.length;C++){let A=p[C];switch(A){case"--time-budget":m=Number(p[++C]);break;case"--min-samples":k=Number(p[++C]);break;case"--jobs":{let v=p[++C];h=v==="auto"?x():Number(v);break}case"--gc":b=!0;break;case"--filter":P=p[++C];break;case"--isolate":j=!0;break;case"--out-dir":D=p[++C];break;case"--export-json":R=p[++C];break;case"--format":N=p[++C];break;case"--quiet":E=!0;break;case"--help":case"-h":F=!0;break;default:l.push(A)}}return{suites:l,timeBudgetMs:m,minSamples:k,jobs:h,gc:b,filter:P,isolate:j,outDir:D,exportJson:R,format:N,quiet:E,help:F}}async function ue(p){let l=ie(p);if(l.help||l.suites.length===0)return process.stdout.write(te),l.help?0:2;if(!(l.format in n))return process.stderr.write(`Unknown --format "${l.format}". Expected one of: ${Object.keys(n).join(", ")}
142
- `),2;if(l.jobs!==void 0&&!(l.jobs>=1))return process.stderr.write(`--jobs expects a positive integer or "auto".
143
- `),2;let m;try{m=await d({suites:l.suites,timeBudgetMs:l.timeBudgetMs,minSamples:l.minSamples,jobs:l.jobs,gc:l.gc,filter:l.filter,isolate:l.isolate,outDir:l.outDir})}catch(k){return process.stderr.write(`Bench failed: ${k instanceof Error?k.message:String(k)}
144
- `),2}if(l.exportJson)await o(m,l.exportJson);if(!l.quiet){let h=await n[l.format].render(m,{});await I(h)}return 0}function le(p){let l=[],m,k,h="table",b=!1,P=!1;for(let j=0;j<p.length;j++){let D=p[j];switch(D){case"--baseline":m=p[++j];break;case"--export-json":k=p[++j];break;case"--format":h=p[++j];break;case"--quiet":b=!0;break;case"--help":case"-h":P=!0;break;default:l.push(D)}}return{paths:l,baseline:m,exportJson:k,format:h,quiet:b,help:P}}async function ce(p){let l=le(p);if(l.help)return process.stdout.write(Z),0;let m,k;if(l.baseline)m=l.baseline,k=l.paths[0];else m=l.paths[0],k=l.paths[1];if(!m||!k)return process.stdout.write(Z),2;let h,b;try{[h,b]=await Promise.all([t(m),t(k)])}catch(R){return process.stderr.write(`Failed to load documents: ${R instanceof Error?R.message:String(R)}
145
- `),2}let P=f(h,b),j={...b,comparisons:P};if(l.exportJson)await o(j,l.exportJson);if(!l.quiet){let N=await n[l.format].render(j,{});await I(N)}return P.some((R)=>R.verdict==="fail")?1:0}function de(p){let l,m="table",k=!1;for(let h=0;h<p.length;h++){let b=p[h];switch(b){case"--format":m=p[++h];break;case"--help":case"-h":k=!0;break;default:l=b}}return{path:l,format:m,help:k}}async function pe(p){let l=de(p);if(l.help||!l.path)return process.stdout.write(re),l.help?0:2;let m;try{m=await t(l.path)}catch(b){return process.stderr.write(`Failed to load ${l.path}: ${b instanceof Error?b.message:String(b)}
146
- `),2}let h=await n[l.format].render(m,{});return await I(h),0}var me={ascii:"table"};function fe(p){let l,m,k,h,b=!1;for(let P=0;P<p.length;P++){let j=p[P];switch(j){case"--format":{let D=p[++P]??"";m=me[D]??D;break}case"--run":k=p[++P];break;case"--out-dir":h=p[++P];break;case"--help":case"-h":b=!0;break;default:l=j}}return{path:l,format:m,runId:k,outDir:h,help:b}}async function he(p){let l=fe(p);if(l.help||!l.path||!l.format)return process.stdout.write(se),l.help?0:2;if(!(l.format in n))return process.stderr.write(`Unknown --format "${l.format}". Expected one of: ${Object.keys(n).join(", ")}, ascii
171
+ `;function ae(p){let l=[],m,x,h=!1,b=!1,C,j,F,D="table",v=!1,B=!1;for(let A=0;A<p.length;A++){let R=p[A];switch(R){case"--runs":m=Number(p[++A]);break;case"--warmup":x=Number(p[++A]);break;case"--cpu":h=!0;break;case"--heap":b=!0;break;case"--cpu-interval":C=Number(p[++A]);break;case"--out-dir":j=p[++A];break;case"--export-json":F=p[++A];break;case"--format":D=p[++A];break;case"--quiet":v=!0;break;case"--help":case"-h":B=!0;break;default:l.push(R)}}return{commands:l,runs:m,warmup:x,cpu:h,heap:b,cpuIntervalUs:C,outDir:j,exportJson:F,format:D,quiet:v,help:B}}async function ie(p){let l=ae(p);if(l.help||l.commands.length===0)return process.stdout.write(se),l.help?0:2;if(!(l.format in n))return process.stderr.write(`Unknown --format "${l.format}". Expected one of: ${Object.keys(n).join(", ")}
172
+ `),2;let m;try{m=await k({commands:l.commands,runs:l.runs,warmup:l.warmup,cpu:l.cpu,heap:l.heap,cpuIntervalUs:l.cpuIntervalUs,outDir:l.outDir})}catch(h){return process.stderr.write(`Run failed: ${h instanceof Error?h.message:String(h)}
173
+ `),2}if(l.exportJson)await o(m,l.exportJson);if(!l.quiet){let b=await n[l.format].render(m,{});await T(b)}return m.runs.some((h)=>h.trials.some((b)=>b.exitCode!==void 0&&b.exitCode!==0))?1:0}function le(p){let l=[],m,x,h,b=!1,C,j=!1,F=[],D=[],v,B,A="table",R=!1,E=!1;for(let N=0;N<p.length;N++){let I=p[N];if(I==="--bun-flags"||I.startsWith("--bun-flags=")){let S=I.startsWith("--bun-flags=")?I.slice(12):p[++N]??"";D.push(...S.split(/\s+/).filter(Boolean));continue}switch(I){case"--time-budget":m=Number(p[++N]);break;case"--min-samples":x=Number(p[++N]);break;case"--jobs":{let S=p[++N];h=S==="auto"?w():Number(S);break}case"--gc":b=!0;break;case"--filter":C=p[++N];break;case"--isolate":j=!0;break;case"--preload":F.push(p[++N]);break;case"--out-dir":v=p[++N];break;case"--export-json":B=p[++N];break;case"--format":A=p[++N];break;case"--quiet":R=!0;break;case"--help":case"-h":E=!0;break;default:l.push(I)}}return{suites:l,timeBudgetMs:m,minSamples:x,jobs:h,gc:b,filter:C,isolate:j,preload:F,bunFlags:D,outDir:v,exportJson:B,format:A,quiet:R,help:E}}async function ue(p){let l=le(p);if(l.help)return process.stdout.write(X),0;if(!(l.format in n))return process.stderr.write(`Unknown --format "${l.format}". Expected one of: ${Object.keys(n).join(", ")}
174
+ `),2;let m=await q(),x=await P(l,m?.bench);if(x.suites.length===0)return process.stdout.write(X),2;if(x.jobs!==void 0&&!(x.jobs>=1))return process.stderr.write(`--jobs expects a positive integer or "auto".
175
+ `),2;let h;try{h=await d(x)}catch(b){return process.stderr.write(`Bench failed: ${b instanceof Error?b.message:String(b)}
176
+ `),2}if(l.exportJson)await o(h,l.exportJson);if(!l.quiet){let C=await n[l.format].render(h,{});await T(C)}return 0}function ce(p){let l=[],m,x,h="table",b=!1,C=!1;for(let j=0;j<p.length;j++){let F=p[j];switch(F){case"--baseline":m=p[++j];break;case"--export-json":x=p[++j];break;case"--format":h=p[++j];break;case"--quiet":b=!0;break;case"--help":case"-h":C=!0;break;default:l.push(F)}}return{paths:l,baseline:m,exportJson:x,format:h,quiet:b,help:C}}async function de(p){let l=ce(p);if(l.help)return process.stdout.write(Q),0;let m,x;if(l.baseline)m=l.baseline,x=l.paths[0];else m=l.paths[0],x=l.paths[1];if(!m||!x)return process.stdout.write(Q),2;let h,b;try{[h,b]=await Promise.all([t(m),t(x)])}catch(D){return process.stderr.write(`Failed to load documents: ${D instanceof Error?D.message:String(D)}
177
+ `),2}let C=f(h,b),j={...b,comparisons:C};if(l.exportJson)await o(j,l.exportJson);if(!l.quiet){let v=await n[l.format].render(j,{});await T(v)}return C.some((D)=>D.verdict==="fail")?1:0}function pe(p){let l,m="table",x=!1;for(let h=0;h<p.length;h++){let b=p[h];switch(b){case"--format":m=p[++h];break;case"--help":case"-h":x=!0;break;default:l=b}}return{path:l,format:m,help:x}}async function me(p){let l=pe(p);if(l.help||!l.path)return process.stdout.write(re),l.help?0:2;let m;try{m=await t(l.path)}catch(b){return process.stderr.write(`Failed to load ${l.path}: ${b instanceof Error?b.message:String(b)}
178
+ `),2}let h=await n[l.format].render(m,{});return await T(h),0}var fe={ascii:"table"};function he(p){let l,m,x,h,b=!1;for(let C=0;C<p.length;C++){let j=p[C];switch(j){case"--format":{let F=p[++C]??"";m=fe[F]??F;break}case"--run":x=p[++C];break;case"--out-dir":h=p[++C];break;case"--help":case"-h":b=!0;break;default:l=j}}return{path:l,format:m,runId:x,outDir:h,help:b}}async function ge(p){let l=he(p);if(l.help||!l.path||!l.format)return process.stdout.write(ne),l.help?0:2;if(!(l.format in n))return process.stderr.write(`Unknown --format "${l.format}". Expected one of: ${Object.keys(n).join(", ")}, ascii
147
179
  `),2;let m;try{m=await t(l.path)}catch(b){return process.stderr.write(`Failed to load ${l.path}: ${b instanceof Error?b.message:String(b)}
148
180
  `),2}let h=await n[l.format].render(m,{runId:l.runId});if(!h.text&&(!h.files||h.files.length===0))return process.stderr.write(l.runId?`No CPU evidence found for run "${l.runId}".
149
181
  `:`No CPU evidence found in this document (no cpu-phase runs). Capture some with "ostia run --cpu ...".
150
- `),2;return await I(h,l.outDir),0}function ge(p){let l=!1,m,k,h=!1,b=!1;for(let P=0;P<p.length;P++)switch(p[P]){case"--full":l=!0;break;case"--baseline":m=p[++P];break;case"--export-json":k=p[++P];break;case"--quiet":h=!0;break;case"--help":case"-h":b=!0;break}return{full:l,baseline:m,exportJson:k,quiet:h,help:b}}async function be(p){let l=ge(p);if(l.help)return process.stdout.write(ne),0;let m=await V();if(!m)return process.stderr.write(`No ostia.config.json found. "ostia ci" needs configured workloads.
182
+ `),2;return await T(h,l.outDir),0}function be(p){let l=!1,m,x,h=!1,b=!1;for(let C=0;C<p.length;C++)switch(p[C]){case"--full":l=!0;break;case"--baseline":m=p[++C];break;case"--export-json":x=p[++C];break;case"--quiet":h=!0;break;case"--help":case"-h":b=!0;break}return{full:l,baseline:m,exportJson:x,quiet:h,help:b}}async function we(p){let l=be(p);if(l.help)return process.stdout.write(oe),0;let m=await q();if(!m)return process.stderr.write(`No ostia.config.json found. "ostia ci" needs configured workloads.
151
183
  `),2;if(m.workloads.length===0)return process.stderr.write(`ostia.config.json has no "workloads" configured.
152
- `),2;let k;try{k=await K({config:m,full:l.full,baselineName:l.baseline})}catch(h){if(h instanceof T)return process.stderr.write(`${h.message}
184
+ `),2;let x;try{x=await K({config:m,full:l.full,baselineName:l.baseline})}catch(h){if(h instanceof U)return process.stderr.write(`${h.message}
153
185
  `),2;return process.stderr.write(`CI run failed: ${h instanceof Error?h.message:String(h)}
154
- `),2}if(l.exportJson)await o(k.document,l.exportJson);if(!l.quiet)process.stdout.write(G(k.summary));return k.summary.regressed>0?1:0}async function we(){let[p,...l]=process.argv.slice(2);switch(p){case"run":return ae(l);case"bench":return ue(l);case"compare":return ce(l);case"report":return pe(l);case"ci":return be(l);case"viz":return he(l);case void 0:case"--help":case"-h":return process.stdout.write(`ostia - Bun-native profile IR engine
186
+ `),2}if(l.exportJson)await o(x.document,l.exportJson);if(!l.quiet)process.stdout.write(Z(x.summary));return x.summary.regressed>0?1:0}async function ke(){let[p,...l]=process.argv.slice(2);switch(p){case"run":return ie(l);case"bench":return ue(l);case"compare":return de(l);case"report":return me(l);case"ci":return we(l);case"viz":return ge(l);case void 0:case"--help":case"-h":return process.stdout.write(`ostia - Bun-native profile IR engine
155
187
 
156
188
  Commands:
157
189
  run Run commands N times and report timing/CPU/heap
@@ -163,4 +195,4 @@ Commands:
163
195
 
164
196
  Run "ostia <command> --help" for details.
165
197
  `),p===void 0?2:0;default:return process.stderr.write(`Unknown subcommand "${p}". Run "ostia --help".
166
- `),2}}if(import.meta.main)we().then((p)=>process.exit(p));
198
+ `),2}}if(import.meta.main)ke().then((p)=>process.exit(p));
package/index.d.ts CHANGED
@@ -257,10 +257,34 @@ interface BenchOptions {
257
257
  * many cheap ones sharing a process). Multiplies process-spawn overhead by
258
258
  * task count instead of file count. */
259
259
  isolate?: boolean;
260
+ /** Scripts run, in order, before each suite file loads - in the same
261
+ * subprocess, so they can install globals (jsdom's `document`/`window`) or
262
+ * register a `Bun.plugin()` file-loader (e.g. for `.svelte`/`.vue`) ahead
263
+ * of the suite's own top-level code. Consumer-authored; ostia ships no
264
+ * preload scripts itself. */
265
+ preload?: string[];
266
+ /** Extra flags passed through to the `bun` invocation that runs each suite
267
+ * file (e.g. `["--conditions", "browser"]`), inserted before the runner
268
+ * script path so `bun` itself parses them rather than the runner. Useful
269
+ * for suites that import packages whose `exports` map branches on a
270
+ * resolution condition Bun doesn't set by default (e.g. Svelte/Vue's
271
+ * `browser` vs `default` builds). */
272
+ bunFlags?: string[];
260
273
  }
261
274
 
262
275
  export declare function bench(opts: BenchOptions): Promise<ProfileDocument>;
263
276
 
277
+ interface Thresholds {
278
+ timingPct: number;
279
+ frameSelfPct: number;
280
+ heapTypePct: number;
281
+ minFrameSelfUs: number;
282
+ }
283
+
284
+ export declare function compareDocuments(base: ProfileDocument, cand: ProfileDocument, thresholds?: Thresholds): Comparison[];
285
+
286
+ export declare function range(start: number, end: number, multiplier?: number): number[];
287
+
264
288
  export interface TaskOptions {
265
289
  /** Marks this task as the Relative reference for its group in the table
266
290
  * renderer, mirroring mitata's `baseline()`. At most one per group. */
@@ -278,6 +302,9 @@ export interface TaskOptions {
278
302
  * run. Overrides the group's and the suite-wide `bench({ isolate })` /
279
303
  * `--isolate` default for this task only. */
280
304
  isolate?: boolean;
305
+ /** Overrides the suite-wide `bench({ gc })` / `--gc` (and any
306
+ * `GroupOptions.gc`) for this task only. */
307
+ gc?: boolean;
281
308
  }
282
309
 
283
310
  export interface GroupOptions {
@@ -287,21 +314,15 @@ export interface GroupOptions {
287
314
  /** Default `isolate` for every task in this group, unless a task overrides
288
315
  * it with its own `TaskOptions.isolate`. */
289
316
  isolate?: boolean;
317
+ /** Default `gc` for every task in this group, unless a task overrides it
318
+ * with its own `TaskOptions.gc`. */
319
+ gc?: boolean;
290
320
  }
291
321
 
292
322
  export declare function group(name: string, fn: () => void, opts?: GroupOptions): void;
293
323
 
294
324
  export declare function task(name: string, fn: () => unknown | Promise<unknown>, opts?: TaskOptions): void;
295
325
 
296
- interface Thresholds {
297
- timingPct: number;
298
- frameSelfPct: number;
299
- heapTypePct: number;
300
- minFrameSelfUs: number;
301
- }
302
-
303
- export declare function compareDocuments(base: ProfileDocument, cand: ProfileDocument, thresholds?: Thresholds): Comparison[];
304
-
305
326
  export declare function saveDocument(doc: ProfileDocument, path: string): Promise<void>;
306
327
 
307
328
  export declare function loadDocument(path: string): Promise<ProfileDocument>;
package/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{d,f,n,y,v}from"./chunk-gsjgejr1.js";import{o,t,F,S}from"./chunk-y1gkhb0y.js";export{d as bench,f as compareDocuments,F as group,t as loadDocument,v as profile,n as renderers,y as run,o as saveDocument,S as task};
2
+ import{d,f,S,n,k,B}from"./chunk-3qbcj1m9.js";import{o,t,U,M}from"./chunk-zrck2q0b.js";export{d as bench,f as compareDocuments,U as group,t as loadDocument,B as profile,S as range,n as renderers,k as run,o as saveDocument,M as task};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ostia",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Fast profiling and benchmarking for Bun.",
5
5
  "type": "module",
6
6
  "exports": {
package/runner.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- import{r,P,i,s,o,l,m,I,C,p,N,D}from"./chunk-y1gkhb0y.js";var z=500,H=20,A=3,j=10,v=2,X=0.1,q=1000,K=1e4;function J(n){let e=Math.log10(Math.max(1,n)/1e6),a=Math.round(A+v*e);return Math.min(j,Math.max(A,a))}function Q(n,e){let a=Math.floor(e/n);return Math.min(H,Math.max(a,J(n)))}var L=0;function O(n){if(typeof n==="number")L+=n;else if(n!==void 0&&n!==null)L+=1}function B(n){return n!==null&&typeof n==="object"&&typeof n.then==="function"}function G(n,e){return Math.max(1,Math.ceil(q/n),Math.ceil(e/(n*K)))}async function U(n,e={}){let a=(e.timeBudgetMs??z)*1e6,d=a*(e.warmupFraction??X),T=Bun.nanoseconds(),f=0,b=0;while(b<d){let g=n();O(B(g)?await g:g),f++,b=Bun.nanoseconds()-T}let h;if(f>0)h=Math.max(1,b/f);else{let g=Bun.nanoseconds(),w=n();O(B(w)?await w:w),h=Math.max(1,Bun.nanoseconds()-g)}let t=G(h,a);if(t>1){let g=Bun.nanoseconds();for(let w=0;w<t;w++){let k=n();O(B(k)?await k:k)}h=Math.max(1,(Bun.nanoseconds()-g)/t),t=G(h,a)}let u=h*t,S=e.minSamples??Q(u,a),c=[],M=Bun.nanoseconds(),F=0,R=0;while(R<S||F<a){let g=Bun.nanoseconds();for(let k=0;k<t;k++){let _=n();O(B(_)?await _:_)}let w=Bun.nanoseconds();if(c.push({i:R,wallNs:(w-g)/t}),R++,F=Bun.nanoseconds()-M,e.gc)Bun.gc(!0)}let W=c.map((g)=>g.wallNs),y=l(W),E=m(y,[],"inprocess"),x=J(u);if(c.length<x)E.push({code:"low-sample-count",message:`Only ${c.length} sample(s) at ~${V(u)} per trial; ${x} is the floor for this cost class. Raise minSamples or the time budget for a steadier number.`,data:{samples:c.length,target:x,trialCostNs:u}});return{trials:c,timing:y,warnings:E}}function V(n){if(n>=1e9)return`${(n/1e9).toFixed(2)}s`;if(n>=1e6)return`${(n/1e6).toFixed(1)}ms`;if(n>=1000)return`${(n/1000).toFixed(1)}\xB5s`;return`${n.toFixed(0)}ns`}async function Y(){let[n,e,a]=process.argv.slice(2);if(!n||!e)return process.stderr.write(`bench runner: usage: runner.ts <suiteFile> <outputPath> [optsJson]
4
- `),2;let d=a?JSON.parse(a):{};C(),await import(n);let T=I();if(T.length===0)return process.stderr.write(`bench runner: ${n} registered no tasks (no task() calls found).
5
- `),2;let f=D(T,d.filter);if(d.taskIds){let t=new Set(d.taskIds);f=f.filter((u)=>t.has(p(u)))}if(f.length===0)return process.stderr.write(`bench runner: --filter ${JSON.stringify(d.filter)} matched zero of ${T.length} registered tasks in ${n}.
6
- `),2;if(d.planOnly){let t=f.map((u)=>({id:p(u),isolate:N(u,d.isolate??!1)}));return await Bun.write(e,JSON.stringify({tasks:t})),0}let b=[],h=[];for(let t of f){let u=p(t),S=P(n,u,{label:u,baseline:t.baseline,group:t.groupName,description:t.opts?.description,groupDescription:t.groupDescription,isolated:d.markIsolated});b.push(S);let c={...d,...t.opts?.timeBudgetMs!==void 0&&{timeBudgetMs:t.opts.timeBudgetMs},...t.opts?.minSamples!==void 0&&{minSamples:t.opts.minSamples}},M=await U(t.fn,c);h.push(i({workload:S,configFingerprint:s({timeBudgetMs:c.timeBudgetMs??null,minSamples:c.minSamples??null,gc:c.gc??!1}),trials:M.trials,timing:M.timing,warnings:M.warnings}))}return await o(r(b,h),e),0}Y().then((n)=>process.exit(n));
3
+ import{r,C,i,s,o,l,p,N,v,m,R,D,F}from"./chunk-zrck2q0b.js";var z=500,H=20,A=3,j=10,X=2,q=0.1,K=1000,Q=1e4;function J(t){let a=Math.log10(Math.max(1,t)/1e6),c=Math.round(A+X*a);return Math.min(j,Math.max(A,c))}function V(t,a){let c=Math.floor(a/t);return Math.min(H,Math.max(c,J(t)))}var L=0;function O(t){if(typeof t==="number")L+=t;else if(t!==void 0&&t!==null)L+=1}function I(t){return t!==null&&typeof t==="object"&&typeof t.then==="function"}function G(t,a){return Math.max(1,Math.ceil(K/t),Math.ceil(a/(t*Q)))}async function U(t,a={}){let c=(a.timeBudgetMs??z)*1e6,e=c*(a.warmupFraction??q),S=Bun.nanoseconds(),g=0,B=0;while(B<e){let u=t();O(I(u)?await u:u),g++,B=Bun.nanoseconds()-S}let f;if(g>0)f=Math.max(1,B/g);else{let u=Bun.nanoseconds(),b=t();O(I(b)?await b:b),f=Math.max(1,Bun.nanoseconds()-u)}let d=G(f,c);if(d>1){let u=Bun.nanoseconds();for(let b=0;b<d;b++){let M=t();O(I(M)?await M:M)}f=Math.max(1,(Bun.nanoseconds()-u)/d),d=G(f,c)}let n=f*d,h=a.minSamples??V(n,c),w=[],k=Bun.nanoseconds(),T=0,x=0;while(x<h||T<c){let u=Bun.nanoseconds();for(let M=0;M<d;M++){let P=t();O(I(P)?await P:P)}let b=Bun.nanoseconds();if(w.push({i:x,wallNs:(b-u)/d}),x++,T=Bun.nanoseconds()-k,a.gc)Bun.gc(!0)}let W=w.map((u)=>u.wallNs),E=l(W),y=p(E,[],"inprocess"),_=J(n);if(w.length<_)y.push({code:"low-sample-count",message:`Only ${w.length} sample(s) at ~${Y(n)} per trial; ${_} is the floor for this cost class. Raise minSamples or the time budget for a steadier number.`,data:{samples:w.length,target:_,trialCostNs:n}});return{trials:w,timing:E,warnings:y}}function Y(t){if(t>=1e9)return`${(t/1e9).toFixed(2)}s`;if(t>=1e6)return`${(t/1e6).toFixed(1)}ms`;if(t>=1000)return`${(t/1000).toFixed(1)}\xB5s`;return`${t.toFixed(0)}ns`}async function Z(){let[t,a,c]=process.argv.slice(2);if(!t||!a)return process.stderr.write(`bench runner: usage: runner.ts <suiteFile> <outputPath> [optsJson]
4
+ `),2;let e=c?JSON.parse(c):{};for(let n of e.preload??[])await import(n);v(),await import(t);let S=N();if(S.length===0)return process.stderr.write(`bench runner: ${t} registered no tasks (no task() calls found).
5
+ `),2;let g=F(S,e.filter);if(e.taskIds){let n=new Set(e.taskIds);g=g.filter((h)=>n.has(m(h)))}if(g.length===0)return process.stderr.write(`bench runner: --filter ${JSON.stringify(e.filter)} matched zero of ${S.length} registered tasks in ${t}.
6
+ `),2;if(e.planPath){let n=g.map((h)=>({id:m(h),isolate:R(h,e.isolate??!1)}));await Bun.write(e.planPath,JSON.stringify({tasks:n}))}let B=e.taskIds?g:g.filter((n)=>!R(n,e.isolate??!1)),f=[],d=[];for(let n of B){let h=m(n),w=C(t,h,{label:h,baseline:n.baseline,group:n.groupName,description:n.opts?.description,groupDescription:n.groupDescription,isolated:e.markIsolated});f.push(w);let k={...e,...n.opts?.timeBudgetMs!==void 0&&{timeBudgetMs:n.opts.timeBudgetMs},...n.opts?.minSamples!==void 0&&{minSamples:n.opts.minSamples},gc:D(n,e.gc??!1)},T=await U(n.fn,k);d.push(i({workload:w,configFingerprint:s({timeBudgetMs:k.timeBudgetMs??null,minSamples:k.minSamples??null,gc:k.gc??!1}),trials:T.trials,timing:T.timing,warnings:T.warnings}))}return await o(r(f,d),a),0}Z().then((t)=>process.exit(t));
package/chunk-gsjgejr1.js DELETED
@@ -1,21 +0,0 @@
1
- // @bun
2
- import{h,e,r,u,R,i,b,T,s,k,t,l,m}from"./chunk-y1gkhb0y.js";function je(o){return o.startsWith("file://")?o.slice(7):o}function oe(o,D,c){let C=o.nodes,p=C.length,I=new Map,N=[],P=new Map,U=new Int32Array(p);for(let O=0;O<p;O++){let W=C[O],F=W.callFrame,L=je(F.url),K=I.get(F.functionName);if(K===void 0)K=new Map,I.set(F.functionName,K);let G=K.get(L);if(G===void 0)G=N.length,K.set(L,G),N.push({key:e("fr",F.functionName,L),name:F.functionName,url:L||void 0,line:F.lineNumber>=0?F.lineNumber:void 0,col:F.columnNumber>=0?F.columnNumber:void 0});U[O]=G,P.set(W.id,O)}let B=Array(p);for(let O=0;O<p;O++){let W=C[O];B[O]={id:W.id,frameIx:U[P.get(W.id)],children:W.children??[]}}let M=new Float64Array(p),S=new Float64Array(p),{samples:E,timeDeltas:V}=o;for(let O=0;O<E.length;O++){let W=P.get(E[O]);if(W===void 0)continue;M[W]+=V[O]??0,S[W]+=1}let z=new Int32Array(p).fill(-1);for(let O=0;O<p;O++){let W=C[O].children;if(!W)continue;for(let F of W){let L=P.get(F);if(L!==void 0)z[L]=O}}let A=[],H=[];for(let O=p-1;O>=0;O--)if(z[O]===-1)H.push(O);while(H.length>0){let O=H.pop();A.push(O);let W=C[O].children;if(!W)continue;for(let F of W){let L=P.get(F);if(L!==void 0&&z[L]===O)H.push(L)}}let _=new Float64Array(p);for(let O=A.length-1;O>=0;O--){let W=A[O];_[W]+=M[W];let F=z[W];if(F>=0)_[F]+=_[W]}let J=Array(N.length),j=[];for(let O=0;O<p;O++){let W=B[O].frameIx,F=J[W];if(F)F.selfUs+=M[O],F.totalUs+=_[O],F.samples+=S[O];else{let L={frameIx:W,selfUs:M[O],totalUs:_[O],samples:S[O]};J[W]=L,j.push(L)}}return{origin:D,samplingIntervalUs:c,frames:N,nodes:B,totals:j.sort((O,W)=>W.selfUs-O.selfUs),samples:{nodeIds:o.samples,timeDeltasUs:o.timeDeltas}}}function _e(o,D,c,C){let p=["--cpu-prof","--cpu-prof-dir",D,"--cpu-prof-name",c,"--cpu-prof-interval",String(C)],I=o[0];if(I==="bun"||I?.endsWith("/bun"))return[I,...p,...o.slice(1)];return o}async function de(o){let D=`${o.artifactDir}/${o.fileName}`,c=o.argv[0],C=c==="bun"||c?.endsWith("/bun"),p=_e(o.argv,o.artifactDir,o.fileName,o.intervalUs),I=C?o.env:{...process.env,...o.env,BUN_OPTIONS:`--cpu-prof --cpu-prof-dir ${o.artifactDir} --cpu-prof-name ${o.fileName} --cpu-prof-interval ${o.intervalUs}`},N=Bun.nanoseconds(),U=await Bun.spawn(p,{cwd:o.cwd,env:I,stdout:"ignore",stderr:"ignore",stdin:"ignore"}).exited,B=Bun.nanoseconds()-N,M=Bun.file(D);if(!await M.exists())return{diagnosticWallNs:B,exitCode:U,warnings:[{code:"artifact-missing",message:`Expected a .cpuprofile at ${D} after exit ${U}, found nothing. The workload's argv[0] must be a \`bun\` binary for CPU capture.`,data:{artifactPath:D,argv:o.argv}}]};let S=await M.json(),E=oe(S,"cpu-prof",o.intervalUs),V=S.samples.length===0?[{code:"empty-profile",message:"CPU capture produced zero samples."}]:[];return{diagnosticWallNs:B,exitCode:U,artifactPath:D,cpu:E,warnings:V}}function fe(o,D="heap-prof"){let{node_fields:c,node_types:C}=o.snapshot.meta,p=c.indexOf("type"),I=c.indexOf("self_size"),N=c.length,P=C[0];if(p===-1||I===-1||!Array.isArray(P))return{origin:D,typeCounts:[],objectCount:o.snapshot.node_count};let U=P.length,B=Array(U),M=new Map,S=[],E=0,V=o.nodes,z=V.length;for(let j=0;j<z;j+=N){let O=V[j+p],W=V[j+I]??0;E+=W;let F;if(O>=0&&O<U){if(F=B[O],F===void 0)F={type:P[O],count:0,bytes:0},B[O]=F,S.push(F)}else{let L=`unknown(${O})`;if(F=M.get(L),F===void 0)F={type:L,count:0,bytes:0},M.set(L,F),S.push(F)}F.count++,F.bytes+=W}let A=S.sort((j,O)=>O.count-j.count),H=A.slice(0,20),_=A.slice(20),J=H.map(({type:j,count:O,bytes:W})=>({type:j,count:O,retainedBytes:W}));if(_.length>0){let j=0,O=0;for(let W of _)j+=W.count,O+=W.bytes;J.push({type:"other",count:j,retainedBytes:O})}return{origin:D,heapSizeBytes:E,objectCount:o.snapshot.node_count,typeCounts:J}}function Le(o,D,c){let C=["--heap-prof","--heap-prof-dir",D,"--heap-prof-name",c],p=o[0];if(p==="bun"||p?.endsWith("/bun"))return[p,...C,...o.slice(1)];return o}async function ge(o){let D=`${o.artifactDir}/${o.fileName}`,c=o.argv[0],C=c==="bun"||c?.endsWith("/bun"),p=Le(o.argv,o.artifactDir,o.fileName),I=C?o.env:{...process.env,...o.env,BUN_OPTIONS:`--heap-prof --heap-prof-dir ${o.artifactDir} --heap-prof-name ${o.fileName}`},N=Bun.nanoseconds(),U=await Bun.spawn(p,{cwd:o.cwd,env:I,stdout:"ignore",stderr:"ignore",stdin:"ignore"}).exited,B=Bun.nanoseconds()-N,M=Bun.file(D);if(!await M.exists())return{diagnosticWallNs:B,exitCode:U,warnings:[{code:"artifact-missing",message:`Expected a heap snapshot at ${D} after exit ${U}, found nothing. The workload's argv[0] must be a \`bun\` binary for heap capture.`,data:{artifactPath:D,argv:o.argv}}]};let S=await M.json(),E=fe(S,"heap-prof");return{diagnosticWallNs:B,exitCode:U,artifactPath:D,heap:E,warnings:[]}}import{Session as He}from"inspector/promises";var Je=1000;async function he(o,D={}){let c=D.intervalUs??Je,C=new He;C.connect();let p=Bun.nanoseconds();try{await C.post("Profiler.enable"),await C.post("Profiler.setSamplingInterval",{interval:c}),await C.post("Profiler.start");let I=await o(),{profile:N}=await C.post("Profiler.stop"),P=Bun.nanoseconds()-p,U=oe(N,"inspector",c);return{result:I,cpu:U,diagnosticWallNs:P}}finally{C.disconnect()}}import{profile as Ve}from"bun:jsc";var ze=new Map([["LLInt","llint"],["Baseline","baseline"],["DFG","dfg"],["FTL","ftl"]]),be=4294967295;function ye(o,D){let c=D??o.interval*1e6,C=new Map,p=[];function I(F,L,K,G){let q=C.get(F);if(q===void 0)q=new Map,C.set(F,q);let Y=L??"",X=q.get(Y);if(X===void 0)X=p.length,q.set(Y,X),p.push({key:e("fr",F,Y),name:F,url:L,line:K,col:G});return X}function N(F){let L=F.line===be,K=L?void 0:F.line-1,G=L||F.column===be?void 0:F.column-1;return I(F.name,F.sourceURL,K,G)}let P=I("(root)",void 0,void 0,void 0),U=1,B={id:0,frameIx:P,children:new Map,selfUs:0,samples:0,totalUs:0},M=new Map([[0,B]]),S={llint:0,baseline:0,dfg:0,ftl:0},E=new Map,V=[],z=[];for(let F of o.traces){let L=F.frames,K=B;for(let Y=L.length-1;Y>=0;Y--){let X=N(L[Y]),ne=K.children.get(X);if(!ne)ne={id:U++,frameIx:X,children:new Map,selfUs:0,samples:0,totalUs:0},K.children.set(X,ne),M.set(ne.id,ne);K=ne}K.selfUs+=c,K.samples+=1,V.push(K.id),z.push(c);let G=L[0],q=G&&ze.get(G.category);if(q){S[q]++;let Y=E.get(q)??new Map;Y.set(K.frameIx,(Y.get(K.frameIx)??0)+1),E.set(q,Y)}}function A(F){let L=F.selfUs;for(let K of F.children.values())L+=A(K);return F.totalUs=L,L}A(B);let H=new Map;function _(F){let L=H.get(F.frameIx);if(L)L.selfUs+=F.selfUs,L.totalUs+=F.totalUs,L.samples+=F.samples;else H.set(F.frameIx,{frameIx:F.frameIx,selfUs:F.selfUs,totalUs:F.totalUs,samples:F.samples});for(let K of F.children.values())_(K)}_(B);let J=[...M.values()].map((F)=>({id:F.id,frameIx:F.frameIx,children:[...F.children.values()].map((L)=>L.id)})),j={origin:"jsc-profile",samplingIntervalUs:c,frames:p,nodes:J,totals:[...H.values()].sort((F,L)=>L.selfUs-F.selfUs),samples:{nodeIds:V,timeDeltasUs:z}},O=[...E.entries()].flatMap(([F,L])=>[...L.entries()].sort((K,G)=>G[1]-K[1]).slice(0,3).map(([K,G])=>({tier:F,frameKey:p[K].key,samples:G})));return{cpu:j,jit:{origin:"jsc-profile",tiers:S,topFramesByTier:O}}}var Ke=1000;async function we(o,D={}){let c=D.intervalUs??Ke,C,p=Bun.nanoseconds(),I=await Ve(async()=>(C=await o(),C),c),N=Bun.nanoseconds()-p,{cpu:P,jit:U}=ye(I.stackTraces,c);return{result:C,cpu:P,jit:U,diagnosticWallNs:N}}async function ue(o){let D=Bun.nanoseconds(),c=Bun.spawn(o.argv,{cwd:o.cwd,env:o.env,stdout:"ignore",stderr:"ignore",stdin:"ignore"}),C=await c.exited,p=Bun.nanoseconds(),I=c.resourceUsage?.();return{wallNs:p-D,exitCode:C,userNs:I?Number(I.cpuTime.user)*1000:void 0,systemNs:I?Number(I.cpuTime.system)*1000:void 0,maxRssBytes:I?.maxRSS}}function xe(o){return o.trim().split(/\s+/).filter(Boolean)}var Ge=10,Ye=3000000000,qe=3;async function g(o){let D=o.warmup??qe;for(let M=0;M<D;M++)await ue(o);let c=[],C=o.runs??o.minRuns??Ge,p=o.runs!==void 0?0:o.minTotalNs??Ye,I=0,N=0;while(N<C||I<p){let M=await ue(o);if(c.push({i:N,wallNs:M.wallNs,exitCode:M.exitCode,userNs:M.userNs,systemNs:M.systemNs,maxRssBytes:M.maxRssBytes}),I+=M.wallNs,N++,o.runs!==void 0&&N>=o.runs)break}let P=c.map((M)=>M.wallNs),U=l(P),B=m(U,c.map((M)=>M.exitCode));return{trials:c,timing:U,warnings:B}}var Re=new URL("./runner.ts",import.meta.url).pathname,Qe="node_modules/.cache/ostia";function x(){return Math.max(1,navigator.hardwareConcurrency||1)}async function d(o){let c=`${o.outDir??Qe}/bench-tmp`,C=o.cwd??process.cwd(),p=Math.max(1,Math.floor(o.jobs??1)),I={timeBudgetMs:o.timeBudgetMs,minSamples:o.minSamples,gc:o.gc},N=o.suites.map((U)=>U.startsWith("/")?U:`${C}/${U}`),P=async(U,B)=>{let M=new Set,S=0,E,V=async()=>{while(E===void 0&&S<U.length){let z=S++;try{let A=Bun.spawn(U[z],{cwd:C,stdout:"inherit",stderr:"inherit",stdin:"ignore"});M.add(A);let H=await A.exited;if(M.delete(A),H!==0)throw Error(`Bench suite failed: ${B(z)} (runner exited ${H})`)}catch(A){E??=A instanceof Error?A:Error(String(A));for(let H of M)H.kill()}}};if(await Promise.all(Array.from({length:Math.min(p,U.length)},V)),E)throw E};try{let U=N.map((_)=>`${c}/${e("bench-plan",_)}.json`),B=N.map((_,J)=>["bun",Re,_,U[J],JSON.stringify({...I,filter:o.filter,isolate:o.isolate,planOnly:!0})]);await P(B,(_)=>o.suites[_]);let M=await Promise.all(U.map(async(_)=>{let{tasks:J}=await Bun.file(_).json();return J})),S=[];for(let _=0;_<M.length;_++){let J=M[_].filter((j)=>!j.isolate).map((j)=>j.id);if(J.length>0)S.push({suiteIndex:_,taskIds:J,markIsolated:!1});for(let j of M[_])if(j.isolate)S.push({suiteIndex:_,taskIds:[j.id],markIsolated:!0})}let E=S.map((_,J)=>`${c}/${e("bench-item",N[_.suiteIndex],J)}.json`),V=S.map((_,J)=>["bun",Re,N[_.suiteIndex],E[J],JSON.stringify({...I,taskIds:_.taskIds,..._.markIsolated&&{markIsolated:!0}})]);await P(V,(_)=>o.suites[S[_].suiteIndex]);let z=await Promise.all(E.map(t)),A=[],H=[];for(let _=0;_<M.length;_++){let J=S.findIndex((F)=>F.suiteIndex===_&&!F.markIsolated),j=J>=0?z[J]:void 0,O=0,W=new Map;S.forEach((F,L)=>{if(F.suiteIndex===_&&F.markIsolated)W.set(F.taskIds[0],z[L])});for(let F of M[_])if(F.isolate){let L=W.get(F.id);A.push(L.workloads[0]),H.push(L.runs[0])}else A.push(j.workloads[O]),H.push(j.runs[O]),O++}return r(A,H)}finally{await Bun.spawn(["rm","-rf",c]).exited}}var a={timingPct:5,frameSelfPct:10,heapTypePct:10,minFrameSelfUs:1000};function ie(o,D){if(o===0)return D===0?0:1/0;return(D-o)/o*100}function te(o,D,c){return o.runs.find((C)=>C.workloadId===D&&C.phase===c)}function f(o,D,c=a){let C=new Set(D.workloads.map((I)=>I.id)),p=[];for(let I of o.workloads){if(!C.has(I.id))continue;let N=w(o,D,I.id,c);if(N)p.push(N)}return p}function w(o,D,c,C=a){let p=te(o,c,"timing"),I=te(D,c,"timing"),N=te(o,c,"cpu"),P=te(D,c,"cpu"),U=te(o,c,"heap"),B=te(D,c,"heap"),M=p?.id??N?.id??U?.id,S=I?.id??P?.id??B?.id;if(!M||!S)return;let E=!1,V;if(p?.timing&&I?.timing){let H=ie(p.timing.median,I.timing.median),_=ie(p.timing.mean,I.timing.mean),J=H>C.timingPct?"regressed":H<-C.timingPct?"improved":"unchanged";if(J==="regressed")E=!0;V={medianDeltaPct:H,meanDeltaPct:_,verdict:J}}let z;if(N?.cpu&&P?.cpu){let H=new Map(N.cpu.totals.map((W)=>[N.cpu.frames[W.frameIx].key,W])),_=new Map(P.cpu.totals.map((W)=>[P.cpu.frames[W.frameIx].key,W])),J=new Map(N.cpu.frames.map((W)=>[W.key,W.name])),j=new Map(P.cpu.frames.map((W)=>[W.key,W.name]));z=[...new Set([...H.keys(),..._.keys()])].map((W)=>{let F=H.get(W)?.selfUs??0,L=_.get(W)?.selfUs??0;return{frameKey:W,name:j.get(W)??J.get(W)??W,baseSelfUs:F,candSelfUs:L,deltaPct:ie(F,L)}}).sort((W,F)=>Math.abs(F.deltaPct)-Math.abs(W.deltaPct));for(let W of z)if((W.baseSelfUs>=C.minFrameSelfUs||W.candSelfUs>=C.minFrameSelfUs)&&W.deltaPct>C.frameSelfPct)E=!0}let A;if(U?.heap&&B?.heap){let H=new Map(U.heap.typeCounts.map((j)=>[j.type,j])),_=new Map(B.heap.typeCounts.map((j)=>[j.type,j]));A=[...new Set([...H.keys(),..._.keys()])].map((j)=>{let O=H.get(j),W=_.get(j);return{type:j,baseCount:O?.count??0,candCount:W?.count??0,baseBytes:O?.retainedBytes,candBytes:W?.retainedBytes,deltaPct:ie(O?.count??0,W?.count??0)}}).sort((j,O)=>Math.abs(O.deltaPct)-Math.abs(j.deltaPct));for(let j of A)if(j.deltaPct>C.heapTypePct)E=!0}return{id:e("cmp",M,S),baselineRunId:M,candidateRunId:S,timing:V,frames:z,heapTypes:A,thresholds:C,verdict:E?"fail":"pass"}}function Z(o,D){if(D){let c=o.runs.find((C)=>C.id===D);return c?.cpu?[c]:[]}return o.runs.filter((c)=>c.phase==="cpu"&&c.cpu)}function re(o){let D=o.nodes,c=D.length,C=Xe(o),p=new Int32Array(c).fill(-1);for(let U=0;U<c;U++)for(let B of D[U].children){let M=C(B);if(M!==-1)p[M]=U}let I=[];for(let U=0;U<c;U++)if(p[U]===-1)I.push(U);let N=[],P=[];for(let U=I.length-1;U>=0;U--)P.push(I[U]);while(P.length>0){let U=P.pop();N.push(U);for(let B of D[U].children){let M=C(B);if(M!==-1&&p[M]===U)P.push(M)}}return{count:c,indexOf:C,parentIx:p,roots:I,order:N}}function Xe(o){let D=o.nodes,c=D.length,C=1/0,p=-1/0,I=!0;for(let P=0;P<c;P++){let U=D[P].id;if(!Number.isInteger(U)){I=!1;break}if(U<C)C=U;if(U>p)p=U}if(I&&c>0&&p-C<c*4+64){let P=p-C+1,U=new Int32Array(P).fill(-1);for(let B=0;B<c;B++)U[D[B].id-C]=B;return(B)=>{let M=B-C;return M>=0&&M<P?U[M]:-1}}let N=new Map;for(let P=0;P<c;P++)N.set(D[P].id,P);return(P)=>N.get(P)??-1}function Pe(o,D){let{count:c,indexOf:C,parentIx:p,order:I}=D,N=new Float64Array(c),P=new Float64Array(c),U=o.samples?.nodeIds??[],B=o.samples?.timeDeltasUs??[];for(let S=0;S<U.length;S++){let E=C(U[S]);if(E===-1)continue;N[E]+=B[S]??0,P[E]+=1}let M=new Float64Array(c);for(let S=I.length-1;S>=0;S--){let E=I[S];M[E]+=N[E];let V=p[E];if(V>=0)M[V]+=M[E]}return{selfUs:N,totalUs:M,samples:P}}var ke={name:"collapsed",async render(o,D={}){return{files:Z(o,D.runId).map((p)=>{let I=p.cpu,{nodes:N,frames:P}=I,U=re(I),B=Array(U.count);for(let z of U.order){let A=P[N[z].frameIx].name||"(anonymous)",H=U.parentIx[z];B[z]=H===-1?A:`${B[H]};${A}`}let M=new Float64Array(U.count),S=[],E=I.samples?.nodeIds??[];for(let z=0;z<E.length;z++){let A=U.indexOf(E[z]);if(A===-1)continue;if(M[A]++===0)S.push(A)}let V=Array(S.length);for(let z=0;z<S.length;z++){let A=S[z];V[z]=`${B[A]} ${M[A]}`}return{path:`${p.id}.collapsed.txt`,content:V.join(`
3
- `)+(V.length>0?`
4
- `:"")}})}}};var Te={name:"cpuprofile",async render(o,D={}){let c=Z(o,D.runId),C=[],p=[];for(let I of c){if(I.cpu?.origin!=="cpu-prof"&&I.cpu?.origin!=="inspector"){p.push(`${I.id} (origin ${I.cpu?.origin??"unknown"} has no .cpuprofile artifact to pass through)`);continue}let N=I.artifacts.find((U)=>U.kind==="cpuprofile");if(!N){p.push(`${I.id} (no cpuprofile artifact recorded on this run)`);continue}let P=Bun.file(N.path);if(!await P.exists()){p.push(`${I.id} (artifact missing on disk: ${N.path})`);continue}C.push({path:`${I.id}.cpuprofile`,content:await P.text()})}if(C.length===0&&p.length>0)return{text:`No .cpuprofile artifacts available:
5
- ${p.map((I)=>` - ${I}`).join(`
6
- `)}
7
- `};return{files:C}}};var Ie={name:"json",async render(o){return{text:k(o)}}};var $e={name:"jsonl",async render(o){let{runs:D,...c}=o;return{text:`${[h(c),...D.map((p)=>h(p))].join(`
8
- `)}
9
- `}}};function ee(o){return(o/1e6).toFixed(3)}function ae(o){return o?.label??o?.command?.join(" ")??o?.entry?.task??o?.id??"unknown"}var ve=10,Ce=10,Ne={name:"markdown",async render(o){let D=new Map(o.workloads.map((p)=>[p.id,p])),c=[];c.push("# Profile Report",""),c.push(`Bun ${o.bunVersion} \xB7 ostia ${o.toolVersion} \xB7 ${o.platform.os}/${o.platform.arch} \xB7 ${o.createdAt}`,"");let C=o.runs.filter((p)=>p.phase==="timing"&&p.timing!==void 0);if(C.length>0){c.push("## Timing",""),c.push("| Command | Mean \xB1 SD (ms) | Min\u2026Max (ms) | Median (ms) |","|---|---|---|---|");for(let I of C){let N=ae(D.get(I.workloadId)),P=I.timing;c.push(`| ${N} | ${ee(P.mean)} \xB1 ${ee(P.stddev)} | ${ee(P.min)}\u2026${ee(P.max)} | ${ee(P.median)} |`)}c.push("");let p=C.filter((I)=>I.warnings.length>0);if(p.length>0){c.push("### Warnings","");for(let I of p){let N=ae(D.get(I.workloadId));for(let P of I.warnings)c.push(`- **${N}**: ${P.message} (\`${P.code}\`)`)}c.push("")}}for(let p of o.runs){if(p.phase!=="cpu"&&p.phase!=="heap")continue;let I=ae(D.get(p.workloadId));if(p.phase==="cpu"){if(c.push(`## CPU capture - ${I}`,""),c.push(`instrumented, diagnostic wall ${ee(p.diagnosticWallNs??0)}ms`,""),p.cpu){c.push(`origin: \`${p.cpu.origin}\`, interval: ${p.cpu.samplingIntervalUs}\xB5s`,""),c.push("| Self % | Self (ms) | Total (ms) | Frame |","|---|---|---|---|");let N=p.cpu.totals.reduce((P,U)=>P+U.selfUs,0)||1;for(let P of p.cpu.totals.slice(0,ve)){let U=p.cpu.frames[P.frameIx],B=(P.selfUs/N*100).toFixed(1);c.push(`| ${B}% | ${(P.selfUs/1000).toFixed(2)} | ${(P.totalUs/1000).toFixed(2)} | ${U?.name||"(anonymous)"} |`)}if(c.push(""),p.jit){let P=p.jit.tiers;c.push(`JIT tiers: LLInt ${P.llint} \xB7 Baseline ${P.baseline} \xB7 DFG ${P.dfg} \xB7 FTL ${P.ftl}`,"")}}}else if(c.push(`## Heap snapshot - ${I}`,""),c.push(`instrumented, diagnostic wall ${ee(p.diagnosticWallNs??0)}ms`,""),p.heap){c.push(`${p.heap.objectCount??"?"} objects, ${((p.heap.heapSizeBytes??0)/1e6).toFixed(2)}MB`,""),c.push("| Count | Type |","|---|---|");for(let N of p.heap.typeCounts.slice(0,Ce))c.push(`| ${N.count} | ${N.type} |`);c.push("")}for(let N of p.artifacts)c.push(`- artifact: \`${N.path}\``);for(let N of p.warnings)c.push(`- ! ${N.message} (\`${N.code}\`)`);if(p.artifacts.length>0||p.warnings.length>0)c.push("")}if(o.comparisons&&o.comparisons.length>0){c.push("## Comparisons","");for(let p of o.comparisons){let I=o.runs.find((P)=>P.id===p.candidateRunId),N=ae(I?D.get(I.workloadId):void 0);if(c.push(`### ${p.verdict==="pass"?"\u2713":"\u2717"} ${N}`,""),p.timing){let P=p.timing.medianDeltaPct>0?"+":"";c.push(`- timing: ${P}${p.timing.medianDeltaPct.toFixed(1)}% median (**${p.timing.verdict}**)`)}for(let P of p.frames?.slice(0,ve)??[]){if(Math.abs(P.deltaPct)<0.5)continue;let U=P.deltaPct>0?"+":"";c.push(`- frame \`${P.name}\`: ${U}${P.deltaPct.toFixed(1)}% self-time (${(P.baseSelfUs/1000).toFixed(2)}ms \u2192 ${(P.candSelfUs/1000).toFixed(2)}ms)`)}for(let P of p.heapTypes?.slice(0,Ce)??[]){if(Math.abs(P.deltaPct)<0.5)continue;let U=P.deltaPct>0?"+":"";c.push(`- heap \`${P.type}\`: ${U}${P.deltaPct.toFixed(1)}% count (${P.baseCount} \u2192 ${P.candCount})`)}c.push("")}}return{text:c.join(`
10
- `)}}};var Ze=15;function le(o){return`n${o}`}function en(o,D,c){return`${(o||"(anonymous)").replace(/"/g,"'")} (self ${(D/1000).toFixed(2)}ms, total ${(c/1000).toFixed(2)}ms)`}function nn(o,D,c,C){let p=[];if(C<=0)return p;for(let I=0;I<D;I++){if(I===c)continue;let N=o[I];if(p.length===C&&N<=o[p[C-1]])continue;let P=p.length;while(P>0&&o[p[P-1]]<N)P--;if(p.splice(P,0,I),p.length>C)p.pop()}return p}var Ue={name:"mermaid",async render(o,D={}){let c=D.topN??Ze;return{files:Z(o,D.runId).map((I)=>{let N=I.cpu,{nodes:P,frames:U}=N,B=re(N),{selfUs:M,totalUs:S}=Pe(N,B),{parentIx:E}=B,V=B.roots[0]??-1,z=nn(M,B.count,V,c),A=new Set(V!==-1?[V]:[]),H=[];for(let J of z){H.length=0;for(let j=J;j!==-1;j=E[j])H.push(j);for(let j=H.length-1;j>=0;j--)A.add(H[j])}let _=["graph TD"];for(let J of A){let j=P[J].id;_.push(` ${le(j)}["${en(U[P[J].frameIx].name,M[J],S[J])}"]`)}for(let J of A){let j=E[J];if(j!==-1&&A.has(j))_.push(` ${le(P[j].id)} --> ${le(P[J].id)}`)}return{path:`${I.id}.mermaid.md`,content:`${_.join(`
11
- `)}
12
- `}})}}};function De(o){if(!o?.entry)return;if(o.entry.group!==void 0)return o.entry.group;let D=o.entry.task,c=D.lastIndexOf("/");return c===-1?void 0:D.slice(0,c)}function ce(o){let D=Math.min(...o.map((p)=>p.run.timing.median)),c=new Map;for(let p of o){let I=De(p.workload);if(I===void 0)continue;let N=c.get(I);if(N)N.push(p);else c.set(I,[p])}let C=new Map;for(let p of o){let I=De(p.workload);if(I===void 0){C.set(p,D);continue}let N=c.get(I)??[p],P=N.find((U)=>U.workload?.baseline);C.set(p,P?P.run.timing.median:Math.min(...N.map((U)=>U.run.timing.median)))}return C}function Q(o){return Number.isFinite(o)?Number(o.toPrecision(6)):o}function tn(o,D){return o?.entry?.task??o?.label??o?.command?.join(" ")??D.workloadId}function rn(o){let D=new Map(o.workloads.map((I)=>[I.id,I])),c=o.runs.filter((I)=>I.phase==="timing"&&I.timing!==void 0).map((I)=>({run:I,workload:D.get(I.workloadId)})),C=c.length>1?ce(c):void 0,p=new Map((o.comparisons??[]).map((I)=>[I.candidateRunId,I]));return c.map((I)=>{let{run:N,workload:P}=I,U=N.timing,B={task:tn(P,N),unit:"ns",samples:U.samples.length,mean:Q(U.mean),median:Q(U.median),stddev:Q(U.stddev),stddevPct:Q(U.mean===0?0:U.stddev/U.mean*100),min:Q(U.min),max:Q(U.max),warnings:N.warnings.map((S)=>S.data?{code:S.code,data:S.data}:{code:S.code})};if(P?.entry?.group!==void 0)B.group=P.entry.group;if(P?.description!==void 0)B.description=P.description;if(P?.groupDescription!==void 0)B.groupDescription=P.groupDescription;if(C)B.relative=Q(U.median/(C.get(I)??U.median));if(P?.baseline)B.baseline=!0;let M=p.get(N.id);if(M?.timing)B.delta={medianPct:Q(M.timing.medianDeltaPct),meanPct:Q(M.timing.meanDeltaPct),verdict:M.timing.verdict,pass:M.verdict==="pass"};return B})}var Fe={name:"minimal",async render(o){let D=rn(o).map((c)=>JSON.stringify(c));return{text:D.length>0?`${D.join(`
13
- `)}
14
- `:""}}};var sn="https://www.speedscope.app/file-format-schema.json";function Me(o){return o?.label??o?.command?.join(" ")??o?.entry?.task??"profile"}var Se={name:"speedscope",async render(o,D={}){let c=Z(o,D.runId),C=new Map(o.workloads.map((I)=>[I.id,I]));return{files:c.map((I)=>{let N=I.cpu,{nodes:P}=N,U=re(N),B=N.samples?.nodeIds??[],M=N.samples?.timeDeltasUs??[],S=Array(U.count);for(let A of U.order){let H=U.parentIx[A],_=P[A].frameIx;S[A]=H===-1?[_]:[...S[H],_]}let E=Array(B.length);for(let A=0;A<B.length;A++){let H=U.indexOf(B[A]);E[A]=H===-1?[]:S[H]}let V=0;for(let A=0;A<M.length;A++)V+=M[A];let z={$schema:sn,exporter:"ostia",name:Me(C.get(I.workloadId)),activeProfileIndex:0,shared:{frames:N.frames.map((A)=>({name:A.name||"(anonymous)",file:A.url,line:A.line!==void 0?A.line+1:void 0}))},profiles:[{type:"sampled",name:Me(C.get(I.workloadId)),unit:"microseconds",startValue:0,endValue:V,samples:E,weights:M}]};return{path:`${I.id}.speedscope.json`,content:`${JSON.stringify(z,null,2)}
15
- `}})}}};function se(o){return(o/1e6).toFixed(3)}function pe(o){return o.label??o.command?.join(" ")??o.entry?.task??o.id}var Oe={name:"table",async render(o){let D=o.runs.filter((S)=>S.phase==="timing"&&S.timing!==void 0),c=new Map(o.workloads.map((S)=>[S.id,S]));if(D.length===0){let S=Be(o,c);return{text:S.length>0?`${S.join(`
16
- `)}
17
- `:`(no timing runs)
18
- `}}let C=D.map((S)=>{let E=c.get(S.workloadId);return{run:S,workload:E,label:E?pe(E):S.workloadId}}),p=C.length>1,I=ce(C),N=[],P=Math.max(7,...C.map((S)=>S.label.length)),U=p?`${"Command".padEnd(P)} Mean [ms] Min\u2026Max [ms] Relative`:`${"Command".padEnd(P)} Mean [ms] Min\u2026Max [ms]`;N.push(U),N.push("-".repeat(U.length));for(let S of C){let{run:E,label:V,workload:z}=S,A=E.timing,H=`${se(A.mean)} \xB1 ${se(A.stddev)}`,_=`${se(A.min)}\u2026${se(A.max)}`,J=`${V.padEnd(P)} ${H.padEnd(15)} ${_.padEnd(18)}`;if(p){let j=A.median/(I.get(S)??A.median);if(j===1)J+=z?.baseline?" 1.00\xD7 (baseline)":" 1.00\xD7";else if(j>1)J+=` ${j.toFixed(2)}\xD7 slower`;else J+=` ${(1/j).toFixed(2)}\xD7 faster`}N.push(J);for(let j of E.warnings)N.push(` ! ${j.message}`)}let B=an(o,c);if(B.length>0)N.push(""),N.push(...B);let M=Be(o,c);if(M.length>0)N.push(""),N.push(...M);return{text:`${N.join(`
19
- `)}
20
- `}}};function on(o,D,c){let C=o.runs.find((I)=>I.id===c),p=C?D.get(C.workloadId):void 0;return p?pe(p):c}function Be(o,D){if(!o.comparisons||o.comparisons.length===0)return[];let c=[];for(let C of o.comparisons){let p=on(o,D,C.candidateRunId),I=C.verdict==="pass"?"\u2713":"\u2717";if(c.push(`${I} ${p}`),C.timing){let N=C.timing.medianDeltaPct>0?"+":"";c.push(` timing: ${N}${C.timing.medianDeltaPct.toFixed(1)}% median (${C.timing.verdict})`)}if(C.frames)for(let N of C.frames.slice(0,We)){if(Math.abs(N.deltaPct)<0.5)continue;let P=N.deltaPct>0?"+":"";c.push(` frame ${N.name}: ${P}${N.deltaPct.toFixed(1)}% self-time (${(N.baseSelfUs/1000).toFixed(2)}ms -> ${(N.candSelfUs/1000).toFixed(2)}ms)`)}if(C.heapTypes)for(let N of C.heapTypes.slice(0,Ee)){if(Math.abs(N.deltaPct)<0.5)continue;let P=N.deltaPct>0?"+":"";c.push(` heap ${N.type}: ${P}${N.deltaPct.toFixed(1)}% count (${N.baseCount} -> ${N.candCount})`)}}return c}var We=5,Ee=5;function an(o,D){let c=[];for(let C of o.runs){if(C.phase!=="cpu"&&C.phase!=="heap")continue;let p=D.get(C.workloadId),I=p?pe(p):C.workloadId;if(C.phase==="cpu")if(C.cpu){c.push(`CPU capture - ${I} (instrumented, ${C.cpu.samplingIntervalUs}\xB5s interval, diagnostic wall ${se(C.diagnosticWallNs??0)}ms)`);let N=C.cpu.totals.reduce((P,U)=>P+U.selfUs,0)||1;for(let P of C.cpu.totals.slice(0,We)){let U=C.cpu.frames[P.frameIx],B=(P.selfUs/N*100).toFixed(1);c.push(` ${B.padStart(5)}% ${(P.selfUs/1000).toFixed(2).padStart(8)}ms self ${U?.name??"?"}`)}}else c.push(`CPU capture - ${I} (instrumented, no evidence captured)`);else if(C.heap){let N=((C.heap.heapSizeBytes??0)/1e6).toFixed(2);c.push(`Heap snapshot - ${I} (instrumented, ${C.heap.objectCount??"?"} objects, ${N}MB)`);for(let P of C.heap.typeCounts.slice(0,Ee))c.push(` ${String(P.count).padStart(6)} ${P.type}`)}else c.push(`Heap snapshot - ${I} (instrumented, no evidence captured)`);for(let N of C.artifacts)c.push(` artifact: ${N.path}`);for(let N of C.warnings)c.push(` ! ${N.message}`)}return c}var n={table:Oe,json:Ie,markdown:Ne,jsonl:$e,minimal:Fe,collapsed:ke,mermaid:Ue,speedscope:Se,cpuprofile:Te};var cn="node_modules/.cache/ostia",me=1000;async function y(o){let D=s({runs:o.runs??null,warmup:o.warmup??null,cpu:o.cpu??!1,heap:o.heap??!1,cpuIntervalUs:o.cpuIntervalUs??me}),C=`${o.outDir??cn}/artifacts`,p=[],I=[];for(let N of o.commands){let P=Array.isArray(N)?N:xe(N),U=u(P,Array.isArray(N)?void 0:N);p.push(U);let B=await g({argv:P,cwd:o.cwd,env:o.env,runs:o.runs,warmup:o.warmup}),M=i({workload:U,configFingerprint:D,trials:B.trials,timing:B.timing,warnings:B.warnings});if(I.push(M),o.cpu){let S=`${M.id}-cpu.cpuprofile`,E=await de({argv:P,cwd:o.cwd,env:o.env,artifactDir:C,fileName:S,intervalUs:o.cpuIntervalUs??me});I.push(await Ae({workload:U,phase:"cpu",configFingerprint:D,diagnosticWallNs:E.diagnosticWallNs,exitCode:E.exitCode,cpu:E.cpu,artifactPath:E.artifactPath,artifactKind:"cpuprofile",warnings:E.warnings}))}if(o.heap){let S=`${M.id}-heap.heapsnapshot`,E=await ge({argv:P,cwd:o.cwd,env:o.env,artifactDir:C,fileName:S});I.push(await Ae({workload:U,phase:"heap",configFingerprint:D,diagnosticWallNs:E.diagnosticWallNs,exitCode:E.exitCode,heap:E.heap,artifactPath:E.artifactPath,artifactKind:"heapsnapshot",warnings:E.warnings}))}}return r(p,I)}async function Ae(o){let D=`${o.workload.id}-${o.phase}-${o.configFingerprint}`,c=o.artifactPath?[await T(D,o.artifactKind,o.artifactPath)]:[];return b({workload:o.workload,phase:o.phase,configFingerprint:o.configFingerprint,diagnosticWallNs:o.diagnosticWallNs,exitCode:o.exitCode,cpu:o.cpu,heap:o.heap,warnings:o.warnings,artifacts:c})}async function v(o,D={}){let c=R(o),C=s({intervalUs:D.intervalUs??me,origin:D.origin??"inspector"}),p=(B)=>B.samples?.nodeIds.length===0?[{code:"empty-profile",message:"In-process capture produced zero samples."}]:[];if(D.origin==="jsc"){let{result:B,cpu:M,jit:S,diagnosticWallNs:E}=await we(o,D),V=b({workload:c,phase:"cpu",configFingerprint:C,diagnosticWallNs:E,cpu:M,jit:S,warnings:p(M),artifacts:[]});return{result:B,run:V}}let{result:I,cpu:N,diagnosticWallNs:P}=await he(o,D),U=b({workload:c,phase:"cpu",configFingerprint:C,diagnosticWallNs:P,cpu:N,warnings:p(N),artifacts:[]});return{result:I,run:U}}
21
- export{x,d,a,f,w,g,n,y,v};
package/chunk-y1gkhb0y.js DELETED
@@ -1,4 +0,0 @@
1
- // @bun
2
- function h(n){return JSON.stringify(O(n))}function O(n){if(Array.isArray(n))return n.map(O);if(n!==null&&typeof n==="object"){let a={};for(let d of Object.keys(n).sort())a[d]=O(n[d]);return a}return n}function e(n,...a){let d=Bun.CryptoHasher.hash("sha256",h(a),"hex");return`${n}_${d.slice(0,16)}`}var c="0.1.0";function r(n,a){return{schemaVersion:1,toolVersion:c,bunVersion:Bun.version,platform:{os:process.platform,arch:process.arch},createdAt:new Date().toISOString(),workloads:n,runs:a}}function u(n,a){return{id:e("wl","subprocess",n,process.cwd()),kind:"subprocess",command:n,label:a}}function R(n,a){return{id:e("wl","inprocess",n.name,n.toString()),kind:"inprocess",label:a}}function P(n,a,d={}){return{id:e("wl","inprocess-entry",n,a),kind:"inprocess",entry:{file:n,task:a,...d.group!==void 0&&{group:d.group}},...d.label!==void 0&&{label:d.label},...d.baseline!==void 0&&{baseline:d.baseline},...d.description!==void 0&&{description:d.description},...d.groupDescription!==void 0&&{groupDescription:d.groupDescription},...d.isolated!==void 0&&{isolated:d.isolated}}}function i(n){return{id:e("run",n.workload.id,"timing",n.configFingerprint,Bun.version,c),workloadId:n.workload.id,phase:"timing",instrumented:!1,configFingerprint:n.configFingerprint,trials:n.trials,timing:n.timing,warnings:n.warnings,artifacts:[],memory:Z(n.trials)}}function Z(n){let a=n.map((d)=>d.maxRssBytes).filter((d)=>d!==void 0);if(a.length===0)return;return{origin:"resourceUsage",perTrial:n.map((d)=>({rssBytes:d.maxRssBytes})),maxRssBytes:Math.max(...a)}}function b(n){return{id:e("run",n.workload.id,n.phase,n.configFingerprint,Bun.version,c),workloadId:n.workload.id,phase:n.phase,instrumented:!0,configFingerprint:n.configFingerprint,trials:[{i:0,wallNs:n.diagnosticWallNs,exitCode:n.exitCode}],diagnosticWallNs:n.diagnosticWallNs,cpu:n.cpu,heap:n.heap,jit:n.jit,warnings:n.warnings,artifacts:n.artifacts}}async function T(n,a,d){let f=await Bun.file(d).arrayBuffer(),w=new Bun.CryptoHasher("sha256");return w.update(f),{id:e("art",n,a,d),kind:a,path:d,sha256:w.digest("hex"),bytes:f.byteLength}}function s(n){return e("cfg",n)}function k(n){return`${JSON.stringify(O(n),null,2)}
3
- `}async function o(n,a){await Bun.write(a,k(n))}async function t(n){let a=await Bun.file(n).text();return JSON.parse(a)}var H=[],v;function F(n,a,d){let g=v;v={name:n,description:d?.description,isolate:d?.isolate};try{a()}finally{v=g}}function S(n,a,d){H.push({groupName:v?.name,groupDescription:v?.description,groupIsolate:v?.isolate,name:n,fn:a,baseline:d?.baseline,opts:d})}function I(){return H}function C(){H.length=0,v=void 0}function p(n){return n.groupName?`${n.groupName}/${n.name}`:n.name}function N(n,a){return n.opts?.isolate??n.groupIsolate??a}function D(n,a){if(!a)return[...n];let d=new RegExp(a);return n.filter((g)=>d.test(p(g)))}function l(n){if(n.length===0)throw Error("computeTimingStats: samples must be non-empty");let a=n.length,d=z(n),g=0;for(let y=0;y<a;y++)g+=n[y];let f=g/a,w=B(d,0.5),x=0;for(let y=0;y<a;y++){let W=n[y]-f;x+=W*W}let A=Math.sqrt(x/a),J=d[0],E=d[a-1],q=B(d,0.25),_=B(d,0.75),M=_-q,V=q-1.5*M,G=_+1.5*M,K=q-3*M,U=_+3*M,j=0,L=0;for(let y=0;y<a;y++){let W=n[y];if(W<K||W>U)L++;else if(W<V||W>G)j++}return{unit:"ns",samples:n,mean:f,median:w,stddev:A,min:J,max:E,outliers:{mild:j,severe:L}}}function z(n){let a=new Float64Array(n.length);return a.set(n),a.sort(),a}function B(n,a){let d=n.length;if(d===1)return n[0];let g=a*(d-1),f=Math.floor(g),w=Math.ceil(g);if(f===w)return n[f];let x=g-f;return n[f]*(1-x)+n[w]*x}var Q=5000000,X=200;function m(n,a,d="subprocess"){let g=[],f=n.samples[0];if(f!==void 0){let x=z(n.samples),A=B(x,0.25),E=B(x,0.75)-A;if(f>n.median+3*E&&E>0)g.push({code:"slow-first-run",message:`First run took ${(f/1e6).toFixed(2)}ms, much slower than the median ${(n.median/1e6).toFixed(2)}ms. Consider more warmup.`,data:{firstNs:f,medianNs:n.median}})}if(n.outliers.mild+n.outliers.severe>0)g.push({code:"outliers-detected",message:`${n.outliers.mild+n.outliers.severe} outlier(s) detected (${n.outliers.severe} severe, ${n.outliers.mild} mild).`,data:n.outliers});if(d==="subprocess"&&n.median<Q)g.push({code:"fast-command",message:`Median run time (${(n.median/1e6).toFixed(3)}ms) is very fast; results may be dominated by spawn overhead.`,data:{medianNs:n.median}});if(d==="inprocess"&&n.median<X)g.push({code:"below-timer-resolution",message:`Median run time (${n.median.toFixed(0)}ns) is close to timer resolution; consider a larger batch size or a coarser operation.`,data:{medianNs:n.median}});let w=a.filter((x)=>x!==void 0&&x!==0);if(w.length>0)g.push({code:"nonzero-exit",message:`${w.length} of ${a.length} trial(s) exited non-zero.`,data:{exitCodes:w}});return g}
4
- export{h,e,c,r,u,R,P,i,b,T,s,k,o,t,l,m,F,S,I,C,p,N,D};