ostia 0.1.1 → 0.1.2

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
@@ -34,7 +34,7 @@ Find a CPU hotspot (profiler runs as a separate labeled trial, never mixed into
34
34
  timing numbers above):
35
35
 
36
36
  ```sh
37
- ostia run --runs 5 --cpu --cpu-interval 200 --export-json .ostia/doc.json fixtures/work.ts
37
+ ostia run --runs 5 --cpu --cpu-interval 200 --export-json node_modules/.cache/ostia/doc.json fixtures/work.ts
38
38
  ```
39
39
 
40
40
  ```
@@ -45,10 +45,16 @@ bun fixtures/work.ts 275.815 ± 2.853 273.334…281.384
45
45
  CPU capture - bun fixtures/work.ts (instrumented, 200µs interval, diagnostic wall 297.578ms)
46
46
  100.0% 284.19ms self hashLoop
47
47
  0.0% 0.00ms self (root)
48
- artifact: .ostia/artifacts/<run-id>-cpu.cpuprofile
48
+ artifact: node_modules/.cache/ostia/artifacts/<run-id>-cpu.cpuprofile
49
49
  ```
50
50
 
51
- Gate a change against a local baseline (baselines are gitignored under `.ostia/`):
51
+ Scratch/artifact output defaults to `node_modules/.cache/ostia` (already gitignored
52
+ everywhere, no setup needed - same convention as Babel/ESLint/Jest caches). Baselines are
53
+ the one exception: they default to `.ostia/baselines/` at the repo root instead, since
54
+ they need to survive `node_modules` reinstalls between branches and CI jobs, so gitignore
55
+ `.ostia/` if you use `ostia ci`.
56
+
57
+ Gate a change against a local baseline:
52
58
 
53
59
  ```sh
54
60
  bun run baseline # on known-good: measure ostia.config.json -> .ostia/baselines/main.json
@@ -120,13 +126,16 @@ Heap snapshot - bun fixtures/allocate.ts (instrumented, 2518 objects, 0.12MB)
120
126
  321 closure
121
127
  216 object shape
122
128
  104 hidden
123
- artifact: .ostia/artifacts/<run-id>-heap.heapsnapshot
129
+ artifact: node_modules/.cache/ostia/artifacts/<run-id>-heap.heapsnapshot
124
130
  ```
125
131
 
126
132
  ### `ostia bench`
127
133
 
128
- In-process microbenchmarks registered with `group()` / `task()`. Time budget + min
129
- samples (mitata-shaped); batches when a call is too fast for `Bun.nanoseconds()`.
134
+ In-process microbenchmarks registered with `group()` / `task()`. Each task samples
135
+ for `--time-budget` (default 500ms). `--min-samples` is a hard floor kept even when it
136
+ overruns the budget; left unset, the floor is cost-aware (as many trials as fit in the
137
+ budget, clamped to 3..20) so one slow task can't blow the suite's total. Fast calls are
138
+ batched so a trial spans at least 1µs and a full budget yields about 10k trials at most.
130
139
 
131
140
  ```sh
132
141
  ostia bench bench/*.ts
@@ -189,9 +198,9 @@ Turn CPU evidence into files for other tools. Formats: `collapsed`, `mermaid`,
189
198
  `speedscope`, `cpuprofile` (pass-through of a real CDP artifact when present).
190
199
 
191
200
  ```sh
192
- ostia viz .ostia/doc.json --format collapsed
193
- ostia viz .ostia/doc.json --format mermaid
194
- ostia viz .ostia/doc.json --format speedscope > flame.json
201
+ ostia viz doc.json --format collapsed
202
+ ostia viz doc.json --format mermaid
203
+ ostia viz doc.json --format speedscope > flame.json
195
204
  ```
196
205
 
197
206
  Collapsed stacks (one line per stack; feeds `flamegraph.pl` and friends):
@@ -267,6 +276,10 @@ Exit codes: `0` pass, `1` regression, `2` harness error (missing config/baseline
267
276
 
268
277
  `inputs` is optional. Workloads with no `inputs` always rerun (cache fails conservative).
269
278
 
279
+ Two directory options, both optional: `outDir` (default `node_modules/.cache/ostia`) for
280
+ scratch/cache/artifacts, and `baselineDir` (default `.ostia/baselines`) for baselines. They're
281
+ independent - `baselineDir` doesn't move just because you override `outDir`.
282
+
270
283
  #### Baselines (local and CI)
271
284
 
272
285
  Baselines are JSON under `.ostia/baselines/` (gitignored). `ostia ci` only needs the file
@@ -329,7 +342,7 @@ const doc = await run({
329
342
  cpu: true,
330
343
  heap: false,
331
344
  cpuIntervalUs: 200,
332
- outDir: ".ostia",
345
+ outDir: "node_modules/.cache/ostia", // default; artifacts land under here
333
346
  })
334
347
  ```
335
348
 
@@ -365,6 +378,19 @@ import { group, task } from "ostia"
365
378
  group("parse", () => {
366
379
  task("small input", () => parse(smallBuf))
367
380
  task("large input", () => parse(largeBuf))
381
+ // Per-task options override the suite-wide time budget / min samples.
382
+ task("full pipeline", () => build(), { timeBudgetMs: 2000, minSamples: 10 })
383
+ })
384
+ ```
385
+
386
+ Mark one task per group as the `Relative` reference with `{ baseline: true }`
387
+ (mirrors mitata's `baseline()`); otherwise `Relative` defaults to the fastest
388
+ task in the group:
389
+
390
+ ```ts
391
+ group("parse", () => {
392
+ task("current impl", () => parse(buf), { baseline: true })
393
+ task("candidate impl", () => parseFast(buf))
368
394
  })
369
395
  ```
370
396
 
@@ -395,8 +421,8 @@ const diffs = compareDocuments(baselineDoc, candidateDoc, {
395
421
  ### `saveDocument` / `loadDocument`
396
422
 
397
423
  ```ts
398
- await saveDocument(doc, ".ostia/doc.json")
399
- const loaded: ProfileDocument = await loadDocument(".ostia/doc.json")
424
+ await saveDocument(doc, "doc.json")
425
+ const loaded: ProfileDocument = await loadDocument("doc.json")
400
426
  ```
401
427
 
402
428
  ### `renderers`
@@ -0,0 +1,19 @@
1
+ // @bun
2
+ import{g,e,r,u,k,i,h,P,s,y,t,l,p}from"./chunk-qh19pbhc.js";function Be(o){return o.startsWith("file://")?o.slice(7):o}function re(o,v,c){let T=o.nodes,x=T.length,C=new Map,N=[],R=new Map,U=new Int32Array(x);for(let D=0;D<x;D++){let M=T[D],F=M.callFrame,L=Be(F.url),J=C.get(F.functionName);if(J===void 0)J=new Map,C.set(F.functionName,J);let K=J.get(L);if(K===void 0)K=N.length,J.set(L,K),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[D]=K,R.set(M.id,D)}let B=Array(x);for(let D=0;D<x;D++){let M=T[D];B[D]={id:M.id,frameIx:U[R.get(M.id)],children:M.children??[]}}let S=new Float64Array(x),A=new Float64Array(x),{samples:O,timeDeltas:W}=o;for(let D=0;D<O.length;D++){let M=R.get(O[D]);if(M===void 0)continue;S[M]+=W[D]??0,A[M]+=1}let j=new Int32Array(x).fill(-1);for(let D=0;D<x;D++){let M=T[D].children;if(!M)continue;for(let F of M){let L=R.get(F);if(L!==void 0)j[L]=D}}let E=[],H=[];for(let D=x-1;D>=0;D--)if(j[D]===-1)H.push(D);while(H.length>0){let D=H.pop();E.push(D);let M=T[D].children;if(!M)continue;for(let F of M){let L=R.get(F);if(L!==void 0&&j[L]===D)H.push(L)}}let z=new Float64Array(x);for(let D=E.length-1;D>=0;D--){let M=E[D];z[M]+=S[M];let F=j[M];if(F>=0)z[F]+=z[M]}let V=Array(N.length),_=[];for(let D=0;D<x;D++){let M=B[D].frameIx,F=V[M];if(F)F.selfUs+=S[D],F.totalUs+=z[D],F.samples+=A[D];else{let L={frameIx:M,selfUs:S[D],totalUs:z[D],samples:A[D]};V[M]=L,_.push(L)}}return{origin:v,samplingIntervalUs:c,frames:N,nodes:B,totals:_.sort((D,M)=>M.selfUs-D.selfUs),samples:{nodeIds:o.samples,timeDeltasUs:o.timeDeltas}}}function Oe(o,v,c,T){let x=["--cpu-prof","--cpu-prof-dir",v,"--cpu-prof-name",c,"--cpu-prof-interval",String(T)],C=o[0];if(C==="bun"||C?.endsWith("/bun"))return[C,...x,...o.slice(1)];return o}async function pe(o){let v=`${o.artifactDir}/${o.fileName}`,c=o.argv[0],T=c==="bun"||c?.endsWith("/bun"),x=Oe(o.argv,o.artifactDir,o.fileName,o.intervalUs),C=T?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(x,{cwd:o.cwd,env:C,stdout:"ignore",stderr:"ignore",stdin:"ignore"}).exited,B=Bun.nanoseconds()-N,S=Bun.file(v);if(!await S.exists())return{diagnosticWallNs:B,exitCode:U,warnings:[{code:"artifact-missing",message:`Expected a .cpuprofile at ${v} after exit ${U}, found nothing. The workload's argv[0] must be a \`bun\` binary for CPU capture.`,data:{artifactPath:v,argv:o.argv}}]};let A=await S.json(),O=re(A,"cpu-prof",o.intervalUs),W=A.samples.length===0?[{code:"empty-profile",message:"CPU capture produced zero samples."}]:[];return{diagnosticWallNs:B,exitCode:U,artifactPath:v,cpu:O,warnings:W}}function le(o,v="heap-prof"){let{node_fields:c,node_types:T}=o.snapshot.meta,x=c.indexOf("type"),C=c.indexOf("self_size"),N=c.length,R=T[0];if(x===-1||C===-1||!Array.isArray(R))return{origin:v,typeCounts:[],objectCount:o.snapshot.node_count};let U=R.length,B=Array(U),S=new Map,A=[],O=0,W=o.nodes,j=W.length;for(let _=0;_<j;_+=N){let D=W[_+x],M=W[_+C]??0;O+=M;let F;if(D>=0&&D<U){if(F=B[D],F===void 0)F={type:R[D],count:0,bytes:0},B[D]=F,A.push(F)}else{let L=`unknown(${D})`;if(F=S.get(L),F===void 0)F={type:L,count:0,bytes:0},S.set(L,F),A.push(F)}F.count++,F.bytes+=M}let E=A.sort((_,D)=>D.count-_.count),H=E.slice(0,20),z=E.slice(20),V=H.map(({type:_,count:D,bytes:M})=>({type:_,count:D,retainedBytes:M}));if(z.length>0){let _=0,D=0;for(let M of z)_+=M.count,D+=M.bytes;V.push({type:"other",count:_,retainedBytes:D})}return{origin:v,heapSizeBytes:O,objectCount:o.snapshot.node_count,typeCounts:V}}function We(o,v,c){let T=["--heap-prof","--heap-prof-dir",v,"--heap-prof-name",c],x=o[0];if(x==="bun"||x?.endsWith("/bun"))return[x,...T,...o.slice(1)];return o}async function me(o){let v=`${o.artifactDir}/${o.fileName}`,c=o.argv[0],T=c==="bun"||c?.endsWith("/bun"),x=We(o.argv,o.artifactDir,o.fileName),C=T?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(x,{cwd:o.cwd,env:C,stdout:"ignore",stderr:"ignore",stdin:"ignore"}).exited,B=Bun.nanoseconds()-N,S=Bun.file(v);if(!await S.exists())return{diagnosticWallNs:B,exitCode:U,warnings:[{code:"artifact-missing",message:`Expected a heap snapshot at ${v} after exit ${U}, found nothing. The workload's argv[0] must be a \`bun\` binary for heap capture.`,data:{artifactPath:v,argv:o.argv}}]};let A=await S.json(),O=le(A,"heap-prof");return{diagnosticWallNs:B,exitCode:U,artifactPath:v,heap:O,warnings:[]}}import{Session as Ee}from"inspector/promises";var Ae=1000;async function fe(o,v={}){let c=v.intervalUs??Ae,T=new Ee;T.connect();let x=Bun.nanoseconds();try{await T.post("Profiler.enable"),await T.post("Profiler.setSamplingInterval",{interval:c}),await T.post("Profiler.start");let C=await o(),{profile:N}=await T.post("Profiler.stop"),R=Bun.nanoseconds()-x,U=re(N,"inspector",c);return{result:C,cpu:U,diagnosticWallNs:R}}finally{T.disconnect()}}import{profile as je}from"bun:jsc";var _e=new Map([["LLInt","llint"],["Baseline","baseline"],["DFG","dfg"],["FTL","ftl"]]),de=4294967295;function ge(o,v){let c=v??o.interval*1e6,T=new Map,x=[];function C(F,L,J,K){let Y=T.get(F);if(Y===void 0)Y=new Map,T.set(F,Y);let G=L??"",q=Y.get(G);if(q===void 0)q=x.length,Y.set(G,q),x.push({key:e("fr",F,G),name:F,url:L,line:J,col:K});return q}function N(F){let L=F.line===de,J=L?void 0:F.line-1,K=L||F.column===de?void 0:F.column-1;return C(F.name,F.sourceURL,J,K)}let R=C("(root)",void 0,void 0,void 0),U=1,B={id:0,frameIx:R,children:new Map,selfUs:0,samples:0,totalUs:0},S=new Map([[0,B]]),A={llint:0,baseline:0,dfg:0,ftl:0},O=new Map,W=[],j=[];for(let F of o.traces){let L=F.frames,J=B;for(let G=L.length-1;G>=0;G--){let q=N(L[G]),Z=J.children.get(q);if(!Z)Z={id:U++,frameIx:q,children:new Map,selfUs:0,samples:0,totalUs:0},J.children.set(q,Z),S.set(Z.id,Z);J=Z}J.selfUs+=c,J.samples+=1,W.push(J.id),j.push(c);let K=L[0],Y=K&&_e.get(K.category);if(Y){A[Y]++;let G=O.get(Y)??new Map;G.set(J.frameIx,(G.get(J.frameIx)??0)+1),O.set(Y,G)}}function E(F){let L=F.selfUs;for(let J of F.children.values())L+=E(J);return F.totalUs=L,L}E(B);let H=new Map;function z(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 J of F.children.values())z(J)}z(B);let V=[...S.values()].map((F)=>({id:F.id,frameIx:F.frameIx,children:[...F.children.values()].map((L)=>L.id)})),_={origin:"jsc-profile",samplingIntervalUs:c,frames:x,nodes:V,totals:[...H.values()].sort((F,L)=>L.selfUs-F.selfUs),samples:{nodeIds:W,timeDeltasUs:j}},D=[...O.entries()].flatMap(([F,L])=>[...L.entries()].sort((J,K)=>K[1]-J[1]).slice(0,3).map(([J,K])=>({tier:F,frameKey:x[J].key,samples:K})));return{cpu:_,jit:{origin:"jsc-profile",tiers:A,topFramesByTier:D}}}var Le=1000;async function he(o,v={}){let c=v.intervalUs??Le,T,x=Bun.nanoseconds(),C=await je(async()=>(T=await o(),T),c),N=Bun.nanoseconds()-x,{cpu:R,jit:U}=ge(C.stackTraces,c);return{result:T,cpu:R,jit:U,diagnosticWallNs:N}}async function ie(o){let v=Bun.nanoseconds(),c=Bun.spawn(o.argv,{cwd:o.cwd,env:o.env,stdout:"ignore",stderr:"ignore",stdin:"ignore"}),T=await c.exited,x=Bun.nanoseconds(),C=c.resourceUsage?.();return{wallNs:x-v,exitCode:T,userNs:C?Number(C.cpuTime.user)*1000:void 0,systemNs:C?Number(C.cpuTime.system)*1000:void 0,maxRssBytes:C?.maxRSS}}function be(o){return o.trim().split(/\s+/).filter(Boolean)}var He=10,ze=3000000000,Je=3;async function f(o){let v=o.warmup??Je;for(let S=0;S<v;S++)await ie(o);let c=[],T=o.runs??o.minRuns??He,x=o.runs!==void 0?0:o.minTotalNs??ze,C=0,N=0;while(N<T||C<x){let S=await ie(o);if(c.push({i:N,wallNs:S.wallNs,exitCode:S.exitCode,userNs:S.userNs,systemNs:S.systemNs,maxRssBytes:S.maxRssBytes}),C+=S.wallNs,N++,o.runs!==void 0&&N>=o.runs)break}let R=c.map((S)=>S.wallNs),U=l(R),B=p(U,c.map((S)=>S.exitCode));return{trials:c,timing:U,warnings:B}}var Ve=new URL("./runner.ts",import.meta.url).pathname,Ke="node_modules/.cache/ostia";async function m(o){let c=`${o.outDir??Ke}/bench-tmp`,T=o.cwd??process.cwd(),x={timeBudgetMs:o.timeBudgetMs,minSamples:o.minSamples,gc:o.gc,filter:o.filter},C=[],N=[];try{for(let R of o.suites){let U=R.startsWith("/")?R:`${T}/${R}`,B=`${c}/${e("bench-out",U)}.json`,A=await Bun.spawn(["bun",Ve,U,B,JSON.stringify(x)],{cwd:T,stdout:"inherit",stderr:"inherit",stdin:"ignore"}).exited;if(A!==0)throw Error(`Bench suite failed: ${R} (runner exited ${A})`);let O=await t(B);C.push(...O.workloads),N.push(...O.runs)}}finally{await Bun.spawn(["rm","-rf",c]).exited}return r(C,N)}var a={timingPct:5,frameSelfPct:10,heapTypePct:10,minFrameSelfUs:1000};function se(o,v){if(o===0)return v===0?0:1/0;return(v-o)/o*100}function ee(o,v,c){return o.runs.find((T)=>T.workloadId===v&&T.phase===c)}function d(o,v,c=a){let T=new Set(v.workloads.map((C)=>C.id)),x=[];for(let C of o.workloads){if(!T.has(C.id))continue;let N=b(o,v,C.id,c);if(N)x.push(N)}return x}function b(o,v,c,T=a){let x=ee(o,c,"timing"),C=ee(v,c,"timing"),N=ee(o,c,"cpu"),R=ee(v,c,"cpu"),U=ee(o,c,"heap"),B=ee(v,c,"heap"),S=x?.id??N?.id??U?.id,A=C?.id??R?.id??B?.id;if(!S||!A)return;let O=!1,W;if(x?.timing&&C?.timing){let H=se(x.timing.median,C.timing.median),z=se(x.timing.mean,C.timing.mean),V=H>T.timingPct?"regressed":H<-T.timingPct?"improved":"unchanged";if(V==="regressed")O=!0;W={medianDeltaPct:H,meanDeltaPct:z,verdict:V}}let j;if(N?.cpu&&R?.cpu){let H=new Map(N.cpu.totals.map((M)=>[N.cpu.frames[M.frameIx].key,M])),z=new Map(R.cpu.totals.map((M)=>[R.cpu.frames[M.frameIx].key,M])),V=new Map(N.cpu.frames.map((M)=>[M.key,M.name])),_=new Map(R.cpu.frames.map((M)=>[M.key,M.name]));j=[...new Set([...H.keys(),...z.keys()])].map((M)=>{let F=H.get(M)?.selfUs??0,L=z.get(M)?.selfUs??0;return{frameKey:M,name:_.get(M)??V.get(M)??M,baseSelfUs:F,candSelfUs:L,deltaPct:se(F,L)}}).sort((M,F)=>Math.abs(F.deltaPct)-Math.abs(M.deltaPct));for(let M of j)if((M.baseSelfUs>=T.minFrameSelfUs||M.candSelfUs>=T.minFrameSelfUs)&&M.deltaPct>T.frameSelfPct)O=!0}let E;if(U?.heap&&B?.heap){let H=new Map(U.heap.typeCounts.map((_)=>[_.type,_])),z=new Map(B.heap.typeCounts.map((_)=>[_.type,_]));E=[...new Set([...H.keys(),...z.keys()])].map((_)=>{let D=H.get(_),M=z.get(_);return{type:_,baseCount:D?.count??0,candCount:M?.count??0,baseBytes:D?.retainedBytes,candBytes:M?.retainedBytes,deltaPct:se(D?.count??0,M?.count??0)}}).sort((_,D)=>Math.abs(D.deltaPct)-Math.abs(_.deltaPct));for(let _ of E)if(_.deltaPct>T.heapTypePct)O=!0}return{id:e("cmp",S,A),baselineRunId:S,candidateRunId:A,timing:W,frames:j,heapTypes:E,thresholds:T,verdict:O?"fail":"pass"}}function Q(o,v){if(v){let c=o.runs.find((T)=>T.id===v);return c?.cpu?[c]:[]}return o.runs.filter((c)=>c.phase==="cpu"&&c.cpu)}function ne(o){let v=o.nodes,c=v.length,T=Ge(o),x=new Int32Array(c).fill(-1);for(let U=0;U<c;U++)for(let B of v[U].children){let S=T(B);if(S!==-1)x[S]=U}let C=[];for(let U=0;U<c;U++)if(x[U]===-1)C.push(U);let N=[],R=[];for(let U=C.length-1;U>=0;U--)R.push(C[U]);while(R.length>0){let U=R.pop();N.push(U);for(let B of v[U].children){let S=T(B);if(S!==-1&&x[S]===U)R.push(S)}}return{count:c,indexOf:T,parentIx:x,roots:C,order:N}}function Ge(o){let v=o.nodes,c=v.length,T=1/0,x=-1/0,C=!0;for(let R=0;R<c;R++){let U=v[R].id;if(!Number.isInteger(U)){C=!1;break}if(U<T)T=U;if(U>x)x=U}if(C&&c>0&&x-T<c*4+64){let R=x-T+1,U=new Int32Array(R).fill(-1);for(let B=0;B<c;B++)U[v[B].id-T]=B;return(B)=>{let S=B-T;return S>=0&&S<R?U[S]:-1}}let N=new Map;for(let R=0;R<c;R++)N.set(v[R].id,R);return(R)=>N.get(R)??-1}function ye(o,v){let{count:c,indexOf:T,parentIx:x,order:C}=v,N=new Float64Array(c),R=new Float64Array(c),U=o.samples?.nodeIds??[],B=o.samples?.timeDeltasUs??[];for(let A=0;A<U.length;A++){let O=T(U[A]);if(O===-1)continue;N[O]+=B[A]??0,R[O]+=1}let S=new Float64Array(c);for(let A=C.length-1;A>=0;A--){let O=C[A];S[O]+=N[O];let W=x[O];if(W>=0)S[W]+=S[O]}return{selfUs:N,totalUs:S,samples:R}}var we={name:"collapsed",async render(o,v={}){return{files:Q(o,v.runId).map((x)=>{let C=x.cpu,{nodes:N,frames:R}=C,U=ne(C),B=Array(U.count);for(let j of U.order){let E=R[N[j].frameIx].name||"(anonymous)",H=U.parentIx[j];B[j]=H===-1?E:`${B[H]};${E}`}let S=new Float64Array(U.count),A=[],O=C.samples?.nodeIds??[];for(let j=0;j<O.length;j++){let E=U.indexOf(O[j]);if(E===-1)continue;if(S[E]++===0)A.push(E)}let W=Array(A.length);for(let j=0;j<A.length;j++){let E=A[j];W[j]=`${B[E]} ${S[E]}`}return{path:`${x.id}.collapsed.txt`,content:W.join(`
3
+ `)+(W.length>0?`
4
+ `:"")}})}}};var xe={name:"cpuprofile",async render(o,v={}){let c=Q(o,v.runId),T=[],x=[];for(let C of c){if(C.cpu?.origin!=="cpu-prof"&&C.cpu?.origin!=="inspector"){x.push(`${C.id} (origin ${C.cpu?.origin??"unknown"} has no .cpuprofile artifact to pass through)`);continue}let N=C.artifacts.find((U)=>U.kind==="cpuprofile");if(!N){x.push(`${C.id} (no cpuprofile artifact recorded on this run)`);continue}let R=Bun.file(N.path);if(!await R.exists()){x.push(`${C.id} (artifact missing on disk: ${N.path})`);continue}T.push({path:`${C.id}.cpuprofile`,content:await R.text()})}if(T.length===0&&x.length>0)return{text:`No .cpuprofile artifacts available:
5
+ ${x.map((C)=>` - ${C}`).join(`
6
+ `)}
7
+ `};return{files:T}}};var Re={name:"json",async render(o){return{text:y(o)}}};var Pe={name:"jsonl",async render(o){let{runs:v,...c}=o;return{text:`${[g(c),...v.map((x)=>g(x))].join(`
8
+ `)}
9
+ `}}};function X(o){return(o/1e6).toFixed(3)}function oe(o){return o?.label??o?.command?.join(" ")??o?.entry?.task??o?.id??"unknown"}var Te=10,$e=10,Ce={name:"markdown",async render(o){let v=new Map(o.workloads.map((x)=>[x.id,x])),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 T=o.runs.filter((x)=>x.phase==="timing"&&x.timing!==void 0);if(T.length>0){c.push("## Timing",""),c.push("| Command | Mean \xB1 SD (ms) | Min\u2026Max (ms) | Median (ms) |","|---|---|---|---|");for(let C of T){let N=oe(v.get(C.workloadId)),R=C.timing;c.push(`| ${N} | ${X(R.mean)} \xB1 ${X(R.stddev)} | ${X(R.min)}\u2026${X(R.max)} | ${X(R.median)} |`)}c.push("");let x=T.filter((C)=>C.warnings.length>0);if(x.length>0){c.push("### Warnings","");for(let C of x){let N=oe(v.get(C.workloadId));for(let R of C.warnings)c.push(`- **${N}**: ${R.message} (\`${R.code}\`)`)}c.push("")}}for(let x of o.runs){if(x.phase!=="cpu"&&x.phase!=="heap")continue;let C=oe(v.get(x.workloadId));if(x.phase==="cpu"){if(c.push(`## CPU capture - ${C}`,""),c.push(`instrumented, diagnostic wall ${X(x.diagnosticWallNs??0)}ms`,""),x.cpu){c.push(`origin: \`${x.cpu.origin}\`, interval: ${x.cpu.samplingIntervalUs}\xB5s`,""),c.push("| Self % | Self (ms) | Total (ms) | Frame |","|---|---|---|---|");let N=x.cpu.totals.reduce((R,U)=>R+U.selfUs,0)||1;for(let R of x.cpu.totals.slice(0,Te)){let U=x.cpu.frames[R.frameIx],B=(R.selfUs/N*100).toFixed(1);c.push(`| ${B}% | ${(R.selfUs/1000).toFixed(2)} | ${(R.totalUs/1000).toFixed(2)} | ${U?.name||"(anonymous)"} |`)}if(c.push(""),x.jit){let R=x.jit.tiers;c.push(`JIT tiers: LLInt ${R.llint} \xB7 Baseline ${R.baseline} \xB7 DFG ${R.dfg} \xB7 FTL ${R.ftl}`,"")}}}else if(c.push(`## Heap snapshot - ${C}`,""),c.push(`instrumented, diagnostic wall ${X(x.diagnosticWallNs??0)}ms`,""),x.heap){c.push(`${x.heap.objectCount??"?"} objects, ${((x.heap.heapSizeBytes??0)/1e6).toFixed(2)}MB`,""),c.push("| Count | Type |","|---|---|");for(let N of x.heap.typeCounts.slice(0,$e))c.push(`| ${N.count} | ${N.type} |`);c.push("")}for(let N of x.artifacts)c.push(`- artifact: \`${N.path}\``);for(let N of x.warnings)c.push(`- ! ${N.message} (\`${N.code}\`)`);if(x.artifacts.length>0||x.warnings.length>0)c.push("")}if(o.comparisons&&o.comparisons.length>0){c.push("## Comparisons","");for(let x of o.comparisons){let C=o.runs.find((R)=>R.id===x.candidateRunId),N=oe(C?v.get(C.workloadId):void 0);if(c.push(`### ${x.verdict==="pass"?"\u2713":"\u2717"} ${N}`,""),x.timing){let R=x.timing.medianDeltaPct>0?"+":"";c.push(`- timing: ${R}${x.timing.medianDeltaPct.toFixed(1)}% median (**${x.timing.verdict}**)`)}for(let R of x.frames?.slice(0,Te)??[]){if(Math.abs(R.deltaPct)<0.5)continue;let U=R.deltaPct>0?"+":"";c.push(`- frame \`${R.name}\`: ${U}${R.deltaPct.toFixed(1)}% self-time (${(R.baseSelfUs/1000).toFixed(2)}ms \u2192 ${(R.candSelfUs/1000).toFixed(2)}ms)`)}for(let R of x.heapTypes?.slice(0,$e)??[]){if(Math.abs(R.deltaPct)<0.5)continue;let U=R.deltaPct>0?"+":"";c.push(`- heap \`${R.type}\`: ${U}${R.deltaPct.toFixed(1)}% count (${R.baseCount} \u2192 ${R.candCount})`)}c.push("")}}return{text:c.join(`
10
+ `)}}};var Ye=15;function ae(o){return`n${o}`}function qe(o,v,c){return`${(o||"(anonymous)").replace(/"/g,"'")} (self ${(v/1000).toFixed(2)}ms, total ${(c/1000).toFixed(2)}ms)`}function Qe(o,v,c,T){let x=[];if(T<=0)return x;for(let C=0;C<v;C++){if(C===c)continue;let N=o[C];if(x.length===T&&N<=o[x[T-1]])continue;let R=x.length;while(R>0&&o[x[R-1]]<N)R--;if(x.splice(R,0,C),x.length>T)x.pop()}return x}var Ie={name:"mermaid",async render(o,v={}){let c=v.topN??Ye;return{files:Q(o,v.runId).map((C)=>{let N=C.cpu,{nodes:R,frames:U}=N,B=ne(N),{selfUs:S,totalUs:A}=ye(N,B),{parentIx:O}=B,W=B.roots[0]??-1,j=Qe(S,B.count,W,c),E=new Set(W!==-1?[W]:[]),H=[];for(let V of j){H.length=0;for(let _=V;_!==-1;_=O[_])H.push(_);for(let _=H.length-1;_>=0;_--)E.add(H[_])}let z=["graph TD"];for(let V of E){let _=R[V].id;z.push(` ${ae(_)}["${qe(U[R[V].frameIx].name,S[V],A[V])}"]`)}for(let V of E){let _=O[V];if(_!==-1&&E.has(_))z.push(` ${ae(R[_].id)} --> ${ae(R[V].id)}`)}return{path:`${C.id}.mermaid.md`,content:`${z.join(`
11
+ `)}
12
+ `}})}}};var Xe="https://www.speedscope.app/file-format-schema.json";function Ne(o){return o?.label??o?.command?.join(" ")??o?.entry?.task??"profile"}var ke={name:"speedscope",async render(o,v={}){let c=Q(o,v.runId),T=new Map(o.workloads.map((C)=>[C.id,C]));return{files:c.map((C)=>{let N=C.cpu,{nodes:R}=N,U=ne(N),B=N.samples?.nodeIds??[],S=N.samples?.timeDeltasUs??[],A=Array(U.count);for(let E of U.order){let H=U.parentIx[E],z=R[E].frameIx;A[E]=H===-1?[z]:[...A[H],z]}let O=Array(B.length);for(let E=0;E<B.length;E++){let H=U.indexOf(B[E]);O[E]=H===-1?[]:A[H]}let W=0;for(let E=0;E<S.length;E++)W+=S[E];let j={$schema:Xe,exporter:"ostia",name:Ne(T.get(C.workloadId)),activeProfileIndex:0,shared:{frames:N.frames.map((E)=>({name:E.name||"(anonymous)",file:E.url,line:E.line!==void 0?E.line+1:void 0}))},profiles:[{type:"sampled",name:Ne(T.get(C.workloadId)),unit:"microseconds",startValue:0,endValue:W,samples:O,weights:S}]};return{path:`${C.id}.speedscope.json`,content:`${JSON.stringify(j,null,2)}
13
+ `}})}}};function te(o){return(o/1e6).toFixed(3)}function ce(o){return o.label??o.command?.join(" ")??o.entry?.task??o.id}function Ue(o){let v=o?.entry?.task;if(!v)return;let c=v.lastIndexOf("/");return c===-1?void 0:v.slice(0,c)}var Fe={name:"table",async render(o){let v=o.runs.filter((W)=>W.phase==="timing"&&W.timing!==void 0),c=new Map(o.workloads.map((W)=>[W.id,W]));if(v.length===0){let W=ve(o,c);return{text:W.length>0?`${W.join(`
14
+ `)}
15
+ `:`(no timing runs)
16
+ `}}let T=v.map((W)=>{let j=c.get(W.workloadId);return{run:W,workload:j,label:j?ce(j):W.workloadId}}),x=Math.min(...T.map((W)=>W.run.timing.median)),C=T.length>1,N=new Map;for(let W of T){let j=Ue(W.workload);if(j===void 0)continue;let E=N.get(j);if(E)E.push(W);else N.set(j,[W])}let R=(W)=>{let j=N.get(Ue(W.workload)??"");if(!j||j.length<=1)return x;let E=j.find((H)=>H.workload?.baseline);return E?E.run.timing.median:Math.min(...j.map((H)=>H.run.timing.median))},U=[],B=Math.max(7,...T.map((W)=>W.label.length)),S=C?`${"Command".padEnd(B)} Mean [ms] Min\u2026Max [ms] Relative`:`${"Command".padEnd(B)} Mean [ms] Min\u2026Max [ms]`;U.push(S),U.push("-".repeat(S.length));for(let W of T){let{run:j,label:E,workload:H}=W,z=j.timing,V=`${te(z.mean)} \xB1 ${te(z.stddev)}`,_=`${te(z.min)}\u2026${te(z.max)}`,D=`${E.padEnd(B)} ${V.padEnd(15)} ${_.padEnd(18)}`;if(C){let M=z.median/R(W);if(M===1)D+=H?.baseline?" 1.00\xD7 (baseline)":" 1.00\xD7";else if(M>1)D+=` ${M.toFixed(2)}\xD7 slower`;else D+=` ${(1/M).toFixed(2)}\xD7 faster`}U.push(D);for(let M of j.warnings)U.push(` ! ${M.message}`)}let A=en(o,c);if(A.length>0)U.push(""),U.push(...A);let O=ve(o,c);if(O.length>0)U.push(""),U.push(...O);return{text:`${U.join(`
17
+ `)}
18
+ `}}};function Ze(o,v,c){let T=o.runs.find((C)=>C.id===c),x=T?v.get(T.workloadId):void 0;return x?ce(x):c}function ve(o,v){if(!o.comparisons||o.comparisons.length===0)return[];let c=[];for(let T of o.comparisons){let x=Ze(o,v,T.candidateRunId),C=T.verdict==="pass"?"\u2713":"\u2717";if(c.push(`${C} ${x}`),T.timing){let N=T.timing.medianDeltaPct>0?"+":"";c.push(` timing: ${N}${T.timing.medianDeltaPct.toFixed(1)}% median (${T.timing.verdict})`)}if(T.frames)for(let N of T.frames.slice(0,De)){if(Math.abs(N.deltaPct)<0.5)continue;let R=N.deltaPct>0?"+":"";c.push(` frame ${N.name}: ${R}${N.deltaPct.toFixed(1)}% self-time (${(N.baseSelfUs/1000).toFixed(2)}ms -> ${(N.candSelfUs/1000).toFixed(2)}ms)`)}if(T.heapTypes)for(let N of T.heapTypes.slice(0,Me)){if(Math.abs(N.deltaPct)<0.5)continue;let R=N.deltaPct>0?"+":"";c.push(` heap ${N.type}: ${R}${N.deltaPct.toFixed(1)}% count (${N.baseCount} -> ${N.candCount})`)}}return c}var De=5,Me=5;function en(o,v){let c=[];for(let T of o.runs){if(T.phase!=="cpu"&&T.phase!=="heap")continue;let x=v.get(T.workloadId),C=x?ce(x):T.workloadId;if(T.phase==="cpu")if(T.cpu){c.push(`CPU capture - ${C} (instrumented, ${T.cpu.samplingIntervalUs}\xB5s interval, diagnostic wall ${te(T.diagnosticWallNs??0)}ms)`);let N=T.cpu.totals.reduce((R,U)=>R+U.selfUs,0)||1;for(let R of T.cpu.totals.slice(0,De)){let U=T.cpu.frames[R.frameIx],B=(R.selfUs/N*100).toFixed(1);c.push(` ${B.padStart(5)}% ${(R.selfUs/1000).toFixed(2).padStart(8)}ms self ${U?.name??"?"}`)}}else c.push(`CPU capture - ${C} (instrumented, no evidence captured)`);else if(T.heap){let N=((T.heap.heapSizeBytes??0)/1e6).toFixed(2);c.push(`Heap snapshot - ${C} (instrumented, ${T.heap.objectCount??"?"} objects, ${N}MB)`);for(let R of T.heap.typeCounts.slice(0,Me))c.push(` ${String(R.count).padStart(6)} ${R.type}`)}else c.push(`Heap snapshot - ${C} (instrumented, no evidence captured)`);for(let N of T.artifacts)c.push(` artifact: ${N.path}`);for(let N of T.warnings)c.push(` ! ${N.message}`)}return c}var n={table:Fe,json:Re,markdown:Ce,jsonl:Pe,collapsed:we,mermaid:Ie,speedscope:ke,cpuprofile:xe};var nn="node_modules/.cache/ostia",ue=1000;async function w(o){let v=s({runs:o.runs??null,warmup:o.warmup??null,cpu:o.cpu??!1,heap:o.heap??!1,cpuIntervalUs:o.cpuIntervalUs??ue}),T=`${o.outDir??nn}/artifacts`,x=[],C=[];for(let N of o.commands){let R=Array.isArray(N)?N:be(N),U=u(R,Array.isArray(N)?void 0:N);x.push(U);let B=await f({argv:R,cwd:o.cwd,env:o.env,runs:o.runs,warmup:o.warmup}),S=i({workload:U,configFingerprint:v,trials:B.trials,timing:B.timing,warnings:B.warnings});if(C.push(S),o.cpu){let A=`${S.id}-cpu.cpuprofile`,O=await pe({argv:R,cwd:o.cwd,env:o.env,artifactDir:T,fileName:A,intervalUs:o.cpuIntervalUs??ue});C.push(await Se({workload:U,phase:"cpu",configFingerprint:v,diagnosticWallNs:O.diagnosticWallNs,exitCode:O.exitCode,cpu:O.cpu,artifactPath:O.artifactPath,artifactKind:"cpuprofile",warnings:O.warnings}))}if(o.heap){let A=`${S.id}-heap.heapsnapshot`,O=await me({argv:R,cwd:o.cwd,env:o.env,artifactDir:T,fileName:A});C.push(await Se({workload:U,phase:"heap",configFingerprint:v,diagnosticWallNs:O.diagnosticWallNs,exitCode:O.exitCode,heap:O.heap,artifactPath:O.artifactPath,artifactKind:"heapsnapshot",warnings:O.warnings}))}}return r(x,C)}async function Se(o){let v=`${o.workload.id}-${o.phase}-${o.configFingerprint}`,c=o.artifactPath?[await P(v,o.artifactKind,o.artifactPath)]:[];return h({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 I(o,v={}){let c=k(o),T=s({intervalUs:v.intervalUs??ue,origin:v.origin??"inspector"}),x=(B)=>B.samples?.nodeIds.length===0?[{code:"empty-profile",message:"In-process capture produced zero samples."}]:[];if(v.origin==="jsc"){let{result:B,cpu:S,jit:A,diagnosticWallNs:O}=await he(o,v),W=h({workload:c,phase:"cpu",configFingerprint:T,diagnosticWallNs:O,cpu:S,jit:A,warnings:x(S),artifacts:[]});return{result:B,run:W}}let{result:C,cpu:N,diagnosticWallNs:R}=await fe(o,v),U=h({workload:c,phase:"cpu",configFingerprint:T,diagnosticWallNs:R,cpu:N,warnings:x(N),artifacts:[]});return{result:C,run:U}}
19
+ export{m,a,d,b,f,n,w,I};
@@ -0,0 +1,4 @@
1
+ // @bun
2
+ function g(n){return JSON.stringify(W(n))}function W(n){if(Array.isArray(n))return n.map(W);if(n!==null&&typeof n==="object"){let a={};for(let d of Object.keys(n).sort())a[d]=W(n[d]);return a}return n}function e(n,...a){let d=Bun.CryptoHasher.hash("sha256",g(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 k(n,a){return{id:e("wl","inprocess",n.name,n.toString()),kind:"inprocess",label:a}}function R(n,a,d,m){return{id:e("wl","inprocess-entry",n,a),kind:"inprocess",entry:{file:n,task:a},label:d,baseline:m}}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:G(n.trials)}}function G(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 h(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 P(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 y(n){return`${JSON.stringify(W(n),null,2)}
3
+ `}async function o(n,a){await Bun.write(a,y(n))}async function t(n){let a=await Bun.file(n).text();return JSON.parse(a)}var _=[],B;function F(n,a){let d=B;B=n;try{a()}finally{B=d}}function D(n,a,d){_.push({groupName:B,name:n,fn:a,baseline:d?.baseline,opts:d})}function T(){return _}function C(){_.length=0,B=void 0}function x(n){return n.groupName?`${n.groupName}/${n.name}`:n.name}function N(n,a){if(!a)return[...n];let d=new RegExp(a);return n.filter((m)=>d.test(x(m)))}function l(n){if(n.length===0)throw Error("computeTimingStats: samples must be non-empty");let a=n.length,d=L(n),m=0;for(let v=0;v<a;v++)m+=n[v];let f=m/a,w=I(d,0.5),b=0;for(let v=0;v<a;v++){let S=n[v]-f;b+=S*S}let A=Math.sqrt(b/a),H=d[0],O=d[a-1],E=I(d,0.25),q=I(d,0.75),M=q-E,z=E-1.5*M,V=q+1.5*M,K=E-3*M,U=q+3*M,J=0,j=0;for(let v=0;v<a;v++){let S=n[v];if(S<K||S>U)j++;else if(S<z||S>V)J++}return{unit:"ns",samples:n,mean:f,median:w,stddev:A,min:H,max:O,outliers:{mild:J,severe:j}}}function L(n){let a=new Float64Array(n.length);return a.set(n),a.sort(),a}function I(n,a){let d=n.length;if(d===1)return n[0];let m=a*(d-1),f=Math.floor(m),w=Math.ceil(m);if(f===w)return n[f];let b=m-f;return n[f]*(1-b)+n[w]*b}var Z=5000000,Q=200;function p(n,a,d="subprocess"){let m=[],f=n.samples[0];if(f!==void 0){let b=L(n.samples),A=I(b,0.25),O=I(b,0.75)-A;if(f>n.median+3*O&&O>0)m.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)m.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<Z)m.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<Q)m.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((b)=>b!==void 0&&b!==0);if(w.length>0)m.push({code:"nonzero-exit",message:`${w.length} of ${a.length} trial(s) exited non-zero.`,data:{exitCodes:w}});return m}
4
+ export{g,e,c,r,u,k,R,i,h,P,s,y,o,t,l,p,F,D,T,C,x,N};
package/cli.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- import{a as z,b as R,c as _,d as v,e as M,f as m,g as K}from"./chunk-j0j2b0fj.js";import{j as y,k as O,l as U,m as H,p as q,s as J,u as b,v as g}from"./chunk-ck12vbed.js";function N(t){return y("cache",t.workloadId,t.phase,t.configFingerprint,t.bunVersion,t.toolVersion,t.instrumented,t.inputsDigest??null)}async function A(t,e=process.cwd()){if(t.length===0)return;let r=new Set;for(let s of t){let a=new Bun.Glob(s);for await(let i of a.scan({cwd:e,absolute:!1}))r.add(i)}let o=[...r].sort(),n=await Promise.all(o.map(async(s)=>{let a=await Bun.file(`${e}/${s}`).arrayBuffer();return{path:s,sha256:Bun.CryptoHasher.hash("sha256",a,"hex")}}));return y("inputs",n)}function E(t,e){return`${t}/cache/${e}.json`}async function I(t,e){let r=Bun.file(E(t,e));if(!await r.exists())return;return await r.json()}async function S(t,e,r){await Bun.write(E(t,e),`${JSON.stringify(r,null,2)}
4
- `)}var G={runs:null,warmup:3,outDir:".ostia",baseline:"main",cpuIntervalUs:1000,thresholds:R,workloads:[]};async function B(t="ostia.config.json"){let e=Bun.file(t);if(!await e.exists())return;let r=await e.json();return{...G,...r,thresholds:{...R,...r.thresholds??{}}}}function T(t,e){return`${t.outDir}/baselines/${e??t.baseline}.json`}class x extends Error{path;constructor(t){super(`No baseline document at ${t}. Create one with: ostia run --export-json ${t} <command...>`);this.path=t}}async function L(t){let{config:e}=t,r=T(e,t.baselineName);if(!await Bun.file(r).exists())throw new x(r);let n=await g(r),s=[],a=0,i=0,d=0;for(let u of e.workloads){let h=H(u.command,u.label),Z=await A(u.inputs??[]),j=J({runs:e.runs,warmup:e.warmup}),D=N({workloadId:h.id,phase:"timing",configFingerprint:j,bunVersion:Bun.version,toolVersion:O,instrumented:!1,inputsDigest:Z}),F=t.full?void 0:await I(e.outDir,D),k,C;if(F)k=F,C="cached",i++;else{a++;let P=await M({argv:u.command,runs:e.runs??void 0,warmup:e.warmup});k=q({workload:h,configFingerprint:j,trials:P.trials,timing:P.timing,warnings:P.warnings}),await S(e.outDir,D,k),C="executed",d++}s.push({workload:h,status:C,run:k})}let c=U(s.map((u)=>u.workload),s.map((u)=>u.run)),l=0,f=0,p=0;for(let u of s){let h=v(n,c,u.workload.id,e.thresholds);if(!h){p++;continue}if(u.comparison=h,h.verdict==="pass")l++;else f++}return c.comparisons=s.map((u)=>u.comparison).filter((u)=>u!==void 0),{document:c,summary:{total:e.workloads.length,affected:a,cached:i,executed:d,passed:l,regressed:f,missingBaseline:p,results:s}}}function V(t){let e=[];if(e.push(`${t.total} workloads`),e.push(`${t.affected} affected by this change`),e.push(`${t.cached} cached`),e.push(`${t.executed} executed`),t.missingBaseline>0)e.push(`${t.missingBaseline} skipped (no matching baseline workload)`);let r=t.results.filter((o)=>o.comparison?.verdict==="fail").map((o)=>{let n=o.comparison.timing,s=o.workload.label??o.workload.command?.join(" ")??o.workload.id;return n?`${n.medianDeltaPct>0?"+":""}${n.medianDeltaPct.toFixed(1)}% median on ${s}`:s});return e.push(`${t.passed} passed ${t.regressed} regressed${r.length>0?` (${r.join(", ")})`:""}`),e.push(""),e.push(`Profile CI: ${t.regressed>0?"\u2717":"\u2713"}`),`${e.join(`
3
+ import{m,a,d,b,f,n,w}from"./chunk-m8zhsw7r.js";import{e,c,r,u,i,s,o,t}from"./chunk-qh19pbhc.js";function q(p){return e("cache",p.workloadId,p.phase,p.configFingerprint,p.bunVersion,p.toolVersion,p.instrumented,p.inputsDigest??null)}async function v(p,l=process.cwd()){if(p.length===0)return;let h=new Set;for(let k of p){let P=new Bun.Glob(k);for await(let C of P.scan({cwd:l,absolute:!1}))h.add(C)}let x=[...h].sort(),g=await Promise.all(x.map(async(k)=>{let P=await Bun.file(`${l}/${k}`).arrayBuffer();return{path:k,sha256:Bun.CryptoHasher.hash("sha256",P,"hex")}}));return e("inputs",g)}function _(p,l){return`${p}/cache/${l}.json`}async function J(p,l){let h=Bun.file(_(p,l));if(!await h.exists())return;return await h.json()}async function L(p,l,h){await Bun.write(_(p,l),`${JSON.stringify(h,null,2)}
4
+ `)}var Z="node_modules/.cache/ostia",X=".ostia/baselines",Q={runs:null,warmup:3,outDir:Z,baselineDir:X,baseline:"main",cpuIntervalUs:1000,thresholds:a,workloads:[]};async function M(p="ostia.config.json"){let l=Bun.file(p);if(!await l.exists())return;let h=await l.json();return{...Q,...h,thresholds:{...a,...h.thresholds??{}}}}function V(p,l){return`${p.baselineDir}/${l??p.baseline}.json`}class S 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 W(p){let{config:l}=p,h=V(l,p.baselineName);if(!await Bun.file(h).exists())throw new S(h);let g=await t(h),k=[],P=0,C=0,D=0;for(let y of l.workloads){let N=u(y.command,y.label),G=await v(y.inputs??[]),O=s({runs:l.runs,warmup:l.warmup}),U=q({workloadId:N.id,phase:"timing",configFingerprint:O,bunVersion:Bun.version,toolVersion:c,instrumented:!1,inputsDigest:G}),H=p.full?void 0:await J(l.outDir,U),I,T;if(H)I=H,T="cached",C++;else{P++;let B=await f({argv:y.command,runs:l.runs??void 0,warmup:l.warmup});I=i({workload:N,configFingerprint:O,trials:B.trials,timing:B.timing,warnings:B.warnings}),await L(l.outDir,U,I),T="executed",D++}k.push({workload:N,status:T,run:I})}let R=r(k.map((y)=>y.workload),k.map((y)=>y.run)),A=0,F=0,j=0;for(let y of k){let N=b(g,R,y.workload.id,l.thresholds);if(!N){j++;continue}if(y.comparison=N,N.verdict==="pass")A++;else F++}return R.comparisons=k.map((y)=>y.comparison).filter((y)=>y!==void 0),{document:R,summary:{total:l.workloads.length,affected:P,cached:C,executed:D,passed:A,regressed:F,missingBaseline:j,results:k}}}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 h=p.results.filter((x)=>x.comparison?.verdict==="fail").map((x)=>{let g=x.comparison.timing,k=x.workload.label??x.workload.command?.join(" ")??x.workload.id;return g?`${g.medianDeltaPct>0?"+":""}${g.medianDeltaPct.toFixed(1)}% median on ${k}`:k});return l.push(`${p.passed} passed ${p.regressed} regressed${h.length>0?` (${h.join(", ")})`:""}`),l.push(""),l.push(`Profile CI: ${p.regressed>0?"\u2717":"\u2713"}`),`${l.join(`
5
5
  `)}
6
- `}async function w(t,e){if(t.text)process.stdout.write(t.text);if(!t.files||t.files.length===0)return;if(e)for(let r of t.files){let o=r.path?`${e}/${r.path}`:e;await Bun.write(o,r.content),process.stdout.write(`wrote ${o}
7
- `)}else if(t.files.length===1)process.stdout.write(t.files[0].content);else for(let r of t.files)process.stdout.write(`--- ${r.path??"(unnamed)"} ---
8
- ${r.content}
9
- `)}var Q=`ostia run [flags] <command...>
6
+ `}async function E(p,l){if(p.text)process.stdout.write(p.text);if(!p.files||p.files.length===0)return;if(l)for(let h of p.files){let x=h.path?`${l}/${h.path}`:l;await Bun.write(x,h.content),process.stdout.write(`wrote ${x}
7
+ `)}else if(p.files.length===1)process.stdout.write(p.files[0].content);else for(let h of p.files)process.stdout.write(`--- ${h.path??"(unnamed)"} ---
8
+ ${h.content}
9
+ `)}var Y=`ostia run [flags] <command...>
10
10
 
11
11
  Run one or more commands N times with warmup and report timing statistics.
12
12
 
@@ -16,7 +16,7 @@ Flags:
16
16
  --cpu capture one instrumented CPU-profile trial (subprocess --cpu-prof)
17
17
  --heap capture one instrumented heap-snapshot trial (subprocess --heap-prof)
18
18
  --cpu-interval USEC CPU sampling interval in microseconds (default: 1000)
19
- --out-dir PATH directory for captured artifacts (default: .ostia)
19
+ --out-dir PATH directory for captured artifacts (default: node_modules/.cache/ostia)
20
20
  --export-json PATH write the full ProfileDocument to PATH
21
21
  --format FORMAT table | json (default: table)
22
22
  --quiet suppress the rendered report (still writes --export-json)
@@ -30,16 +30,20 @@ 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
- `,X=`ostia bench [flags] <suite.ts...>
33
+ `,ee=`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).
37
37
 
38
38
  Flags:
39
- --time-budget MS time budget per task, min-samples permitting (default: 500)
40
- --min-samples N minimum samples per task (default: 20)
39
+ --time-budget MS sampling budget per task; always runs at least this long (default: 500)
40
+ --min-samples N hard floor on samples per task, kept even when it overruns the
41
+ budget. Default: cost-aware - as many as fit in the budget,
42
+ clamped to 3..20, so one slow task can't blow the total.
41
43
  --gc Bun.gc(true) between trials (default: off - hides allocation cost)
42
- --out-dir PATH directory for scratch IPC files (default: .ostia)
44
+ --filter REGEX only run tasks whose "group/name" id matches this regex (substring,
45
+ case-sensitive; unmatched tasks are skipped, not timed)
46
+ --out-dir PATH directory for scratch IPC files (default: node_modules/.cache/ostia)
43
47
  --export-json PATH write the full ProfileDocument to PATH
44
48
  --format FORMAT table | json (default: table)
45
49
  --quiet suppress the rendered report (still writes --export-json)
@@ -49,12 +53,15 @@ Suite files register tasks like:
49
53
  import { group, task } from "<pkg>"
50
54
  group("parse", () => {
51
55
  task("small input", () => parse(smallBuf))
56
+ task("full pipeline", () => build(), { timeBudgetMs: 2000, minSamples: 10 })
52
57
  })
58
+ Per-task options override --time-budget / --min-samples for that task only.
53
59
 
54
60
  Examples:
55
61
  ostia bench benches/parse.ts
56
62
  ostia bench --time-budget 1000 --min-samples 50 benches/*.ts
57
- `,W=`ostia compare <base.json> <candidate.json>
63
+ ostia bench benches/*.ts --filter parse
64
+ `,K=`ostia compare <base.json> <candidate.json>
58
65
  ostia compare <candidate.json> --baseline <path.json>
59
66
 
60
67
  Compare two ProfileDocuments (matched by workload id) and rank timing/frame/heap deltas.
@@ -68,10 +75,10 @@ Flags:
68
75
  Examples:
69
76
  ostia compare before.json after.json
70
77
  ostia compare after.json --baseline .ostia/baselines/main.json
71
- `,Y=`ostia report <document.json> [--format table|json|markdown|jsonl]
78
+ `,te=`ostia report <document.json> [--format table|json|markdown|jsonl]
72
79
 
73
80
  Render a saved ProfileDocument.
74
- `,ee=`ostia viz <document.json> --format FORMAT [--run <id>] [--out-dir PATH]
81
+ `,re=`ostia viz <document.json> --format FORMAT [--run <id>] [--out-dir PATH]
75
82
 
76
83
  Render CPU evidence from a saved ProfileDocument as a visualization artifact. Files,
77
84
  not a GUI - hand the output to speedscope.app, flamegraph.pl, or
@@ -90,9 +97,9 @@ Flags:
90
97
  --help show this message
91
98
 
92
99
  Examples:
93
- ostia viz run.json --format speedscope --out-dir .ostia/viz
100
+ ostia viz run.json --format speedscope --out-dir node_modules/.cache/ostia/viz
94
101
  ostia viz run.json --format collapsed | flamegraph.pl > flame.svg
95
- `,te=`ostia ci [--full] [--baseline NAME]
102
+ `,se=`ostia ci [--full] [--baseline NAME]
96
103
 
97
104
  Load ostia.config.json, run configured workloads (reusing cached results when their
98
105
  fingerprint is unchanged), compare against the named baseline, and gate on regressions.
@@ -105,21 +112,21 @@ Flags:
105
112
  --help show this message
106
113
 
107
114
  Exit codes: 0 pass, 1 regression, 2 harness error (missing config/baseline, spawn failure).
108
- `;function re(t){let e=[],r,o,n=!1,s=!1,a,i,d,c="table",l=!1,f=!1;for(let p=0;p<t.length;p++){let u=t[p];switch(u){case"--runs":r=Number(t[++p]);break;case"--warmup":o=Number(t[++p]);break;case"--cpu":n=!0;break;case"--heap":s=!0;break;case"--cpu-interval":a=Number(t[++p]);break;case"--out-dir":i=t[++p];break;case"--export-json":d=t[++p];break;case"--format":c=t[++p];break;case"--quiet":l=!0;break;case"--help":case"-h":f=!0;break;default:e.push(u)}}return{commands:e,runs:r,warmup:o,cpu:n,heap:s,cpuIntervalUs:a,outDir:i,exportJson:d,format:c,quiet:l,help:f}}async function ne(t){let e=re(t);if(e.help||e.commands.length===0)return process.stdout.write(Q),e.help?0:2;if(!(e.format in m))return process.stderr.write(`Unknown --format "${e.format}". Expected one of: ${Object.keys(m).join(", ")}
109
- `),2;let r;try{r=await K({commands:e.commands,runs:e.runs,warmup:e.warmup,cpu:e.cpu,heap:e.heap,cpuIntervalUs:e.cpuIntervalUs,outDir:e.outDir})}catch(n){return process.stderr.write(`Run failed: ${n instanceof Error?n.message:String(n)}
110
- `),2}if(e.exportJson)await b(r,e.exportJson);if(!e.quiet){let s=await m[e.format].render(r,{});await w(s)}return r.runs.some((n)=>n.trials.some((s)=>s.exitCode!==void 0&&s.exitCode!==0))?1:0}function se(t){let e=[],r,o,n=!1,s,a,i="table",d=!1,c=!1;for(let l=0;l<t.length;l++){let f=t[l];switch(f){case"--time-budget":r=Number(t[++l]);break;case"--min-samples":o=Number(t[++l]);break;case"--gc":n=!0;break;case"--out-dir":s=t[++l];break;case"--export-json":a=t[++l];break;case"--format":i=t[++l];break;case"--quiet":d=!0;break;case"--help":case"-h":c=!0;break;default:e.push(f)}}return{suites:e,timeBudgetMs:r,minSamples:o,gc:n,outDir:s,exportJson:a,format:i,quiet:d,help:c}}async function oe(t){let e=se(t);if(e.help||e.suites.length===0)return process.stdout.write(X),e.help?0:2;if(!(e.format in m))return process.stderr.write(`Unknown --format "${e.format}". Expected one of: ${Object.keys(m).join(", ")}
111
- `),2;let r;try{r=await z({suites:e.suites,timeBudgetMs:e.timeBudgetMs,minSamples:e.minSamples,gc:e.gc,outDir:e.outDir})}catch(o){return process.stderr.write(`Bench failed: ${o instanceof Error?o.message:String(o)}
112
- `),2}if(e.exportJson)await b(r,e.exportJson);if(!e.quiet){let n=await m[e.format].render(r,{});await w(n)}return 0}function ae(t){let e=[],r,o,n="table",s=!1,a=!1;for(let i=0;i<t.length;i++){let d=t[i];switch(d){case"--baseline":r=t[++i];break;case"--export-json":o=t[++i];break;case"--format":n=t[++i];break;case"--quiet":s=!0;break;case"--help":case"-h":a=!0;break;default:e.push(d)}}return{paths:e,baseline:r,exportJson:o,format:n,quiet:s,help:a}}async function ie(t){let e=ae(t);if(e.help)return process.stdout.write(W),0;let r,o;if(e.baseline)r=e.baseline,o=e.paths[0];else r=e.paths[0],o=e.paths[1];if(!r||!o)return process.stdout.write(W),2;let n,s;try{[n,s]=await Promise.all([g(r),g(o)])}catch(c){return process.stderr.write(`Failed to load documents: ${c instanceof Error?c.message:String(c)}
113
- `),2}let a=_(n,s),i={...s,comparisons:a};if(e.exportJson)await b(i,e.exportJson);if(!e.quiet){let l=await m[e.format].render(i,{});await w(l)}return a.some((c)=>c.verdict==="fail")?1:0}function ue(t){let e,r="table",o=!1;for(let n=0;n<t.length;n++){let s=t[n];switch(s){case"--format":r=t[++n];break;case"--help":case"-h":o=!0;break;default:e=s}}return{path:e,format:r,help:o}}async function ce(t){let e=ue(t);if(e.help||!e.path)return process.stdout.write(Y),e.help?0:2;let r;try{r=await g(e.path)}catch(s){return process.stderr.write(`Failed to load ${e.path}: ${s instanceof Error?s.message:String(s)}
114
- `),2}let n=await m[e.format].render(r,{});return await w(n),0}var le={ascii:"table"};function de(t){let e,r,o,n,s=!1;for(let a=0;a<t.length;a++){let i=t[a];switch(i){case"--format":{let d=t[++a]??"";r=le[d]??d;break}case"--run":o=t[++a];break;case"--out-dir":n=t[++a];break;case"--help":case"-h":s=!0;break;default:e=i}}return{path:e,format:r,runId:o,outDir:n,help:s}}async function pe(t){let e=de(t);if(e.help||!e.path||!e.format)return process.stdout.write(ee),e.help?0:2;if(!(e.format in m))return process.stderr.write(`Unknown --format "${e.format}". Expected one of: ${Object.keys(m).join(", ")}, ascii
115
- `),2;let r;try{r=await g(e.path)}catch(s){return process.stderr.write(`Failed to load ${e.path}: ${s instanceof Error?s.message:String(s)}
116
- `),2}let n=await m[e.format].render(r,{runId:e.runId});if(!n.text&&(!n.files||n.files.length===0))return process.stderr.write(e.runId?`No CPU evidence found for run "${e.runId}".
115
+ `;function ne(p){let l=[],h,x,g=!1,k=!1,P,C,D,R="table",A=!1,F=!1;for(let j=0;j<p.length;j++){let y=p[j];switch(y){case"--runs":h=Number(p[++j]);break;case"--warmup":x=Number(p[++j]);break;case"--cpu":g=!0;break;case"--heap":k=!0;break;case"--cpu-interval":P=Number(p[++j]);break;case"--out-dir":C=p[++j];break;case"--export-json":D=p[++j];break;case"--format":R=p[++j];break;case"--quiet":A=!0;break;case"--help":case"-h":F=!0;break;default:l.push(y)}}return{commands:l,runs:h,warmup:x,cpu:g,heap:k,cpuIntervalUs:P,outDir:C,exportJson:D,format:R,quiet:A,help:F}}async function oe(p){let l=ne(p);if(l.help||l.commands.length===0)return process.stdout.write(Y),l.help?0:2;if(!(l.format in n))return process.stderr.write(`Unknown --format "${l.format}". Expected one of: ${Object.keys(n).join(", ")}
116
+ `),2;let h;try{h=await w({commands:l.commands,runs:l.runs,warmup:l.warmup,cpu:l.cpu,heap:l.heap,cpuIntervalUs:l.cpuIntervalUs,outDir:l.outDir})}catch(g){return process.stderr.write(`Run failed: ${g instanceof Error?g.message:String(g)}
117
+ `),2}if(l.exportJson)await o(h,l.exportJson);if(!l.quiet){let k=await n[l.format].render(h,{});await E(k)}return h.runs.some((g)=>g.trials.some((k)=>k.exitCode!==void 0&&k.exitCode!==0))?1:0}function ae(p){let l=[],h,x,g=!1,k,P,C,D="table",R=!1,A=!1;for(let F=0;F<p.length;F++){let j=p[F];switch(j){case"--time-budget":h=Number(p[++F]);break;case"--min-samples":x=Number(p[++F]);break;case"--gc":g=!0;break;case"--filter":k=p[++F];break;case"--out-dir":P=p[++F];break;case"--export-json":C=p[++F];break;case"--format":D=p[++F];break;case"--quiet":R=!0;break;case"--help":case"-h":A=!0;break;default:l.push(j)}}return{suites:l,timeBudgetMs:h,minSamples:x,gc:g,filter:k,outDir:P,exportJson:C,format:D,quiet:R,help:A}}async function ie(p){let l=ae(p);if(l.help||l.suites.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(", ")}
118
+ `),2;let h;try{h=await m({suites:l.suites,timeBudgetMs:l.timeBudgetMs,minSamples:l.minSamples,gc:l.gc,filter:l.filter,outDir:l.outDir})}catch(x){return process.stderr.write(`Bench failed: ${x instanceof Error?x.message:String(x)}
119
+ `),2}if(l.exportJson)await o(h,l.exportJson);if(!l.quiet){let g=await n[l.format].render(h,{});await E(g)}return 0}function ue(p){let l=[],h,x,g="table",k=!1,P=!1;for(let C=0;C<p.length;C++){let D=p[C];switch(D){case"--baseline":h=p[++C];break;case"--export-json":x=p[++C];break;case"--format":g=p[++C];break;case"--quiet":k=!0;break;case"--help":case"-h":P=!0;break;default:l.push(D)}}return{paths:l,baseline:h,exportJson:x,format:g,quiet:k,help:P}}async function ce(p){let l=ue(p);if(l.help)return process.stdout.write(K),0;let h,x;if(l.baseline)h=l.baseline,x=l.paths[0];else h=l.paths[0],x=l.paths[1];if(!h||!x)return process.stdout.write(K),2;let g,k;try{[g,k]=await Promise.all([t(h),t(x)])}catch(R){return process.stderr.write(`Failed to load documents: ${R instanceof Error?R.message:String(R)}
120
+ `),2}let P=d(g,k),C={...k,comparisons:P};if(l.exportJson)await o(C,l.exportJson);if(!l.quiet){let A=await n[l.format].render(C,{});await E(A)}return P.some((R)=>R.verdict==="fail")?1:0}function le(p){let l,h="table",x=!1;for(let g=0;g<p.length;g++){let k=p[g];switch(k){case"--format":h=p[++g];break;case"--help":case"-h":x=!0;break;default:l=k}}return{path:l,format:h,help:x}}async function de(p){let l=le(p);if(l.help||!l.path)return process.stdout.write(te),l.help?0:2;let h;try{h=await t(l.path)}catch(k){return process.stderr.write(`Failed to load ${l.path}: ${k instanceof Error?k.message:String(k)}
121
+ `),2}let g=await n[l.format].render(h,{});return await E(g),0}var pe={ascii:"table"};function me(p){let l,h,x,g,k=!1;for(let P=0;P<p.length;P++){let C=p[P];switch(C){case"--format":{let D=p[++P]??"";h=pe[D]??D;break}case"--run":x=p[++P];break;case"--out-dir":g=p[++P];break;case"--help":case"-h":k=!0;break;default:l=C}}return{path:l,format:h,runId:x,outDir:g,help:k}}async function fe(p){let l=me(p);if(l.help||!l.path||!l.format)return process.stdout.write(re),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
122
+ `),2;let h;try{h=await t(l.path)}catch(k){return process.stderr.write(`Failed to load ${l.path}: ${k instanceof Error?k.message:String(k)}
123
+ `),2}let g=await n[l.format].render(h,{runId:l.runId});if(!g.text&&(!g.files||g.files.length===0))return process.stderr.write(l.runId?`No CPU evidence found for run "${l.runId}".
117
124
  `:`No CPU evidence found in this document (no cpu-phase runs). Capture some with "ostia run --cpu ...".
118
- `),2;return await w(n,e.outDir),0}function me(t){let e=!1,r,o,n=!1,s=!1;for(let a=0;a<t.length;a++)switch(t[a]){case"--full":e=!0;break;case"--baseline":r=t[++a];break;case"--export-json":o=t[++a];break;case"--quiet":n=!0;break;case"--help":case"-h":s=!0;break}return{full:e,baseline:r,exportJson:o,quiet:n,help:s}}async function fe(t){let e=me(t);if(e.help)return process.stdout.write(te),0;let r=await B();if(!r)return process.stderr.write(`No ostia.config.json found. "ostia ci" needs configured workloads.
119
- `),2;if(r.workloads.length===0)return process.stderr.write(`ostia.config.json has no "workloads" configured.
120
- `),2;let o;try{o=await L({config:r,full:e.full,baselineName:e.baseline})}catch(n){if(n instanceof x)return process.stderr.write(`${n.message}
121
- `),2;return process.stderr.write(`CI run failed: ${n instanceof Error?n.message:String(n)}
122
- `),2}if(e.exportJson)await b(o.document,e.exportJson);if(!e.quiet)process.stdout.write(V(o.summary));return o.summary.regressed>0?1:0}async function he(){let[t,...e]=process.argv.slice(2);switch(t){case"run":return ne(e);case"bench":return oe(e);case"compare":return ie(e);case"report":return ce(e);case"ci":return fe(e);case"viz":return pe(e);case void 0:case"--help":case"-h":return process.stdout.write(`ostia - Bun-native profile IR engine
125
+ `),2;return await E(g,l.outDir),0}function he(p){let l=!1,h,x,g=!1,k=!1;for(let P=0;P<p.length;P++)switch(p[P]){case"--full":l=!0;break;case"--baseline":h=p[++P];break;case"--export-json":x=p[++P];break;case"--quiet":g=!0;break;case"--help":case"-h":k=!0;break}return{full:l,baseline:h,exportJson:x,quiet:g,help:k}}async function ge(p){let l=he(p);if(l.help)return process.stdout.write(se),0;let h=await M();if(!h)return process.stderr.write(`No ostia.config.json found. "ostia ci" needs configured workloads.
126
+ `),2;if(h.workloads.length===0)return process.stderr.write(`ostia.config.json has no "workloads" configured.
127
+ `),2;let x;try{x=await W({config:h,full:l.full,baselineName:l.baseline})}catch(g){if(g instanceof S)return process.stderr.write(`${g.message}
128
+ `),2;return process.stderr.write(`CI run failed: ${g instanceof Error?g.message:String(g)}
129
+ `),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 be(){let[p,...l]=process.argv.slice(2);switch(p){case"run":return oe(l);case"bench":return ie(l);case"compare":return ce(l);case"report":return de(l);case"ci":return ge(l);case"viz":return fe(l);case void 0:case"--help":case"-h":return process.stdout.write(`ostia - Bun-native profile IR engine
123
130
 
124
131
  Commands:
125
132
  run Run commands N times and report timing/CPU/heap
@@ -130,5 +137,5 @@ Commands:
130
137
  viz Render CPU evidence as collapsed/mermaid/speedscope/cpuprofile
131
138
 
132
139
  Run "ostia <command> --help" for details.
133
- `),t===void 0?2:0;default:return process.stderr.write(`Unknown subcommand "${t}". Run "ostia --help".
134
- `),2}}if(import.meta.main)he().then((t)=>process.exit(t));
140
+ `),p===void 0?2:0;default:return process.stderr.write(`Unknown subcommand "${p}". Run "ostia --help".
141
+ `),2}}if(import.meta.main)be().then((p)=>process.exit(p));
package/index.d.ts CHANGED
@@ -48,6 +48,10 @@ interface Workload {
48
48
  file: string;
49
49
  task: string;
50
50
  };
51
+ /** Marks this task as the in-run Relative reference for its group (see
52
+ * `task(name, fn, { baseline: true })`). At most one per group is
53
+ * meaningful; renderers use the first they encounter. */
54
+ baseline?: boolean;
51
55
  }
52
56
 
53
57
  type Phase = "timing" | "cpu" | "heap" | "memstats";
@@ -218,15 +222,27 @@ interface BenchOptions {
218
222
  timeBudgetMs?: number;
219
223
  minSamples?: number;
220
224
  gc?: boolean;
225
+ filter?: string;
221
226
  outDir?: string;
222
227
  cwd?: string;
223
228
  }
224
229
 
225
230
  export declare function bench(opts: BenchOptions): Promise<ProfileDocument>;
226
231
 
232
+ export interface TaskOptions {
233
+ /** Marks this task as the Relative reference for its group in the table
234
+ * renderer, mirroring mitata's `baseline()`. At most one per group. */
235
+ baseline?: boolean;
236
+ /** Per-task time budget; overrides the suite-wide `--time-budget` / `timeBudgetMs`. */
237
+ timeBudgetMs?: number;
238
+ /** Per-task hard floor on trials; overrides the suite-wide `--min-samples` /
239
+ * `minSamples`. */
240
+ minSamples?: number;
241
+ }
242
+
227
243
  export declare function group(name: string, fn: () => void): void;
228
244
 
229
- export declare function task(name: string, fn: () => unknown | Promise<unknown>): void;
245
+ export declare function task(name: string, fn: () => unknown | Promise<unknown>, opts?: TaskOptions): void;
230
246
 
231
247
  interface Thresholds {
232
248
  timingPct: number;
package/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{a as c,c as d,f as g,g as h,h as i}from"./chunk-j0j2b0fj.js";import{u as a,v as b,y as e,z as f}from"./chunk-ck12vbed.js";export{c as bench,d as compareDocuments,e as group,b as loadDocument,i as profile,g as renderers,h as run,a as saveDocument,f as task};
2
+ import{m,d,n,w,I}from"./chunk-m8zhsw7r.js";import{o,t,F,D}from"./chunk-qh19pbhc.js";export{m as bench,d as compareDocuments,F as group,t as loadDocument,I as profile,n as renderers,w as run,o as saveDocument,D as task};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ostia",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Fast profiling and benchmarking for Bun.",
5
5
  "type": "module",
6
6
  "exports": {
package/runner.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- import{A as P,B as E,l as M,o as F,p as N,s as y,u as I,w as B,x as h}from"./chunk-ck12vbed.js";var A=500,D=20,O=0.1,k=1000,S=0;function d(n){if(typeof n==="number")S+=n;else if(n!==void 0&&n!==null)S+=1}function x(n){return n!==null&&typeof n==="object"&&typeof n.then==="function"}async function b(n,t={}){let r=(t.timeBudgetMs??A)*1e6,e=t.minSamples??D,c=r*(t.warmupFraction??O),p=Bun.nanoseconds();while(Bun.nanoseconds()-p<c)d(await n());let m=Bun.nanoseconds();d(await n());let a=Math.max(1,Bun.nanoseconds()-m),s=a<k?Math.max(1,Math.ceil(k/a)):1,i=[],u=Bun.nanoseconds(),o=0,l=0;while(l<e||o<r){let g=Bun.nanoseconds();for(let T=0;T<s;T++){let w=n();d(x(w)?await w:w)}let R=Bun.nanoseconds();if(i.push({i:l,wallNs:(R-g)/s}),l++,o=Bun.nanoseconds()-u,t.gc)Bun.gc(!0)}let _=i.map((g)=>g.wallNs),f=B(_),L=h(f,[],"inprocess");return{trials:i,timing:f,warnings:L}}async function U(){let[n,t,r]=process.argv.slice(2);if(!n||!t)return process.stderr.write(`bench runner: usage: runner.ts <suiteFile> <outputPath> [optsJson]
4
- `),2;let e=r?JSON.parse(r):{};E(),await import(n);let c=P();if(c.length===0)return process.stderr.write(`bench runner: ${n} registered no tasks (no task() calls found).
5
- `),2;let p=y({timeBudgetMs:e.timeBudgetMs??null,minSamples:e.minSamples??null,gc:e.gc??!1}),m=[],a=[];for(let s of c){let i=s.groupName?`${s.groupName}/${s.name}`:s.name,u=F(n,i,i);m.push(u);let o=await b(s.fn,e);a.push(N({workload:u,configFingerprint:p,trials:o.trials,timing:o.timing,warnings:o.warnings}))}return await I(M(m,a),t),0}U().then((n)=>process.exit(n));
3
+ import{r,R,i,s,o,l,p,T,C,x,N}from"./chunk-qh19pbhc.js";var U=500,W=20,J=3,z=0.1,H=1000,G=1e4,A=0;function b(n){if(typeof n==="number")A+=n;else if(n!==void 0&&n!==null)A+=1}function I(n){return n!==null&&typeof n==="object"&&typeof n.then==="function"}function F(n,a){return Math.max(1,Math.ceil(H/n),Math.ceil(a/(n*G)))}async function L(n,a={}){let m=(a.timeBudgetMs??U)*1e6,h=m*(a.warmupFraction??z),k=Bun.nanoseconds(),d=0,f=0;while(f<h){let e=n();b(I(e)?await e:e),d++,f=Bun.nanoseconds()-k}let c;if(d>0)c=Math.max(1,f/d);else{let e=Bun.nanoseconds(),g=n();b(I(g)?await g:g),c=Math.max(1,Bun.nanoseconds()-e)}let t=F(c,m);if(t>1){let e=Bun.nanoseconds();for(let g=0;g<t;g++){let w=n();b(I(w)?await w:w)}c=Math.max(1,(Bun.nanoseconds()-e)/t),t=F(c,m)}let M=c*t,B=a.minSamples??Math.min(W,Math.max(J,Math.floor(m/M))),u=[],S=Bun.nanoseconds(),E=0,_=0;while(_<B||E<m){let e=Bun.nanoseconds();for(let w=0;w<t;w++){let O=n();b(I(O)?await O:O)}let g=Bun.nanoseconds();if(u.push({i:_,wallNs:(g-e)/t}),_++,E=Bun.nanoseconds()-S,a.gc)Bun.gc(!0)}let P=u.map((e)=>e.wallNs),y=l(P),D=p(y,[],"inprocess");return{trials:u,timing:y,warnings:D}}async function j(){let[n,a,m]=process.argv.slice(2);if(!n||!a)return process.stderr.write(`bench runner: usage: runner.ts <suiteFile> <outputPath> [optsJson]
4
+ `),2;let h=m?JSON.parse(m):{};C(),await import(n);let k=T();if(k.length===0)return process.stderr.write(`bench runner: ${n} registered no tasks (no task() calls found).
5
+ `),2;let d=N(k,h.filter);if(d.length===0)return process.stderr.write(`bench runner: --filter ${JSON.stringify(h.filter)} matched zero of ${k.length} registered tasks in ${n}.
6
+ `),2;let f=[],c=[];for(let t of d){let M=x(t),B=R(n,M,M,t.baseline);f.push(B);let u={...h,...t.opts?.timeBudgetMs!==void 0&&{timeBudgetMs:t.opts.timeBudgetMs},...t.opts?.minSamples!==void 0&&{minSamples:t.opts.minSamples}},S=await L(t.fn,u);c.push(i({workload:B,configFingerprint:s({timeBudgetMs:u.timeBudgetMs??null,minSamples:u.minSamples??null,gc:u.gc??!1}),trials:S.trials,timing:S.timing,warnings:S.warnings}))}return await o(r(f,c),a),0}j().then((n)=>process.exit(n));
package/chunk-ck12vbed.js DELETED
@@ -1,4 +0,0 @@
1
- // @bun
2
- function N(n){return JSON.stringify(d(n))}function d(n){if(Array.isArray(n))return n.map(d);if(n!==null&&typeof n==="object"){let e={};for(let r of Object.keys(n).sort())e[r]=d(n[r]);return e}return n}function c(n,...e){let r=Bun.CryptoHasher.hash("sha256",N(e),"hex");return`${n}_${r.slice(0,16)}`}var k="0.1.0";function E(n,e){return{schemaVersion:1,toolVersion:k,bunVersion:Bun.version,platform:{os:process.platform,arch:process.arch},createdAt:new Date().toISOString(),workloads:n,runs:e}}function O(n,e){return{id:c("wl","subprocess",n,process.cwd()),kind:"subprocess",command:n,label:e}}function C(n,e){return{id:c("wl","inprocess",n.name,n.toString()),kind:"inprocess",label:e}}function q(n,e,r){return{id:c("wl","inprocess-entry",n,e),kind:"inprocess",entry:{file:n,task:e},label:r}}function _(n){return{id:c("run",n.workload.id,"timing",n.configFingerprint,Bun.version,k),workloadId:n.workload.id,phase:"timing",instrumented:!1,configFingerprint:n.configFingerprint,trials:n.trials,timing:n.timing,warnings:n.warnings,artifacts:[],memory:B(n.trials)}}function B(n){let e=n.map((r)=>r.maxRssBytes).filter((r)=>r!==void 0);if(e.length===0)return;return{origin:"resourceUsage",perTrial:n.map((r)=>({rssBytes:r.maxRssBytes})),maxRssBytes:Math.max(...e)}}function H(n){return{id:c("run",n.workload.id,n.phase,n.configFingerprint,Bun.version,k),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 J(n,e,r){let i=await Bun.file(r).arrayBuffer(),o=new Bun.CryptoHasher("sha256");return o.update(i),{id:c("art",n,e,r),kind:e,path:r,sha256:o.digest("hex"),bytes:i.byteLength}}function j(n){return c("cfg",n)}function D(n){return`${JSON.stringify(d(n),null,2)}
3
- `}async function L(n,e){await Bun.write(e,D(n))}async function z(n){let e=await Bun.file(n).text();return JSON.parse(e)}var x=[],m;function K(n,e){let r=m;m=n;try{e()}finally{m=r}}function U(n,e){x.push({groupName:m,name:n,fn:e})}function G(){return x}function Z(){x.length=0,m=void 0}function X(n){if(n.length===0)throw Error("computeTimingStats: samples must be non-empty");let e=n.length,r=b(n),t=0;for(let a=0;a<e;a++)t+=n[a];let i=t/e,o=g(r,0.5),s=0;for(let a=0;a<e;a++){let u=n[a]-i;s+=u*u}let p=Math.sqrt(s/e),y=r[0],f=r[e-1],h=g(r,0.25),w=g(r,0.75),l=w-h,v=h-1.5*l,W=w+1.5*l,S=h-3*l,F=w+3*l,R=0,T=0;for(let a=0;a<e;a++){let u=n[a];if(u<S||u>F)T++;else if(u<v||u>W)R++}return{unit:"ns",samples:n,mean:i,median:o,stddev:p,min:y,max:f,outliers:{mild:R,severe:T}}}function b(n){let e=new Float64Array(n.length);return e.set(n),e.sort(),e}function g(n,e){let r=n.length;if(r===1)return n[0];let t=e*(r-1),i=Math.floor(t),o=Math.ceil(t);if(i===o)return n[i];let s=t-i;return n[i]*(1-s)+n[o]*s}var I=5000000,A=200;function Y(n,e,r="subprocess"){let t=[],i=n.samples[0];if(i!==void 0){let s=b(n.samples),p=g(s,0.25),f=g(s,0.75)-p;if(i>n.median+3*f&&f>0)t.push({code:"slow-first-run",message:`First run took ${(i/1e6).toFixed(2)}ms, much slower than the median ${(n.median/1e6).toFixed(2)}ms. Consider more warmup.`,data:{firstNs:i,medianNs:n.median}})}if(n.outliers.mild+n.outliers.severe>0)t.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(r==="subprocess"&&n.median<I)t.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(r==="inprocess"&&n.median<A)t.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 o=e.filter((s)=>s!==void 0&&s!==0);if(o.length>0)t.push({code:"nonzero-exit",message:`${o.length} of ${e.length} trial(s) exited non-zero.`,data:{exitCodes:o}});return t}
4
- export{N as i,c as j,k,E as l,O as m,C as n,q as o,_ as p,H as q,J as r,j as s,D as t,L as u,z as v,X as w,Y as x,K as y,U as z,G as A,Z as B};
package/chunk-j0j2b0fj.js DELETED
@@ -1,19 +0,0 @@
1
- // @bun
2
- import{i as z,j as k,l as E,m as $e,n as Ce,p as Ie,q as j,r as Ne,s as G,t as pe,v as H,w as re,x as se}from"./chunk-ck12vbed.js";function Ue(e){return e.startsWith("file://")?e.slice(7):e}function W(e,a,n){let s=e.nodes,t=s.length,i=new Map,o=[],r=new Map,c=new Int32Array(t);for(let m=0;m<t;m++){let d=s[m],u=d.callFrame,y=Ue(u.url),T=i.get(u.functionName);if(T===void 0)T=new Map,i.set(u.functionName,T);let I=T.get(y);if(I===void 0)I=o.length,T.set(y,I),o.push({key:k("fr",u.functionName,y),name:u.functionName,url:y||void 0,line:u.lineNumber>=0?u.lineNumber:void 0,col:u.columnNumber>=0?u.columnNumber:void 0});c[m]=I,r.set(d.id,m)}let f=Array(t);for(let m=0;m<t;m++){let d=s[m];f[m]={id:d.id,frameIx:c[r.get(d.id)],children:d.children??[]}}let p=new Float64Array(t),l=new Float64Array(t),g=e.samples,x=e.timeDeltas;for(let m=0;m<g.length;m++){let d=r.get(g[m]);if(d===void 0)continue;p[d]+=x[m]??0,l[d]+=1}let R=new Int32Array(t).fill(-1);for(let m=0;m<t;m++){let d=s[m].children;if(!d)continue;for(let u of d){let y=r.get(u);if(y!==void 0)R[y]=m}}let h=[],w=[];for(let m=t-1;m>=0;m--)if(R[m]===-1)w.push(m);while(w.length>0){let m=w.pop();h.push(m);let d=s[m].children;if(!d)continue;for(let u of d){let y=r.get(u);if(y!==void 0&&R[y]===m)w.push(y)}}let P=new Float64Array(t);for(let m=h.length-1;m>=0;m--){let d=h[m];P[d]+=p[d];let u=R[d];if(u>=0)P[u]+=P[d]}let C=Array(o.length),b=[];for(let m=0;m<t;m++){let d=f[m].frameIx,u=C[d];if(u)u.selfUs+=p[m],u.totalUs+=P[m],u.samples+=l[m];else{let y={frameIx:d,selfUs:p[m],totalUs:P[m],samples:l[m]};C[d]=y,b.push(y)}}return{origin:a,samplingIntervalUs:n,frames:o,nodes:f,totals:b.sort((m,d)=>d.selfUs-m.selfUs),samples:{nodeIds:e.samples,timeDeltasUs:e.timeDeltas}}}function ve(e,a,n,s){let t=["--cpu-prof","--cpu-prof-dir",a,"--cpu-prof-name",n,"--cpu-prof-interval",String(s)],i=e[0];if(i==="bun"||i?.endsWith("/bun"))return[i,...t,...e.slice(1)];return e}async function Y(e){let a=`${e.artifactDir}/${e.fileName}`,n=e.argv[0],s=n==="bun"||n?.endsWith("/bun"),t=ve(e.argv,e.artifactDir,e.fileName,e.intervalUs),i=s?e.env:{...process.env,...e.env,BUN_OPTIONS:`--cpu-prof --cpu-prof-dir ${e.artifactDir} --cpu-prof-name ${e.fileName} --cpu-prof-interval ${e.intervalUs}`},o=Bun.nanoseconds(),c=await Bun.spawn(t,{cwd:e.cwd,env:i,stdout:"ignore",stderr:"ignore",stdin:"ignore"}).exited,f=Bun.nanoseconds()-o,p=Bun.file(a);if(!await p.exists())return{diagnosticWallNs:f,exitCode:c,warnings:[{code:"artifact-missing",message:`Expected a .cpuprofile at ${a} after exit ${c}, found nothing. The workload's argv[0] must be a \`bun\` binary for CPU capture.`,data:{artifactPath:a,argv:e.argv}}]};let l=await p.json(),g=W(l,"cpu-prof",e.intervalUs),x=l.samples.length===0?[{code:"empty-profile",message:"CPU capture produced zero samples."}]:[];return{diagnosticWallNs:f,exitCode:c,artifactPath:a,cpu:g,warnings:x}}function q(e,a="heap-prof"){let{node_fields:n,node_types:s}=e.snapshot.meta,t=n.indexOf("type"),i=n.indexOf("self_size"),o=n.length,r=s[0];if(t===-1||i===-1||!Array.isArray(r))return{origin:a,typeCounts:[],objectCount:e.snapshot.node_count};let c=r.length,f=Array(c),p=new Map,l=[],g=0,x=e.nodes,R=x.length;for(let b=0;b<R;b+=o){let m=x[b+t],d=x[b+i]??0;g+=d;let u;if(m>=0&&m<c){if(u=f[m],u===void 0)u={type:r[m],count:0,bytes:0},f[m]=u,l.push(u)}else{let y=`unknown(${m})`;if(u=p.get(y),u===void 0)u={type:y,count:0,bytes:0},p.set(y,u),l.push(u)}u.count++,u.bytes+=d}let h=l.sort((b,m)=>m.count-b.count),w=h.slice(0,20),P=h.slice(20),C=w.map(({type:b,count:m,bytes:d})=>({type:b,count:m,retainedBytes:d}));if(P.length>0){let b=0,m=0;for(let d of P)b+=d.count,m+=d.bytes;C.push({type:"other",count:b,retainedBytes:m})}return{origin:a,heapSizeBytes:g,objectCount:e.snapshot.node_count,typeCounts:C}}function ke(e,a,n){let s=["--heap-prof","--heap-prof-dir",a,"--heap-prof-name",n],t=e[0];if(t==="bun"||t?.endsWith("/bun"))return[t,...s,...e.slice(1)];return e}async function Q(e){let a=`${e.artifactDir}/${e.fileName}`,n=e.argv[0],s=n==="bun"||n?.endsWith("/bun"),t=ke(e.argv,e.artifactDir,e.fileName),i=s?e.env:{...process.env,...e.env,BUN_OPTIONS:`--heap-prof --heap-prof-dir ${e.artifactDir} --heap-prof-name ${e.fileName}`},o=Bun.nanoseconds(),c=await Bun.spawn(t,{cwd:e.cwd,env:i,stdout:"ignore",stderr:"ignore",stdin:"ignore"}).exited,f=Bun.nanoseconds()-o,p=Bun.file(a);if(!await p.exists())return{diagnosticWallNs:f,exitCode:c,warnings:[{code:"artifact-missing",message:`Expected a heap snapshot at ${a} after exit ${c}, found nothing. The workload's argv[0] must be a \`bun\` binary for heap capture.`,data:{artifactPath:a,argv:e.argv}}]};let l=await p.json(),g=q(l,"heap-prof");return{diagnosticWallNs:f,exitCode:c,artifactPath:a,heap:g,warnings:[]}}import{Session as Fe}from"inspector/promises";var De=1000;async function X(e,a={}){let n=a.intervalUs??De,s=new Fe;s.connect();let t=Bun.nanoseconds();try{await s.post("Profiler.enable"),await s.post("Profiler.setSamplingInterval",{interval:n}),await s.post("Profiler.start");let i=await e(),{profile:o}=await s.post("Profiler.stop"),r=Bun.nanoseconds()-t,c=W(o,"inspector",n);return{result:i,cpu:c,diagnosticWallNs:r}}finally{s.disconnect()}}import{profile as Se}from"bun:jsc";var Me=new Map([["LLInt","llint"],["Baseline","baseline"],["DFG","dfg"],["FTL","ftl"]]),Z=4294967295;function ee(e,a){let n=a??e.interval*1e6,s=new Map,t=[];function i(u,y,T,I){let U=s.get(u);if(U===void 0)U=new Map,s.set(u,U);let N=y??"",v=U.get(N);if(v===void 0)v=t.length,U.set(N,v),t.push({key:k("fr",u,N),name:u,url:y,line:T,col:I});return v}function o(u){let y=u.line===Z,T=y?void 0:u.line-1,I=y||u.column===Z?void 0:u.column-1;return i(u.name,u.sourceURL,T,I)}let r=i("(root)",void 0,void 0,void 0),c=1,f={id:0,frameIx:r,children:new Map,selfUs:0,samples:0,totalUs:0},p=new Map([[0,f]]),l={llint:0,baseline:0,dfg:0,ftl:0},g=new Map,x=[],R=[];for(let u of e.traces){let y=u.frames,T=f;for(let N=y.length-1;N>=0;N--){let v=o(y[N]),M=T.children.get(v);if(!M)M={id:c++,frameIx:v,children:new Map,selfUs:0,samples:0,totalUs:0},T.children.set(v,M),p.set(M.id,M);T=M}T.selfUs+=n,T.samples+=1,x.push(T.id),R.push(n);let I=y[0],U=I&&Me.get(I.category);if(U){l[U]++;let N=g.get(U)??new Map;N.set(T.frameIx,(N.get(T.frameIx)??0)+1),g.set(U,N)}}function h(u){let y=u.selfUs;for(let T of u.children.values())y+=h(T);return u.totalUs=y,y}h(f);let w=new Map;function P(u){let y=w.get(u.frameIx);if(y)y.selfUs+=u.selfUs,y.totalUs+=u.totalUs,y.samples+=u.samples;else w.set(u.frameIx,{frameIx:u.frameIx,selfUs:u.selfUs,totalUs:u.totalUs,samples:u.samples});for(let T of u.children.values())P(T)}P(f);let C=[...p.values()].map((u)=>({id:u.id,frameIx:u.frameIx,children:[...u.children.values()].map((y)=>y.id)})),b={origin:"jsc-profile",samplingIntervalUs:n,frames:t,nodes:C,totals:[...w.values()].sort((u,y)=>y.selfUs-u.selfUs),samples:{nodeIds:x,timeDeltasUs:R}},m=[...g.entries()].flatMap(([u,y])=>[...y.entries()].sort((T,I)=>I[1]-T[1]).slice(0,3).map(([T,I])=>({tier:u,frameKey:t[T].key,samples:I})));return{cpu:b,jit:{origin:"jsc-profile",tiers:l,topFramesByTier:m}}}var Be=1000;async function ne(e,a={}){let n=a.intervalUs??Be,s,t=Bun.nanoseconds(),i=await Se(async()=>(s=await e(),s),n),o=Bun.nanoseconds()-t,{cpu:r,jit:c}=ee(i.stackTraces,n);return{result:s,cpu:r,jit:c,diagnosticWallNs:o}}async function L(e){let a=Bun.nanoseconds(),n=Bun.spawn(e.argv,{cwd:e.cwd,env:e.env,stdout:"ignore",stderr:"ignore",stdin:"ignore"}),s=await n.exited,t=Bun.nanoseconds(),i=n.resourceUsage?.();return{wallNs:t-a,exitCode:s,userNs:i?Number(i.cpuTime.user)*1000:void 0,systemNs:i?Number(i.cpuTime.system)*1000:void 0,maxRssBytes:i?.maxRSS}}function te(e){return e.trim().split(/\s+/).filter(Boolean)}var Oe=10,We=3000000000,Ee=3;async function oe(e){let a=e.warmup??Ee;for(let p=0;p<a;p++)await L(e);let n=[],s=e.runs??e.minRuns??Oe,t=e.runs!==void 0?0:e.minTotalNs??We,i=0,o=0;while(o<s||i<t){let p=await L(e);if(n.push({i:o,wallNs:p.wallNs,exitCode:p.exitCode,userNs:p.userNs,systemNs:p.systemNs,maxRssBytes:p.maxRssBytes}),i+=p.wallNs,o++,e.runs!==void 0&&o>=e.runs)break}let r=n.map((p)=>p.wallNs),c=re(r),f=se(c,n.map((p)=>p.exitCode));return{trials:n,timing:c,warnings:f}}var Ae=new URL("./runner.ts",import.meta.url).pathname,_e=".ostia";async function je(e){let n=`${e.outDir??_e}/bench-tmp`,s=e.cwd??process.cwd(),t={timeBudgetMs:e.timeBudgetMs,minSamples:e.minSamples,gc:e.gc},i=[],o=[];try{for(let r of e.suites){let c=r.startsWith("/")?r:`${s}/${r}`,f=`${n}/${k("bench-out",c)}.json`,l=await Bun.spawn(["bun",Ae,c,f,JSON.stringify(t)],{cwd:s,stdout:"inherit",stderr:"inherit",stdin:"ignore"}).exited;if(l!==0)throw Error(`Bench suite failed: ${r} (runner exited ${l})`);let g=await H(f);i.push(...g.workloads),o.push(...g.runs)}}finally{await Bun.spawn(["rm","-rf",n]).exited}return E(i,o)}var ie={timingPct:5,frameSelfPct:10,heapTypePct:10,minFrameSelfUs:1000};function A(e,a){if(e===0)return a===0?0:1/0;return(a-e)/e*100}function S(e,a,n){return e.runs.find((s)=>s.workloadId===a&&s.phase===n)}function Le(e,a,n=ie){let s=new Set(a.workloads.map((i)=>i.id)),t=[];for(let i of e.workloads){if(!s.has(i.id))continue;let o=He(e,a,i.id,n);if(o)t.push(o)}return t}function He(e,a,n,s=ie){let t=S(e,n,"timing"),i=S(a,n,"timing"),o=S(e,n,"cpu"),r=S(a,n,"cpu"),c=S(e,n,"heap"),f=S(a,n,"heap"),p=t?.id??o?.id??c?.id,l=i?.id??r?.id??f?.id;if(!p||!l)return;let g=!1,x;if(t?.timing&&i?.timing){let w=A(t.timing.median,i.timing.median),P=A(t.timing.mean,i.timing.mean),C=w>s.timingPct?"regressed":w<-s.timingPct?"improved":"unchanged";if(C==="regressed")g=!0;x={medianDeltaPct:w,meanDeltaPct:P,verdict:C}}let R;if(o?.cpu&&r?.cpu){let w=new Map(o.cpu.totals.map((d)=>[o.cpu.frames[d.frameIx].key,d])),P=new Map(r.cpu.totals.map((d)=>[r.cpu.frames[d.frameIx].key,d])),C=new Map(o.cpu.frames.map((d)=>[d.key,d.name])),b=new Map(r.cpu.frames.map((d)=>[d.key,d.name]));R=[...new Set([...w.keys(),...P.keys()])].map((d)=>{let u=w.get(d)?.selfUs??0,y=P.get(d)?.selfUs??0;return{frameKey:d,name:b.get(d)??C.get(d)??d,baseSelfUs:u,candSelfUs:y,deltaPct:A(u,y)}}).sort((d,u)=>Math.abs(u.deltaPct)-Math.abs(d.deltaPct));for(let d of R)if((d.baseSelfUs>=s.minFrameSelfUs||d.candSelfUs>=s.minFrameSelfUs)&&d.deltaPct>s.frameSelfPct)g=!0}let h;if(c?.heap&&f?.heap){let w=new Map(c.heap.typeCounts.map((b)=>[b.type,b])),P=new Map(f.heap.typeCounts.map((b)=>[b.type,b]));h=[...new Set([...w.keys(),...P.keys()])].map((b)=>{let m=w.get(b),d=P.get(b);return{type:b,baseCount:m?.count??0,candCount:d?.count??0,baseBytes:m?.retainedBytes,candBytes:d?.retainedBytes,deltaPct:A(m?.count??0,d?.count??0)}}).sort((b,m)=>Math.abs(m.deltaPct)-Math.abs(b.deltaPct));for(let b of h)if(b.deltaPct>s.heapTypePct)g=!0}return{id:k("cmp",p,l),baselineRunId:p,candidateRunId:l,timing:x,frames:R,heapTypes:h,thresholds:s,verdict:g?"fail":"pass"}}function F(e,a){if(a){let n=e.runs.find((s)=>s.id===a);return n?.cpu?[n]:[]}return e.runs.filter((n)=>n.phase==="cpu"&&n.cpu)}function B(e){let a=e.nodes,n=a.length,s=ze(e),t=new Int32Array(n).fill(-1);for(let c=0;c<n;c++)for(let f of a[c].children){let p=s(f);if(p!==-1)t[p]=c}let i=[];for(let c=0;c<n;c++)if(t[c]===-1)i.push(c);let o=[],r=[];for(let c=i.length-1;c>=0;c--)r.push(i[c]);while(r.length>0){let c=r.pop();o.push(c);for(let f of a[c].children){let p=s(f);if(p!==-1&&t[p]===c)r.push(p)}}return{count:n,indexOf:s,parentIx:t,roots:i,order:o}}function ze(e){let a=e.nodes,n=a.length,s=1/0,t=-1/0,i=!0;for(let r=0;r<n;r++){let c=a[r].id;if(!Number.isInteger(c)){i=!1;break}if(c<s)s=c;if(c>t)t=c}if(i&&n>0&&t-s<n*4+64){let r=t-s+1,c=new Int32Array(r).fill(-1);for(let f=0;f<n;f++)c[a[f].id-s]=f;return(f)=>{let p=f-s;return p>=0&&p<r?c[p]:-1}}let o=new Map;for(let r=0;r<n;r++)o.set(a[r].id,r);return(r)=>o.get(r)??-1}function ae(e,a){let{count:n,indexOf:s,parentIx:t,order:i}=a,o=new Float64Array(n),r=new Float64Array(n),c=e.samples?.nodeIds??[],f=e.samples?.timeDeltasUs??[];for(let l=0;l<c.length;l++){let g=s(c[l]);if(g===-1)continue;o[g]+=f[l]??0,r[g]+=1}let p=new Float64Array(n);for(let l=i.length-1;l>=0;l--){let g=i[l];p[g]+=o[g];let x=t[g];if(x>=0)p[x]+=p[g]}return{selfUs:o,totalUs:p,samples:r}}var ce={name:"collapsed",async render(e,a={}){return{files:F(e,a.runId).map((t)=>{let i=t.cpu,{nodes:o,frames:r}=i,c=B(i),f=Array(c.count);for(let R of c.order){let h=r[o[R].frameIx].name||"(anonymous)",w=c.parentIx[R];f[R]=w===-1?h:`${f[w]};${h}`}let p=new Float64Array(c.count),l=[],g=i.samples?.nodeIds??[];for(let R=0;R<g.length;R++){let h=c.indexOf(g[R]);if(h===-1)continue;if(p[h]++===0)l.push(h)}let x=Array(l.length);for(let R=0;R<l.length;R++){let h=l[R];x[R]=`${f[h]} ${p[h]}`}return{path:`${t.id}.collapsed.txt`,content:x.join(`
3
- `)+(x.length>0?`
4
- `:"")}})}}};var ue={name:"cpuprofile",async render(e,a={}){let n=F(e,a.runId),s=[],t=[];for(let i of n){if(i.cpu?.origin!=="cpu-prof"&&i.cpu?.origin!=="inspector"){t.push(`${i.id} (origin ${i.cpu?.origin??"unknown"} has no .cpuprofile artifact to pass through)`);continue}let o=i.artifacts.find((c)=>c.kind==="cpuprofile");if(!o){t.push(`${i.id} (no cpuprofile artifact recorded on this run)`);continue}let r=Bun.file(o.path);if(!await r.exists()){t.push(`${i.id} (artifact missing on disk: ${o.path})`);continue}s.push({path:`${i.id}.cpuprofile`,content:await r.text()})}if(s.length===0&&t.length>0)return{text:`No .cpuprofile artifacts available:
5
- ${t.map((i)=>` - ${i}`).join(`
6
- `)}
7
- `};return{files:s}}};var le={name:"json",async render(e){return{text:pe(e)}}};var me={name:"jsonl",async render(e){let{runs:a,...n}=e;return{text:`${[z(n),...a.map((t)=>z(t))].join(`
8
- `)}
9
- `}}};function D(e){return(e/1e6).toFixed(3)}function _(e){return e?.label??e?.command?.join(" ")??e?.entry?.task??e?.id??"unknown"}var fe=10,de=10,ge={name:"markdown",async render(e){let a=new Map(e.workloads.map((t)=>[t.id,t])),n=[];n.push("# Profile Report",""),n.push(`Bun ${e.bunVersion} \xB7 ostia ${e.toolVersion} \xB7 ${e.platform.os}/${e.platform.arch} \xB7 ${e.createdAt}`,"");let s=e.runs.filter((t)=>t.phase==="timing"&&t.timing!==void 0);if(s.length>0){n.push("## Timing",""),n.push("| Command | Mean \xB1 SD (ms) | Min\u2026Max (ms) | Median (ms) |","|---|---|---|---|");for(let i of s){let o=_(a.get(i.workloadId)),r=i.timing;n.push(`| ${o} | ${D(r.mean)} \xB1 ${D(r.stddev)} | ${D(r.min)}\u2026${D(r.max)} | ${D(r.median)} |`)}n.push("");let t=s.filter((i)=>i.warnings.length>0);if(t.length>0){n.push("### Warnings","");for(let i of t){let o=_(a.get(i.workloadId));for(let r of i.warnings)n.push(`- **${o}**: ${r.message} (\`${r.code}\`)`)}n.push("")}}for(let t of e.runs){if(t.phase!=="cpu"&&t.phase!=="heap")continue;let i=_(a.get(t.workloadId));if(t.phase==="cpu"){if(n.push(`## CPU capture - ${i}`,""),n.push(`instrumented, diagnostic wall ${D(t.diagnosticWallNs??0)}ms`,""),t.cpu){n.push(`origin: \`${t.cpu.origin}\`, interval: ${t.cpu.samplingIntervalUs}\xB5s`,""),n.push("| Self % | Self (ms) | Total (ms) | Frame |","|---|---|---|---|");let o=t.cpu.totals.reduce((r,c)=>r+c.selfUs,0)||1;for(let r of t.cpu.totals.slice(0,fe)){let c=t.cpu.frames[r.frameIx],f=(r.selfUs/o*100).toFixed(1);n.push(`| ${f}% | ${(r.selfUs/1000).toFixed(2)} | ${(r.totalUs/1000).toFixed(2)} | ${c?.name||"(anonymous)"} |`)}if(n.push(""),t.jit){let r=t.jit.tiers;n.push(`JIT tiers: LLInt ${r.llint} \xB7 Baseline ${r.baseline} \xB7 DFG ${r.dfg} \xB7 FTL ${r.ftl}`,"")}}}else if(n.push(`## Heap snapshot - ${i}`,""),n.push(`instrumented, diagnostic wall ${D(t.diagnosticWallNs??0)}ms`,""),t.heap){n.push(`${t.heap.objectCount??"?"} objects, ${((t.heap.heapSizeBytes??0)/1e6).toFixed(2)}MB`,""),n.push("| Count | Type |","|---|---|");for(let o of t.heap.typeCounts.slice(0,de))n.push(`| ${o.count} | ${o.type} |`);n.push("")}for(let o of t.artifacts)n.push(`- artifact: \`${o.path}\``);for(let o of t.warnings)n.push(`- ! ${o.message} (\`${o.code}\`)`);if(t.artifacts.length>0||t.warnings.length>0)n.push("")}if(e.comparisons&&e.comparisons.length>0){n.push("## Comparisons","");for(let t of e.comparisons){let i=e.runs.find((r)=>r.id===t.candidateRunId),o=_(i?a.get(i.workloadId):void 0);if(n.push(`### ${t.verdict==="pass"?"\u2713":"\u2717"} ${o}`,""),t.timing){let r=t.timing.medianDeltaPct>0?"+":"";n.push(`- timing: ${r}${t.timing.medianDeltaPct.toFixed(1)}% median (**${t.timing.verdict}**)`)}for(let r of t.frames?.slice(0,fe)??[]){if(Math.abs(r.deltaPct)<0.5)continue;let c=r.deltaPct>0?"+":"";n.push(`- frame \`${r.name}\`: ${c}${r.deltaPct.toFixed(1)}% self-time (${(r.baseSelfUs/1000).toFixed(2)}ms \u2192 ${(r.candSelfUs/1000).toFixed(2)}ms)`)}for(let r of t.heapTypes?.slice(0,de)??[]){if(Math.abs(r.deltaPct)<0.5)continue;let c=r.deltaPct>0?"+":"";n.push(`- heap \`${r.type}\`: ${c}${r.deltaPct.toFixed(1)}% count (${r.baseCount} \u2192 ${r.candCount})`)}n.push("")}}return{text:n.join(`
10
- `)}}};var Je=15;function J(e){return`n${e}`}function Ve(e,a,n){return`${(e||"(anonymous)").replace(/"/g,"'")} (self ${(a/1000).toFixed(2)}ms, total ${(n/1000).toFixed(2)}ms)`}function Ke(e,a,n,s){let t=[];if(s<=0)return t;for(let i=0;i<a;i++){if(i===n)continue;let o=e[i];if(t.length===s&&o<=e[t[s-1]])continue;let r=t.length;while(r>0&&e[t[r-1]]<o)r--;if(t.splice(r,0,i),t.length>s)t.pop()}return t}var he={name:"mermaid",async render(e,a={}){let n=a.topN??Je;return{files:F(e,a.runId).map((i)=>{let o=i.cpu,{nodes:r,frames:c}=o,f=B(o),{selfUs:p,totalUs:l}=ae(o,f),{parentIx:g}=f,x=f.roots[0]??-1,R=Ke(p,f.count,x,n),h=new Set(x!==-1?[x]:[]),w=[];for(let C of R){w.length=0;for(let b=C;b!==-1;b=g[b])w.push(b);for(let b=w.length-1;b>=0;b--)h.add(w[b])}let P=["graph TD"];for(let C of h){let b=r[C].id;P.push(` ${J(b)}["${Ve(c[r[C].frameIx].name,p[C],l[C])}"]`)}for(let C of h){let b=g[C];if(b!==-1&&h.has(b))P.push(` ${J(r[b].id)} --> ${J(r[C].id)}`)}return{path:`${i.id}.mermaid.md`,content:`${P.join(`
11
- `)}
12
- `}})}}};var Ge="https://www.speedscope.app/file-format-schema.json";function be(e){return e?.label??e?.command?.join(" ")??e?.entry?.task??"profile"}var ye={name:"speedscope",async render(e,a={}){let n=F(e,a.runId),s=new Map(e.workloads.map((i)=>[i.id,i]));return{files:n.map((i)=>{let o=i.cpu,{nodes:r}=o,c=B(o),f=o.samples?.nodeIds??[],p=o.samples?.timeDeltasUs??[],l=Array(c.count);for(let h of c.order){let w=c.parentIx[h],P=r[h].frameIx;l[h]=w===-1?[P]:[...l[w],P]}let g=Array(f.length);for(let h=0;h<f.length;h++){let w=c.indexOf(f[h]);g[h]=w===-1?[]:l[w]}let x=0;for(let h=0;h<p.length;h++)x+=p[h];let R={$schema:Ge,exporter:"ostia",name:be(s.get(i.workloadId)),activeProfileIndex:0,shared:{frames:o.frames.map((h)=>({name:h.name||"(anonymous)",file:h.url,line:h.line!==void 0?h.line+1:void 0}))},profiles:[{type:"sampled",name:be(s.get(i.workloadId)),unit:"microseconds",startValue:0,endValue:x,samples:g,weights:p}]};return{path:`${i.id}.speedscope.json`,content:`${JSON.stringify(R,null,2)}
13
- `}})}}};function O(e){return(e/1e6).toFixed(3)}function V(e){return e.label??e.command?.join(" ")??e.entry?.task??e.id}var xe={name:"table",async render(e){let a=e.runs.filter((l)=>l.phase==="timing"&&l.timing!==void 0),n=new Map(e.workloads.map((l)=>[l.id,l]));if(a.length===0){let l=we(e,n);return{text:l.length>0?`${l.join(`
14
- `)}
15
- `:`(no timing runs)
16
- `}}let s=a.map((l)=>{let g=n.get(l.workloadId);return{run:l,workload:g,label:g?V(g):l.workloadId}}),t=Math.min(...s.map((l)=>l.run.timing.median)),i=s.length>1,o=[],r=Math.max(7,...s.map((l)=>l.label.length)),c=i?`${"Command".padEnd(r)} Mean [ms] Min\u2026Max [ms] Relative`:`${"Command".padEnd(r)} Mean [ms] Min\u2026Max [ms]`;o.push(c),o.push("-".repeat(c.length));for(let{run:l,label:g}of s){let x=l.timing,R=`${O(x.mean)} \xB1 ${O(x.stddev)}`,h=`${O(x.min)}\u2026${O(x.max)}`,w=`${g.padEnd(r)} ${R.padEnd(15)} ${h.padEnd(18)}`;if(i){let P=x.median/t;w+=P===1?" 1.00\xD7":` ${P.toFixed(2)}\xD7 slower`}o.push(w);for(let P of l.warnings)o.push(` ! ${P.message}`)}let f=qe(e,n);if(f.length>0)o.push(""),o.push(...f);let p=we(e,n);if(p.length>0)o.push(""),o.push(...p);return{text:`${o.join(`
17
- `)}
18
- `}}};function Ye(e,a,n){let s=e.runs.find((i)=>i.id===n),t=s?a.get(s.workloadId):void 0;return t?V(t):n}function we(e,a){if(!e.comparisons||e.comparisons.length===0)return[];let n=[];for(let s of e.comparisons){let t=Ye(e,a,s.candidateRunId),i=s.verdict==="pass"?"\u2713":"\u2717";if(n.push(`${i} ${t}`),s.timing){let o=s.timing.medianDeltaPct>0?"+":"";n.push(` timing: ${o}${s.timing.medianDeltaPct.toFixed(1)}% median (${s.timing.verdict})`)}if(s.frames)for(let o of s.frames.slice(0,Re)){if(Math.abs(o.deltaPct)<0.5)continue;let r=o.deltaPct>0?"+":"";n.push(` frame ${o.name}: ${r}${o.deltaPct.toFixed(1)}% self-time (${(o.baseSelfUs/1000).toFixed(2)}ms -> ${(o.candSelfUs/1000).toFixed(2)}ms)`)}if(s.heapTypes)for(let o of s.heapTypes.slice(0,Pe)){if(Math.abs(o.deltaPct)<0.5)continue;let r=o.deltaPct>0?"+":"";n.push(` heap ${o.type}: ${r}${o.deltaPct.toFixed(1)}% count (${o.baseCount} -> ${o.candCount})`)}}return n}var Re=5,Pe=5;function qe(e,a){let n=[];for(let s of e.runs){if(s.phase!=="cpu"&&s.phase!=="heap")continue;let t=a.get(s.workloadId),i=t?V(t):s.workloadId;if(s.phase==="cpu")if(s.cpu){n.push(`CPU capture - ${i} (instrumented, ${s.cpu.samplingIntervalUs}\xB5s interval, diagnostic wall ${O(s.diagnosticWallNs??0)}ms)`);let o=s.cpu.totals.reduce((r,c)=>r+c.selfUs,0)||1;for(let r of s.cpu.totals.slice(0,Re)){let c=s.cpu.frames[r.frameIx],f=(r.selfUs/o*100).toFixed(1);n.push(` ${f.padStart(5)}% ${(r.selfUs/1000).toFixed(2).padStart(8)}ms self ${c?.name??"?"}`)}}else n.push(`CPU capture - ${i} (instrumented, no evidence captured)`);else if(s.heap){let o=((s.heap.heapSizeBytes??0)/1e6).toFixed(2);n.push(`Heap snapshot - ${i} (instrumented, ${s.heap.objectCount??"?"} objects, ${o}MB)`);for(let r of s.heap.typeCounts.slice(0,Pe))n.push(` ${String(r.count).padStart(6)} ${r.type}`)}else n.push(`Heap snapshot - ${i} (instrumented, no evidence captured)`);for(let o of s.artifacts)n.push(` artifact: ${o.path}`);for(let o of s.warnings)n.push(` ! ${o.message}`)}return n}var Qe={table:xe,json:le,markdown:ge,jsonl:me,collapsed:ce,mermaid:he,speedscope:ye,cpuprofile:ue};var Xe=".ostia",K=1000;async function st(e){let a=G({runs:e.runs??null,warmup:e.warmup??null,cpu:e.cpu??!1,heap:e.heap??!1,cpuIntervalUs:e.cpuIntervalUs??K}),s=`${e.outDir??Xe}/artifacts`,t=[],i=[];for(let o of e.commands){let r=Array.isArray(o)?o:te(o),c=$e(r,Array.isArray(o)?void 0:o);t.push(c);let f=await oe({argv:r,cwd:e.cwd,env:e.env,runs:e.runs,warmup:e.warmup}),p=Ie({workload:c,configFingerprint:a,trials:f.trials,timing:f.timing,warnings:f.warnings});if(i.push(p),e.cpu){let l=`${p.id}-cpu.cpuprofile`,g=await Y({argv:r,cwd:e.cwd,env:e.env,artifactDir:s,fileName:l,intervalUs:e.cpuIntervalUs??K});i.push(await Te({workload:c,phase:"cpu",configFingerprint:a,diagnosticWallNs:g.diagnosticWallNs,exitCode:g.exitCode,cpu:g.cpu,artifactPath:g.artifactPath,artifactKind:"cpuprofile",warnings:g.warnings}))}if(e.heap){let l=`${p.id}-heap.heapsnapshot`,g=await Q({argv:r,cwd:e.cwd,env:e.env,artifactDir:s,fileName:l});i.push(await Te({workload:c,phase:"heap",configFingerprint:a,diagnosticWallNs:g.diagnosticWallNs,exitCode:g.exitCode,heap:g.heap,artifactPath:g.artifactPath,artifactKind:"heapsnapshot",warnings:g.warnings}))}}return E(t,i)}async function Te(e){let a=`${e.workload.id}-${e.phase}-${e.configFingerprint}`,n=e.artifactPath?[await Ne(a,e.artifactKind,e.artifactPath)]:[];return j({workload:e.workload,phase:e.phase,configFingerprint:e.configFingerprint,diagnosticWallNs:e.diagnosticWallNs,exitCode:e.exitCode,cpu:e.cpu,heap:e.heap,warnings:e.warnings,artifacts:n})}async function ot(e,a={}){let n=Ce(e),s=G({intervalUs:a.intervalUs??K,origin:a.origin??"inspector"}),t=(f)=>f.samples?.nodeIds.length===0?[{code:"empty-profile",message:"In-process capture produced zero samples."}]:[];if(a.origin==="jsc"){let{result:f,cpu:p,jit:l,diagnosticWallNs:g}=await ne(e,a),x=j({workload:n,phase:"cpu",configFingerprint:s,diagnosticWallNs:g,cpu:p,jit:l,warnings:t(p),artifacts:[]});return{result:f,run:x}}let{result:i,cpu:o,diagnosticWallNs:r}=await X(e,a),c=j({workload:n,phase:"cpu",configFingerprint:s,diagnosticWallNs:r,cpu:o,warnings:t(o),artifacts:[]});return{result:i,run:c}}
19
- export{je as a,ie as b,Le as c,He as d,oe as e,Qe as f,st as g,ot as h};