ostia 0.1.2 → 0.1.4

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
@@ -133,15 +133,40 @@ Heap snapshot - bun fixtures/allocate.ts (instrumented, 2518 objects, 0.12MB)
133
133
 
134
134
  In-process microbenchmarks registered with `group()` / `task()`. Each task samples
135
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.
136
+ overruns the budget. Left unset, the floor is cost-aware in both directions: as many
137
+ trials as fit in the budget (capped at 20) so one slow task can't blow the suite's total,
138
+ but never below the floor a task's per-trial cost earns it - 3 at ≤1ms, two more per
139
+ decade of cost, 10 from about 3s up. Cheap tasks are time-bound and collect thousands of
140
+ trials either way; only the few expensive tasks in a suite pay for the extra rigor, and
141
+ those are exactly where a 3-sample mean is shakiest. Fast calls are batched so a trial
142
+ spans at least 1µs and a full budget yields about 10k trials at most.
143
+
144
+ | per-trial cost | fits in 500ms | default floor |
145
+ |---|---|---|
146
+ | 30ns | thousands | 20 (time-bound; ends in the tens of thousands) |
147
+ | 30ms | 16 | 16 |
148
+ | 140ms | 3 | 7 |
149
+ | 2.4s | 0 | 10 |
150
+
151
+ A run that ends below its cost-class floor (only possible with an explicit
152
+ `--min-samples` or per-task `minSamples`) carries a `low-sample-count` warning with
153
+ `{ samples, target, trialCostNs }`, so a renderer or an agent can flag a thin number
154
+ without re-deriving the policy from the raw sample array.
139
155
 
140
156
  ```sh
141
157
  ostia bench bench/*.ts
142
158
  ostia bench --time-budget 500 --min-samples 50 bench/stats.ts
159
+ ostia bench bench/*.ts --jobs auto # suite files in parallel, see below
160
+ ostia bench bench/*.ts --format minimal # one compact JSON object per task
143
161
  ```
144
162
 
163
+ `--jobs N|auto` runs that many suite files at once, each still in its own child process.
164
+ Files are independent by design, so for a multi-file suite this is close to a linear
165
+ wall-clock win - but concurrent CPU-bound processes contend for cores, caches and turbo
166
+ headroom, so numbers taken at `--jobs > 1` are noisier and not like-for-like with a
167
+ baseline measured at 1. It defaults to 1 for that reason; opt in for exploratory runs,
168
+ keep 1 for anything you `compare` or `ci` against.
169
+
145
170
  ```
146
171
  Command Mean [ms] Min…Max [ms] Relative
147
172
  --------------------------------------------------------------------------------------
@@ -176,8 +201,22 @@ ostia report out.json # table (default)
176
201
  ostia report out.json --format markdown
177
202
  ostia report out.json --format json
178
203
  ostia report out.json --format jsonl
204
+ ostia report out.json --format minimal
205
+ ```
206
+
207
+ Minimal format - one JSON object per timing run, no header, no raw sample array, no prose.
208
+ Built to pipe straight into an LLM agent's context: the full document carries every
209
+ sample (tens of thousands for a fast task), which is tokens a reviewer never reads.
210
+ Numbers stay in ns so they line up with `compare` deltas and the JSON document.
211
+
212
+ ```
213
+ {"task":"diffText()/append at end","group":"diffText()","samples":9282,"mean":50213.4,"median":49871,"stddev":2104.7,"stddevPct":4.19,"min":48120,"max":81002,"relative":1,"warnings":[],"unit":"ns"}
214
+ {"task":"repaint/4000 chars","group":"repaint","description":"full repaint every keystroke","samples":3,"mean":2.61e9,"median":2.4e9,"stddevPct":15.3,"relative":47800,"warnings":[{"code":"low-sample-count","data":{"samples":3,"target":10}}],"unit":"ns"}
179
215
  ```
180
216
 
217
+ `ostia compare ... --format minimal` adds `delta: { medianPct, meanPct, verdict, pass }` to
218
+ each line, so "did this PR regress" is `lines.some(l => l.delta?.verdict === "regressed")`.
219
+
181
220
  Markdown:
182
221
 
183
222
  ```
@@ -383,6 +422,27 @@ group("parse", () => {
383
422
  })
384
423
  ```
385
424
 
425
+ That is the whole registration surface: `group()` and `task()`. Presentation lives in
426
+ the renderers (`--format`), not in the suite file.
427
+
428
+ Both take an optional `description` that flows into the document
429
+ (`Workload.description` / `Workload.groupDescription`) and into `--format minimal`, so
430
+ what a number measures and why travels with the data instead of living only in a
431
+ source comment a reader has to go find:
432
+
433
+ ```ts
434
+ group(
435
+ "repaint",
436
+ () => {
437
+ task("1,000 chars", () => repaint(doc1k))
438
+ task("4,000 chars", () => repaint(doc4k), {
439
+ description: "worst case: full repaint every keystroke at the max document size",
440
+ })
441
+ },
442
+ { description: "editor repaint cost as document size grows" },
443
+ )
444
+ ```
445
+
386
446
  Mark one task per group as the `Relative` reference with `{ baseline: true }`
387
447
  (mirrors mitata's `baseline()`); otherwise `Relative` defaults to the fastest
388
448
  task in the group:
@@ -402,6 +462,7 @@ const doc = await bench({
402
462
  suites: ["suite.ts"],
403
463
  timeBudgetMs: 500,
404
464
  minSamples: 50,
465
+ jobs: 1, // suite files at once; > 1 trades fidelity for wall time
405
466
  })
406
467
  ```
407
468
 
@@ -435,6 +496,7 @@ Pure functions of a `ProfileDocument`. Each returns `{ text? }` and/or `{ files?
435
496
  | `markdown` | agent- and human-readable report |
436
497
  | `json` | pretty JSON document |
437
498
  | `jsonl` | one metadata line, then one line per run |
499
+ | `minimal` | one compact line per timing run, no sample array; for LLM/CI consumption |
438
500
  | `collapsed` | folded stacks (`name;name;name count`) |
439
501
  | `mermaid` | top-N call tree |
440
502
  | `speedscope` | speedscope.app JSON |
@@ -0,0 +1,4 @@
1
+ // @bun
2
+ function g(n){return JSON.stringify(O(n))}function O(n){if(Array.isArray(n))return n.map(O);if(n!==null&&typeof n==="object"){let a={};for(let d of Object.keys(n).sort())a[d]=O(n[d]);return a}return n}function e(n,...a){let d=Bun.CryptoHasher.hash("sha256",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 R(n,a){return{id:e("wl","inprocess",n.name,n.toString()),kind:"inprocess",label:a}}function P(n,a,d={}){return{id:e("wl","inprocess-entry",n,a),kind:"inprocess",entry:{file:n,task:a,...d.group!==void 0&&{group:d.group}},...d.label!==void 0&&{label:d.label},...d.baseline!==void 0&&{baseline:d.baseline},...d.description!==void 0&&{description:d.description},...d.groupDescription!==void 0&&{groupDescription:d.groupDescription}}}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:U(n.trials)}}function U(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 T(n,a,d){let p=await Bun.file(d).arrayBuffer(),k=new Bun.CryptoHasher("sha256");return k.update(p),{id:e("art",n,a,d),kind:a,path:d,sha256:k.digest("hex"),bytes:p.byteLength}}function s(n){return e("cfg",n)}function y(n){return`${JSON.stringify(O(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 _=[],S;function F(n,a,d){let f=S;S={name:n,description:d?.description};try{a()}finally{S=f}}function v(n,a,d){_.push({groupName:S?.name,groupDescription:S?.description,name:n,fn:a,baseline:d?.baseline,opts:d})}function C(){return _}function N(){_.length=0,S=void 0}function x(n){return n.groupName?`${n.groupName}/${n.name}`:n.name}function D(n,a){if(!a)return[...n];let d=new RegExp(a);return n.filter((f)=>d.test(x(f)))}function l(n){if(n.length===0)throw Error("computeTimingStats: samples must be non-empty");let a=n.length,d=L(n),f=0;for(let b=0;b<a;b++)f+=n[b];let p=f/a,k=B(d,0.5),w=0;for(let b=0;b<a;b++){let W=n[b]-p;w+=W*W}let M=Math.sqrt(w/a),H=d[0],E=d[a-1],A=B(d,0.25),q=B(d,0.75),I=q-A,z=A-1.5*I,V=q+1.5*I,G=A-3*I,K=q+3*I,J=0,j=0;for(let b=0;b<a;b++){let W=n[b];if(W<G||W>K)j++;else if(W<z||W>V)J++}return{unit:"ns",samples:n,mean:p,median:k,stddev:M,min:H,max:E,outliers:{mild:J,severe:j}}}function L(n){let a=new Float64Array(n.length);return a.set(n),a.sort(),a}function B(n,a){let d=n.length;if(d===1)return n[0];let f=a*(d-1),p=Math.floor(f),k=Math.ceil(f);if(p===k)return n[p];let w=f-p;return n[p]*(1-w)+n[k]*w}var Z=5000000,Q=200;function m(n,a,d="subprocess"){let f=[],p=n.samples[0];if(p!==void 0){let w=L(n.samples),M=B(w,0.25),E=B(w,0.75)-M;if(p>n.median+3*E&&E>0)f.push({code:"slow-first-run",message:`First run took ${(p/1e6).toFixed(2)}ms, much slower than the median ${(n.median/1e6).toFixed(2)}ms. Consider more warmup.`,data:{firstNs:p,medianNs:n.median}})}if(n.outliers.mild+n.outliers.severe>0)f.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)f.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)f.push({code:"below-timer-resolution",message:`Median run time (${n.median.toFixed(0)}ns) is close to timer resolution; consider a larger batch size or a coarser operation.`,data:{medianNs:n.median}});let k=a.filter((w)=>w!==void 0&&w!==0);if(k.length>0)f.push({code:"nonzero-exit",message:`${k.length} of ${a.length} trial(s) exited non-zero.`,data:{exitCodes:k}});return f}
4
+ export{g,e,c,r,u,R,P,i,h,T,s,y,o,t,l,m,F,v,C,N,x,D};
@@ -0,0 +1,21 @@
1
+ // @bun
2
+ import{g,e,r,u,R,i,h,T,s,y,t,l,m}from"./chunk-3rp84rbb.js";function Ae(o){return o.startsWith("file://")?o.slice(7):o}function oe(o,D,c){let C=o.nodes,x=C.length,v=new Map,N=[],P=new Map,U=new Int32Array(x);for(let W=0;W<x;W++){let O=C[W],S=O.callFrame,_=Ae(S.url),K=v.get(S.functionName);if(K===void 0)K=new Map,v.set(S.functionName,K);let G=K.get(_);if(G===void 0)G=N.length,K.set(_,G),N.push({key:e("fr",S.functionName,_),name:S.functionName,url:_||void 0,line:S.lineNumber>=0?S.lineNumber:void 0,col:S.columnNumber>=0?S.columnNumber:void 0});U[W]=G,P.set(O.id,W)}let M=Array(x);for(let W=0;W<x;W++){let O=C[W];M[W]={id:O.id,frameIx:U[P.get(O.id)],children:O.children??[]}}let F=new Float64Array(x),B=new Float64Array(x),{samples:A,timeDeltas:J}=o;for(let W=0;W<A.length;W++){let O=P.get(A[W]);if(O===void 0)continue;F[O]+=J[W]??0,B[O]+=1}let H=new Int32Array(x).fill(-1);for(let W=0;W<x;W++){let O=C[W].children;if(!O)continue;for(let S of O){let _=P.get(S);if(_!==void 0)H[_]=W}}let E=[],L=[];for(let W=x-1;W>=0;W--)if(H[W]===-1)L.push(W);while(L.length>0){let W=L.pop();E.push(W);let O=C[W].children;if(!O)continue;for(let S of O){let _=P.get(S);if(_!==void 0&&H[_]===W)L.push(_)}}let V=new Float64Array(x);for(let W=E.length-1;W>=0;W--){let O=E[W];V[O]+=F[O];let S=H[O];if(S>=0)V[S]+=V[O]}let z=Array(N.length),j=[];for(let W=0;W<x;W++){let O=M[W].frameIx,S=z[O];if(S)S.selfUs+=F[W],S.totalUs+=V[W],S.samples+=B[W];else{let _={frameIx:O,selfUs:F[W],totalUs:V[W],samples:B[W]};z[O]=_,j.push(_)}}return{origin:D,samplingIntervalUs:c,frames:N,nodes:M,totals:j.sort((W,O)=>O.selfUs-W.selfUs),samples:{nodeIds:o.samples,timeDeltasUs:o.timeDeltas}}}function je(o,D,c,C){let x=["--cpu-prof","--cpu-prof-dir",D,"--cpu-prof-name",c,"--cpu-prof-interval",String(C)],v=o[0];if(v==="bun"||v?.endsWith("/bun"))return[v,...x,...o.slice(1)];return o}async function de(o){let D=`${o.artifactDir}/${o.fileName}`,c=o.argv[0],C=c==="bun"||c?.endsWith("/bun"),x=je(o.argv,o.artifactDir,o.fileName,o.intervalUs),v=C?o.env:{...process.env,...o.env,BUN_OPTIONS:`--cpu-prof --cpu-prof-dir ${o.artifactDir} --cpu-prof-name ${o.fileName} --cpu-prof-interval ${o.intervalUs}`},N=Bun.nanoseconds(),U=await Bun.spawn(x,{cwd:o.cwd,env:v,stdout:"ignore",stderr:"ignore",stdin:"ignore"}).exited,M=Bun.nanoseconds()-N,F=Bun.file(D);if(!await F.exists())return{diagnosticWallNs:M,exitCode:U,warnings:[{code:"artifact-missing",message:`Expected a .cpuprofile at ${D} after exit ${U}, found nothing. The workload's argv[0] must be a \`bun\` binary for CPU capture.`,data:{artifactPath:D,argv:o.argv}}]};let B=await F.json(),A=oe(B,"cpu-prof",o.intervalUs),J=B.samples.length===0?[{code:"empty-profile",message:"CPU capture produced zero samples."}]:[];return{diagnosticWallNs:M,exitCode:U,artifactPath:D,cpu:A,warnings:J}}function fe(o,D="heap-prof"){let{node_fields:c,node_types:C}=o.snapshot.meta,x=c.indexOf("type"),v=c.indexOf("self_size"),N=c.length,P=C[0];if(x===-1||v===-1||!Array.isArray(P))return{origin:D,typeCounts:[],objectCount:o.snapshot.node_count};let U=P.length,M=Array(U),F=new Map,B=[],A=0,J=o.nodes,H=J.length;for(let j=0;j<H;j+=N){let W=J[j+x],O=J[j+v]??0;A+=O;let S;if(W>=0&&W<U){if(S=M[W],S===void 0)S={type:P[W],count:0,bytes:0},M[W]=S,B.push(S)}else{let _=`unknown(${W})`;if(S=F.get(_),S===void 0)S={type:_,count:0,bytes:0},F.set(_,S),B.push(S)}S.count++,S.bytes+=O}let E=B.sort((j,W)=>W.count-j.count),L=E.slice(0,20),V=E.slice(20),z=L.map(({type:j,count:W,bytes:O})=>({type:j,count:W,retainedBytes:O}));if(V.length>0){let j=0,W=0;for(let O of V)j+=O.count,W+=O.bytes;z.push({type:"other",count:j,retainedBytes:W})}return{origin:D,heapSizeBytes:A,objectCount:o.snapshot.node_count,typeCounts:z}}function _e(o,D,c){let C=["--heap-prof","--heap-prof-dir",D,"--heap-prof-name",c],x=o[0];if(x==="bun"||x?.endsWith("/bun"))return[x,...C,...o.slice(1)];return o}async function ge(o){let D=`${o.artifactDir}/${o.fileName}`,c=o.argv[0],C=c==="bun"||c?.endsWith("/bun"),x=_e(o.argv,o.artifactDir,o.fileName),v=C?o.env:{...process.env,...o.env,BUN_OPTIONS:`--heap-prof --heap-prof-dir ${o.artifactDir} --heap-prof-name ${o.fileName}`},N=Bun.nanoseconds(),U=await Bun.spawn(x,{cwd:o.cwd,env:v,stdout:"ignore",stderr:"ignore",stdin:"ignore"}).exited,M=Bun.nanoseconds()-N,F=Bun.file(D);if(!await F.exists())return{diagnosticWallNs:M,exitCode:U,warnings:[{code:"artifact-missing",message:`Expected a heap snapshot at ${D} after exit ${U}, found nothing. The workload's argv[0] must be a \`bun\` binary for heap capture.`,data:{artifactPath:D,argv:o.argv}}]};let B=await F.json(),A=fe(B,"heap-prof");return{diagnosticWallNs:M,exitCode:U,artifactPath:D,heap:A,warnings:[]}}import{Session as Le}from"inspector/promises";var He=1000;async function he(o,D={}){let c=D.intervalUs??He,C=new Le;C.connect();let x=Bun.nanoseconds();try{await C.post("Profiler.enable"),await C.post("Profiler.setSamplingInterval",{interval:c}),await C.post("Profiler.start");let v=await o(),{profile:N}=await C.post("Profiler.stop"),P=Bun.nanoseconds()-x,U=oe(N,"inspector",c);return{result:v,cpu:U,diagnosticWallNs:P}}finally{C.disconnect()}}import{profile as ze}from"bun:jsc";var Je=new Map([["LLInt","llint"],["Baseline","baseline"],["DFG","dfg"],["FTL","ftl"]]),be=4294967295;function ye(o,D){let c=D??o.interval*1e6,C=new Map,x=[];function v(S,_,K,G){let q=C.get(S);if(q===void 0)q=new Map,C.set(S,q);let Y=_??"",X=q.get(Y);if(X===void 0)X=x.length,q.set(Y,X),x.push({key:e("fr",S,Y),name:S,url:_,line:K,col:G});return X}function N(S){let _=S.line===be,K=_?void 0:S.line-1,G=_||S.column===be?void 0:S.column-1;return v(S.name,S.sourceURL,K,G)}let P=v("(root)",void 0,void 0,void 0),U=1,M={id:0,frameIx:P,children:new Map,selfUs:0,samples:0,totalUs:0},F=new Map([[0,M]]),B={llint:0,baseline:0,dfg:0,ftl:0},A=new Map,J=[],H=[];for(let S of o.traces){let _=S.frames,K=M;for(let Y=_.length-1;Y>=0;Y--){let X=N(_[Y]),ne=K.children.get(X);if(!ne)ne={id:U++,frameIx:X,children:new Map,selfUs:0,samples:0,totalUs:0},K.children.set(X,ne),F.set(ne.id,ne);K=ne}K.selfUs+=c,K.samples+=1,J.push(K.id),H.push(c);let G=_[0],q=G&&Je.get(G.category);if(q){B[q]++;let Y=A.get(q)??new Map;Y.set(K.frameIx,(Y.get(K.frameIx)??0)+1),A.set(q,Y)}}function E(S){let _=S.selfUs;for(let K of S.children.values())_+=E(K);return S.totalUs=_,_}E(M);let L=new Map;function V(S){let _=L.get(S.frameIx);if(_)_.selfUs+=S.selfUs,_.totalUs+=S.totalUs,_.samples+=S.samples;else L.set(S.frameIx,{frameIx:S.frameIx,selfUs:S.selfUs,totalUs:S.totalUs,samples:S.samples});for(let K of S.children.values())V(K)}V(M);let z=[...F.values()].map((S)=>({id:S.id,frameIx:S.frameIx,children:[...S.children.values()].map((_)=>_.id)})),j={origin:"jsc-profile",samplingIntervalUs:c,frames:x,nodes:z,totals:[...L.values()].sort((S,_)=>_.selfUs-S.selfUs),samples:{nodeIds:J,timeDeltasUs:H}},W=[...A.entries()].flatMap(([S,_])=>[..._.entries()].sort((K,G)=>G[1]-K[1]).slice(0,3).map(([K,G])=>({tier:S,frameKey:x[K].key,samples:G})));return{cpu:j,jit:{origin:"jsc-profile",tiers:B,topFramesByTier:W}}}var Ve=1000;async function we(o,D={}){let c=D.intervalUs??Ve,C,x=Bun.nanoseconds(),v=await ze(async()=>(C=await o(),C),c),N=Bun.nanoseconds()-x,{cpu:P,jit:U}=ye(v.stackTraces,c);return{result:C,cpu:P,jit:U,diagnosticWallNs:N}}async function ue(o){let D=Bun.nanoseconds(),c=Bun.spawn(o.argv,{cwd:o.cwd,env:o.env,stdout:"ignore",stderr:"ignore",stdin:"ignore"}),C=await c.exited,x=Bun.nanoseconds(),v=c.resourceUsage?.();return{wallNs:x-D,exitCode:C,userNs:v?Number(v.cpuTime.user)*1000:void 0,systemNs:v?Number(v.cpuTime.system)*1000:void 0,maxRssBytes:v?.maxRSS}}function Re(o){return o.trim().split(/\s+/).filter(Boolean)}var Ke=10,Ge=3000000000,Ye=3;async function f(o){let D=o.warmup??Ye;for(let F=0;F<D;F++)await ue(o);let c=[],C=o.runs??o.minRuns??Ke,x=o.runs!==void 0?0:o.minTotalNs??Ge,v=0,N=0;while(N<C||v<x){let F=await ue(o);if(c.push({i:N,wallNs:F.wallNs,exitCode:F.exitCode,userNs:F.userNs,systemNs:F.systemNs,maxRssBytes:F.maxRssBytes}),v+=F.wallNs,N++,o.runs!==void 0&&N>=o.runs)break}let P=c.map((F)=>F.wallNs),U=l(P),M=m(U,c.map((F)=>F.exitCode));return{trials:c,timing:U,warnings:M}}var qe=new URL("./runner.ts",import.meta.url).pathname,Qe="node_modules/.cache/ostia";function k(){return Math.max(1,navigator.hardwareConcurrency||1)}async function p(o){let c=`${o.outDir??Qe}/bench-tmp`,C=o.cwd??process.cwd(),x=Math.max(1,Math.floor(o.jobs??1)),v={timeBudgetMs:o.timeBudgetMs,minSamples:o.minSamples,gc:o.gc,filter:o.filter},N=Array(o.suites.length),P=new Set,U=0,M,F=async(H)=>{let E=o.suites[H],L=E.startsWith("/")?E:`${C}/${E}`,V=`${c}/${e("bench-out",L)}.json`,z=Bun.spawn(["bun",qe,L,V,JSON.stringify(v)],{cwd:C,stdout:"inherit",stderr:"inherit",stdin:"ignore"});P.add(z);let j=await z.exited;if(P.delete(z),j!==0)throw Error(`Bench suite failed: ${E} (runner exited ${j})`);N[H]=await t(V)},B=async()=>{while(M===void 0&&U<o.suites.length){let H=U++;try{await F(H)}catch(E){M??=E instanceof Error?E:Error(String(E));for(let L of P)L.kill()}}};try{if(await Promise.all(Array.from({length:Math.min(x,o.suites.length)},B)),M)throw M}finally{await Bun.spawn(["rm","-rf",c]).exited}let A=[],J=[];for(let H of N)A.push(...H.workloads),J.push(...H.runs);return r(A,J)}var a={timingPct:5,frameSelfPct:10,heapTypePct:10,minFrameSelfUs:1000};function ie(o,D){if(o===0)return D===0?0:1/0;return(D-o)/o*100}function te(o,D,c){return o.runs.find((C)=>C.workloadId===D&&C.phase===c)}function d(o,D,c=a){let C=new Set(D.workloads.map((v)=>v.id)),x=[];for(let v of o.workloads){if(!C.has(v.id))continue;let N=b(o,D,v.id,c);if(N)x.push(N)}return x}function b(o,D,c,C=a){let x=te(o,c,"timing"),v=te(D,c,"timing"),N=te(o,c,"cpu"),P=te(D,c,"cpu"),U=te(o,c,"heap"),M=te(D,c,"heap"),F=x?.id??N?.id??U?.id,B=v?.id??P?.id??M?.id;if(!F||!B)return;let A=!1,J;if(x?.timing&&v?.timing){let L=ie(x.timing.median,v.timing.median),V=ie(x.timing.mean,v.timing.mean),z=L>C.timingPct?"regressed":L<-C.timingPct?"improved":"unchanged";if(z==="regressed")A=!0;J={medianDeltaPct:L,meanDeltaPct:V,verdict:z}}let H;if(N?.cpu&&P?.cpu){let L=new Map(N.cpu.totals.map((O)=>[N.cpu.frames[O.frameIx].key,O])),V=new Map(P.cpu.totals.map((O)=>[P.cpu.frames[O.frameIx].key,O])),z=new Map(N.cpu.frames.map((O)=>[O.key,O.name])),j=new Map(P.cpu.frames.map((O)=>[O.key,O.name]));H=[...new Set([...L.keys(),...V.keys()])].map((O)=>{let S=L.get(O)?.selfUs??0,_=V.get(O)?.selfUs??0;return{frameKey:O,name:j.get(O)??z.get(O)??O,baseSelfUs:S,candSelfUs:_,deltaPct:ie(S,_)}}).sort((O,S)=>Math.abs(S.deltaPct)-Math.abs(O.deltaPct));for(let O of H)if((O.baseSelfUs>=C.minFrameSelfUs||O.candSelfUs>=C.minFrameSelfUs)&&O.deltaPct>C.frameSelfPct)A=!0}let E;if(U?.heap&&M?.heap){let L=new Map(U.heap.typeCounts.map((j)=>[j.type,j])),V=new Map(M.heap.typeCounts.map((j)=>[j.type,j]));E=[...new Set([...L.keys(),...V.keys()])].map((j)=>{let W=L.get(j),O=V.get(j);return{type:j,baseCount:W?.count??0,candCount:O?.count??0,baseBytes:W?.retainedBytes,candBytes:O?.retainedBytes,deltaPct:ie(W?.count??0,O?.count??0)}}).sort((j,W)=>Math.abs(W.deltaPct)-Math.abs(j.deltaPct));for(let j of E)if(j.deltaPct>C.heapTypePct)A=!0}return{id:e("cmp",F,B),baselineRunId:F,candidateRunId:B,timing:J,frames:H,heapTypes:E,thresholds:C,verdict:A?"fail":"pass"}}function Z(o,D){if(D){let c=o.runs.find((C)=>C.id===D);return c?.cpu?[c]:[]}return o.runs.filter((c)=>c.phase==="cpu"&&c.cpu)}function re(o){let D=o.nodes,c=D.length,C=Xe(o),x=new Int32Array(c).fill(-1);for(let U=0;U<c;U++)for(let M of D[U].children){let F=C(M);if(F!==-1)x[F]=U}let v=[];for(let U=0;U<c;U++)if(x[U]===-1)v.push(U);let N=[],P=[];for(let U=v.length-1;U>=0;U--)P.push(v[U]);while(P.length>0){let U=P.pop();N.push(U);for(let M of D[U].children){let F=C(M);if(F!==-1&&x[F]===U)P.push(F)}}return{count:c,indexOf:C,parentIx:x,roots:v,order:N}}function Xe(o){let D=o.nodes,c=D.length,C=1/0,x=-1/0,v=!0;for(let P=0;P<c;P++){let U=D[P].id;if(!Number.isInteger(U)){v=!1;break}if(U<C)C=U;if(U>x)x=U}if(v&&c>0&&x-C<c*4+64){let P=x-C+1,U=new Int32Array(P).fill(-1);for(let M=0;M<c;M++)U[D[M].id-C]=M;return(M)=>{let F=M-C;return F>=0&&F<P?U[F]:-1}}let N=new Map;for(let P=0;P<c;P++)N.set(D[P].id,P);return(P)=>N.get(P)??-1}function xe(o,D){let{count:c,indexOf:C,parentIx:x,order:v}=D,N=new Float64Array(c),P=new Float64Array(c),U=o.samples?.nodeIds??[],M=o.samples?.timeDeltasUs??[];for(let B=0;B<U.length;B++){let A=C(U[B]);if(A===-1)continue;N[A]+=M[B]??0,P[A]+=1}let F=new Float64Array(c);for(let B=v.length-1;B>=0;B--){let A=v[B];F[A]+=N[A];let J=x[A];if(J>=0)F[J]+=F[A]}return{selfUs:N,totalUs:F,samples:P}}var Pe={name:"collapsed",async render(o,D={}){return{files:Z(o,D.runId).map((x)=>{let v=x.cpu,{nodes:N,frames:P}=v,U=re(v),M=Array(U.count);for(let H of U.order){let E=P[N[H].frameIx].name||"(anonymous)",L=U.parentIx[H];M[H]=L===-1?E:`${M[L]};${E}`}let F=new Float64Array(U.count),B=[],A=v.samples?.nodeIds??[];for(let H=0;H<A.length;H++){let E=U.indexOf(A[H]);if(E===-1)continue;if(F[E]++===0)B.push(E)}let J=Array(B.length);for(let H=0;H<B.length;H++){let E=B[H];J[H]=`${M[E]} ${F[E]}`}return{path:`${x.id}.collapsed.txt`,content:J.join(`
3
+ `)+(J.length>0?`
4
+ `:"")}})}}};var Te={name:"cpuprofile",async render(o,D={}){let c=Z(o,D.runId),C=[],x=[];for(let v of c){if(v.cpu?.origin!=="cpu-prof"&&v.cpu?.origin!=="inspector"){x.push(`${v.id} (origin ${v.cpu?.origin??"unknown"} has no .cpuprofile artifact to pass through)`);continue}let N=v.artifacts.find((U)=>U.kind==="cpuprofile");if(!N){x.push(`${v.id} (no cpuprofile artifact recorded on this run)`);continue}let P=Bun.file(N.path);if(!await P.exists()){x.push(`${v.id} (artifact missing on disk: ${N.path})`);continue}C.push({path:`${v.id}.cpuprofile`,content:await P.text()})}if(C.length===0&&x.length>0)return{text:`No .cpuprofile artifacts available:
5
+ ${x.map((v)=>` - ${v}`).join(`
6
+ `)}
7
+ `};return{files:C}}};var $e={name:"json",async render(o){return{text:y(o)}}};var ke={name:"jsonl",async render(o){let{runs:D,...c}=o;return{text:`${[g(c),...D.map((x)=>g(x))].join(`
8
+ `)}
9
+ `}}};function ee(o){return(o/1e6).toFixed(3)}function ae(o){return o?.label??o?.command?.join(" ")??o?.entry?.task??o?.id??"unknown"}var ve=10,Ce=10,Ne={name:"markdown",async render(o){let D=new Map(o.workloads.map((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 C=o.runs.filter((x)=>x.phase==="timing"&&x.timing!==void 0);if(C.length>0){c.push("## Timing",""),c.push("| Command | Mean \xB1 SD (ms) | Min\u2026Max (ms) | Median (ms) |","|---|---|---|---|");for(let v of C){let N=ae(D.get(v.workloadId)),P=v.timing;c.push(`| ${N} | ${ee(P.mean)} \xB1 ${ee(P.stddev)} | ${ee(P.min)}\u2026${ee(P.max)} | ${ee(P.median)} |`)}c.push("");let x=C.filter((v)=>v.warnings.length>0);if(x.length>0){c.push("### Warnings","");for(let v of x){let N=ae(D.get(v.workloadId));for(let P of v.warnings)c.push(`- **${N}**: ${P.message} (\`${P.code}\`)`)}c.push("")}}for(let x of o.runs){if(x.phase!=="cpu"&&x.phase!=="heap")continue;let v=ae(D.get(x.workloadId));if(x.phase==="cpu"){if(c.push(`## CPU capture - ${v}`,""),c.push(`instrumented, diagnostic wall ${ee(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((P,U)=>P+U.selfUs,0)||1;for(let P of x.cpu.totals.slice(0,ve)){let U=x.cpu.frames[P.frameIx],M=(P.selfUs/N*100).toFixed(1);c.push(`| ${M}% | ${(P.selfUs/1000).toFixed(2)} | ${(P.totalUs/1000).toFixed(2)} | ${U?.name||"(anonymous)"} |`)}if(c.push(""),x.jit){let P=x.jit.tiers;c.push(`JIT tiers: LLInt ${P.llint} \xB7 Baseline ${P.baseline} \xB7 DFG ${P.dfg} \xB7 FTL ${P.ftl}`,"")}}}else if(c.push(`## Heap snapshot - ${v}`,""),c.push(`instrumented, diagnostic wall ${ee(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,Ce))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 v=o.runs.find((P)=>P.id===x.candidateRunId),N=ae(v?D.get(v.workloadId):void 0);if(c.push(`### ${x.verdict==="pass"?"\u2713":"\u2717"} ${N}`,""),x.timing){let P=x.timing.medianDeltaPct>0?"+":"";c.push(`- timing: ${P}${x.timing.medianDeltaPct.toFixed(1)}% median (**${x.timing.verdict}**)`)}for(let P of x.frames?.slice(0,ve)??[]){if(Math.abs(P.deltaPct)<0.5)continue;let U=P.deltaPct>0?"+":"";c.push(`- frame \`${P.name}\`: ${U}${P.deltaPct.toFixed(1)}% self-time (${(P.baseSelfUs/1000).toFixed(2)}ms \u2192 ${(P.candSelfUs/1000).toFixed(2)}ms)`)}for(let P of x.heapTypes?.slice(0,Ce)??[]){if(Math.abs(P.deltaPct)<0.5)continue;let U=P.deltaPct>0?"+":"";c.push(`- heap \`${P.type}\`: ${U}${P.deltaPct.toFixed(1)}% count (${P.baseCount} \u2192 ${P.candCount})`)}c.push("")}}return{text:c.join(`
10
+ `)}}};var Ze=15;function pe(o){return`n${o}`}function en(o,D,c){return`${(o||"(anonymous)").replace(/"/g,"'")} (self ${(D/1000).toFixed(2)}ms, total ${(c/1000).toFixed(2)}ms)`}function nn(o,D,c,C){let x=[];if(C<=0)return x;for(let v=0;v<D;v++){if(v===c)continue;let N=o[v];if(x.length===C&&N<=o[x[C-1]])continue;let P=x.length;while(P>0&&o[x[P-1]]<N)P--;if(x.splice(P,0,v),x.length>C)x.pop()}return x}var Ie={name:"mermaid",async render(o,D={}){let c=D.topN??Ze;return{files:Z(o,D.runId).map((v)=>{let N=v.cpu,{nodes:P,frames:U}=N,M=re(N),{selfUs:F,totalUs:B}=xe(N,M),{parentIx:A}=M,J=M.roots[0]??-1,H=nn(F,M.count,J,c),E=new Set(J!==-1?[J]:[]),L=[];for(let z of H){L.length=0;for(let j=z;j!==-1;j=A[j])L.push(j);for(let j=L.length-1;j>=0;j--)E.add(L[j])}let V=["graph TD"];for(let z of E){let j=P[z].id;V.push(` ${pe(j)}["${en(U[P[z].frameIx].name,F[z],B[z])}"]`)}for(let z of E){let j=A[z];if(j!==-1&&E.has(j))V.push(` ${pe(P[j].id)} --> ${pe(P[z].id)}`)}return{path:`${v.id}.mermaid.md`,content:`${V.join(`
11
+ `)}
12
+ `}})}}};function Ue(o){if(!o?.entry)return;if(o.entry.group!==void 0)return o.entry.group;let D=o.entry.task,c=D.lastIndexOf("/");return c===-1?void 0:D.slice(0,c)}function ce(o){let D=Math.min(...o.map((x)=>x.run.timing.median)),c=new Map;for(let x of o){let v=Ue(x.workload);if(v===void 0)continue;let N=c.get(v);if(N)N.push(x);else c.set(v,[x])}let C=new Map;for(let x of o){let v=Ue(x.workload);if(v===void 0){C.set(x,D);continue}let N=c.get(v)??[x],P=N.find((U)=>U.workload?.baseline);C.set(x,P?P.run.timing.median:Math.min(...N.map((U)=>U.run.timing.median)))}return C}function Q(o){return Number.isFinite(o)?Number(o.toPrecision(6)):o}function tn(o,D){return o?.entry?.task??o?.label??o?.command?.join(" ")??D.workloadId}function rn(o){let D=new Map(o.workloads.map((v)=>[v.id,v])),c=o.runs.filter((v)=>v.phase==="timing"&&v.timing!==void 0).map((v)=>({run:v,workload:D.get(v.workloadId)})),C=c.length>1?ce(c):void 0,x=new Map((o.comparisons??[]).map((v)=>[v.candidateRunId,v]));return c.map((v)=>{let{run:N,workload:P}=v,U=N.timing,M={task:tn(P,N),unit:"ns",samples:U.samples.length,mean:Q(U.mean),median:Q(U.median),stddev:Q(U.stddev),stddevPct:Q(U.mean===0?0:U.stddev/U.mean*100),min:Q(U.min),max:Q(U.max),warnings:N.warnings.map((B)=>B.data?{code:B.code,data:B.data}:{code:B.code})};if(P?.entry?.group!==void 0)M.group=P.entry.group;if(P?.description!==void 0)M.description=P.description;if(P?.groupDescription!==void 0)M.groupDescription=P.groupDescription;if(C)M.relative=Q(U.median/(C.get(v)??U.median));if(P?.baseline)M.baseline=!0;let F=x.get(N.id);if(F?.timing)M.delta={medianPct:Q(F.timing.medianDeltaPct),meanPct:Q(F.timing.meanDeltaPct),verdict:F.timing.verdict,pass:F.verdict==="pass"};return M})}var De={name:"minimal",async render(o){let D=rn(o).map((c)=>JSON.stringify(c));return{text:D.length>0?`${D.join(`
13
+ `)}
14
+ `:""}}};var sn="https://www.speedscope.app/file-format-schema.json";function Fe(o){return o?.label??o?.command?.join(" ")??o?.entry?.task??"profile"}var Me={name:"speedscope",async render(o,D={}){let c=Z(o,D.runId),C=new Map(o.workloads.map((v)=>[v.id,v]));return{files:c.map((v)=>{let N=v.cpu,{nodes:P}=N,U=re(N),M=N.samples?.nodeIds??[],F=N.samples?.timeDeltasUs??[],B=Array(U.count);for(let E of U.order){let L=U.parentIx[E],V=P[E].frameIx;B[E]=L===-1?[V]:[...B[L],V]}let A=Array(M.length);for(let E=0;E<M.length;E++){let L=U.indexOf(M[E]);A[E]=L===-1?[]:B[L]}let J=0;for(let E=0;E<F.length;E++)J+=F[E];let H={$schema:sn,exporter:"ostia",name:Fe(C.get(v.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:Fe(C.get(v.workloadId)),unit:"microseconds",startValue:0,endValue:J,samples:A,weights:F}]};return{path:`${v.id}.speedscope.json`,content:`${JSON.stringify(H,null,2)}
15
+ `}})}}};function se(o){return(o/1e6).toFixed(3)}function le(o){return o.label??o.command?.join(" ")??o.entry?.task??o.id}var Be={name:"table",async render(o){let D=o.runs.filter((B)=>B.phase==="timing"&&B.timing!==void 0),c=new Map(o.workloads.map((B)=>[B.id,B]));if(D.length===0){let B=Se(o,c);return{text:B.length>0?`${B.join(`
16
+ `)}
17
+ `:`(no timing runs)
18
+ `}}let C=D.map((B)=>{let A=c.get(B.workloadId);return{run:B,workload:A,label:A?le(A):B.workloadId}}),x=C.length>1,v=ce(C),N=[],P=Math.max(7,...C.map((B)=>B.label.length)),U=x?`${"Command".padEnd(P)} Mean [ms] Min\u2026Max [ms] Relative`:`${"Command".padEnd(P)} Mean [ms] Min\u2026Max [ms]`;N.push(U),N.push("-".repeat(U.length));for(let B of C){let{run:A,label:J,workload:H}=B,E=A.timing,L=`${se(E.mean)} \xB1 ${se(E.stddev)}`,V=`${se(E.min)}\u2026${se(E.max)}`,z=`${J.padEnd(P)} ${L.padEnd(15)} ${V.padEnd(18)}`;if(x){let j=E.median/(v.get(B)??E.median);if(j===1)z+=H?.baseline?" 1.00\xD7 (baseline)":" 1.00\xD7";else if(j>1)z+=` ${j.toFixed(2)}\xD7 slower`;else z+=` ${(1/j).toFixed(2)}\xD7 faster`}N.push(z);for(let j of A.warnings)N.push(` ! ${j.message}`)}let M=an(o,c);if(M.length>0)N.push(""),N.push(...M);let F=Se(o,c);if(F.length>0)N.push(""),N.push(...F);return{text:`${N.join(`
19
+ `)}
20
+ `}}};function on(o,D,c){let C=o.runs.find((v)=>v.id===c),x=C?D.get(C.workloadId):void 0;return x?le(x):c}function Se(o,D){if(!o.comparisons||o.comparisons.length===0)return[];let c=[];for(let C of o.comparisons){let x=on(o,D,C.candidateRunId),v=C.verdict==="pass"?"\u2713":"\u2717";if(c.push(`${v} ${x}`),C.timing){let N=C.timing.medianDeltaPct>0?"+":"";c.push(` timing: ${N}${C.timing.medianDeltaPct.toFixed(1)}% median (${C.timing.verdict})`)}if(C.frames)for(let N of C.frames.slice(0,We)){if(Math.abs(N.deltaPct)<0.5)continue;let P=N.deltaPct>0?"+":"";c.push(` frame ${N.name}: ${P}${N.deltaPct.toFixed(1)}% self-time (${(N.baseSelfUs/1000).toFixed(2)}ms -> ${(N.candSelfUs/1000).toFixed(2)}ms)`)}if(C.heapTypes)for(let N of C.heapTypes.slice(0,Oe)){if(Math.abs(N.deltaPct)<0.5)continue;let P=N.deltaPct>0?"+":"";c.push(` heap ${N.type}: ${P}${N.deltaPct.toFixed(1)}% count (${N.baseCount} -> ${N.candCount})`)}}return c}var We=5,Oe=5;function an(o,D){let c=[];for(let C of o.runs){if(C.phase!=="cpu"&&C.phase!=="heap")continue;let x=D.get(C.workloadId),v=x?le(x):C.workloadId;if(C.phase==="cpu")if(C.cpu){c.push(`CPU capture - ${v} (instrumented, ${C.cpu.samplingIntervalUs}\xB5s interval, diagnostic wall ${se(C.diagnosticWallNs??0)}ms)`);let N=C.cpu.totals.reduce((P,U)=>P+U.selfUs,0)||1;for(let P of C.cpu.totals.slice(0,We)){let U=C.cpu.frames[P.frameIx],M=(P.selfUs/N*100).toFixed(1);c.push(` ${M.padStart(5)}% ${(P.selfUs/1000).toFixed(2).padStart(8)}ms self ${U?.name??"?"}`)}}else c.push(`CPU capture - ${v} (instrumented, no evidence captured)`);else if(C.heap){let N=((C.heap.heapSizeBytes??0)/1e6).toFixed(2);c.push(`Heap snapshot - ${v} (instrumented, ${C.heap.objectCount??"?"} objects, ${N}MB)`);for(let P of C.heap.typeCounts.slice(0,Oe))c.push(` ${String(P.count).padStart(6)} ${P.type}`)}else c.push(`Heap snapshot - ${v} (instrumented, no evidence captured)`);for(let N of C.artifacts)c.push(` artifact: ${N.path}`);for(let N of C.warnings)c.push(` ! ${N.message}`)}return c}var n={table:Be,json:$e,markdown:Ne,jsonl:ke,minimal:De,collapsed:Pe,mermaid:Ie,speedscope:Me,cpuprofile:Te};var cn="node_modules/.cache/ostia",me=1000;async function w(o){let D=s({runs:o.runs??null,warmup:o.warmup??null,cpu:o.cpu??!1,heap:o.heap??!1,cpuIntervalUs:o.cpuIntervalUs??me}),C=`${o.outDir??cn}/artifacts`,x=[],v=[];for(let N of o.commands){let P=Array.isArray(N)?N:Re(N),U=u(P,Array.isArray(N)?void 0:N);x.push(U);let M=await f({argv:P,cwd:o.cwd,env:o.env,runs:o.runs,warmup:o.warmup}),F=i({workload:U,configFingerprint:D,trials:M.trials,timing:M.timing,warnings:M.warnings});if(v.push(F),o.cpu){let B=`${F.id}-cpu.cpuprofile`,A=await de({argv:P,cwd:o.cwd,env:o.env,artifactDir:C,fileName:B,intervalUs:o.cpuIntervalUs??me});v.push(await Ee({workload:U,phase:"cpu",configFingerprint:D,diagnosticWallNs:A.diagnosticWallNs,exitCode:A.exitCode,cpu:A.cpu,artifactPath:A.artifactPath,artifactKind:"cpuprofile",warnings:A.warnings}))}if(o.heap){let B=`${F.id}-heap.heapsnapshot`,A=await ge({argv:P,cwd:o.cwd,env:o.env,artifactDir:C,fileName:B});v.push(await Ee({workload:U,phase:"heap",configFingerprint:D,diagnosticWallNs:A.diagnosticWallNs,exitCode:A.exitCode,heap:A.heap,artifactPath:A.artifactPath,artifactKind:"heapsnapshot",warnings:A.warnings}))}}return r(x,v)}async function Ee(o){let D=`${o.workload.id}-${o.phase}-${o.configFingerprint}`,c=o.artifactPath?[await T(D,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,D={}){let c=R(o),C=s({intervalUs:D.intervalUs??me,origin:D.origin??"inspector"}),x=(M)=>M.samples?.nodeIds.length===0?[{code:"empty-profile",message:"In-process capture produced zero samples."}]:[];if(D.origin==="jsc"){let{result:M,cpu:F,jit:B,diagnosticWallNs:A}=await we(o,D),J=h({workload:c,phase:"cpu",configFingerprint:C,diagnosticWallNs:A,cpu:F,jit:B,warnings:x(F),artifacts:[]});return{result:M,run:J}}let{result:v,cpu:N,diagnosticWallNs:P}=await he(o,D),U=h({workload:c,phase:"cpu",configFingerprint:C,diagnosticWallNs:P,cpu:N,warnings:x(N),artifacts:[]});return{result:v,run:U}}
21
+ export{k,p,a,d,b,f,n,w,I};
package/cli.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
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(`
3
+ import{k,p,a,d,b,f,n,w}from"./chunk-s1d2tx3w.js";import{e,c,r,u,i,s,o,t}from"./chunk-3rp84rbb.js";function q(m){return e("cache",m.workloadId,m.phase,m.configFingerprint,m.bunVersion,m.toolVersion,m.instrumented,m.inputsDigest??null)}async function J(m,l=process.cwd()){if(m.length===0)return;let h=new Set;for(let x of m){let C=new Bun.Glob(x);for await(let y of C.scan({cwd:l,absolute:!1}))h.add(y)}let P=[...h].sort(),g=await Promise.all(P.map(async(x)=>{let C=await Bun.file(`${l}/${x}`).arrayBuffer();return{path:x,sha256:Bun.CryptoHasher.hash("sha256",C,"hex")}}));return e("inputs",g)}function _(m,l){return`${m}/cache/${l}.json`}async function L(m,l){let h=Bun.file(_(m,l));if(!await h.exists())return;return await h.json()}async function M(m,l,h){await Bun.write(_(m,l),`${JSON.stringify(h,null,2)}
4
+ `)}var X="node_modules/.cache/ostia",Q=".ostia/baselines",Y={runs:null,warmup:3,outDir:X,baselineDir:Q,baseline:"main",cpuIntervalUs:1000,thresholds:a,workloads:[]};async function W(m="ostia.config.json"){let l=Bun.file(m);if(!await l.exists())return;let h=await l.json();return{...Y,...h,thresholds:{...a,...h.thresholds??{}}}}function V(m,l){return`${m.baselineDir}/${l??m.baseline}.json`}class T extends Error{path;constructor(m){super(`No baseline document at ${m}. Create one with: ostia run --export-json ${m} <command...>`);this.path=m}}async function z(m){let{config:l}=m,h=V(l,m.baselineName);if(!await Bun.file(h).exists())throw new T(h);let g=await t(h),x=[],C=0,y=0,F=0;for(let R of l.workloads){let A=u(R.command,R.label),Z=await J(R.inputs??[]),v=s({runs:l.runs,warmup:l.warmup}),U=q({workloadId:A.id,phase:"timing",configFingerprint:v,bunVersion:Bun.version,toolVersion:c,instrumented:!1,inputsDigest:Z}),H=m.full?void 0:await L(l.outDir,U),S,B;if(H)S=H,B="cached",y++;else{C++;let O=await f({argv:R.command,runs:l.runs??void 0,warmup:l.warmup});S=i({workload:A,configFingerprint:v,trials:O.trials,timing:O.timing,warnings:O.warnings}),await M(l.outDir,U,S),B="executed",F++}x.push({workload:A,status:B,run:S})}let D=r(x.map((R)=>R.workload),x.map((R)=>R.run)),N=0,E=0,j=0;for(let R of x){let A=b(g,D,R.workload.id,l.thresholds);if(!A){j++;continue}if(R.comparison=A,A.verdict==="pass")N++;else E++}return D.comparisons=x.map((R)=>R.comparison).filter((R)=>R!==void 0),{document:D,summary:{total:l.workloads.length,affected:C,cached:y,executed:F,passed:N,regressed:E,missingBaseline:j,results:x}}}function K(m){let l=[];if(l.push(`${m.total} workloads`),l.push(`${m.affected} affected by this change`),l.push(`${m.cached} cached`),l.push(`${m.executed} executed`),m.missingBaseline>0)l.push(`${m.missingBaseline} skipped (no matching baseline workload)`);let h=m.results.filter((P)=>P.comparison?.verdict==="fail").map((P)=>{let g=P.comparison.timing,x=P.workload.label??P.workload.command?.join(" ")??P.workload.id;return g?`${g.medianDeltaPct>0?"+":""}${g.medianDeltaPct.toFixed(1)}% median on ${x}`:x});return l.push(`${m.passed} passed ${m.regressed} regressed${h.length>0?` (${h.join(", ")})`:""}`),l.push(""),l.push(`Profile CI: ${m.regressed>0?"\u2717":"\u2713"}`),`${l.join(`
5
5
  `)}
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)"} ---
6
+ `}async function I(m,l){if(m.text)process.stdout.write(m.text);if(!m.files||m.files.length===0)return;if(l)for(let h of m.files){let P=h.path?`${l}/${h.path}`:l;await Bun.write(P,h.content),process.stdout.write(`wrote ${P}
7
+ `)}else if(m.files.length===1)process.stdout.write(m.files[0].content);else for(let h of m.files)process.stdout.write(`--- ${h.path??"(unnamed)"} ---
8
8
  ${h.content}
9
- `)}var Y=`ostia run [flags] <command...>
9
+ `)}var ee=`ostia run [flags] <command...>
10
10
 
11
11
  Run one or more commands N times with warmup and report timing statistics.
12
12
 
@@ -18,7 +18,7 @@ Flags:
18
18
  --cpu-interval USEC CPU sampling interval in microseconds (default: 1000)
19
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
- --format FORMAT table | json (default: table)
21
+ --format FORMAT table | json | jsonl | markdown | minimal (default: table)
22
22
  --quiet suppress the rendered report (still writes --export-json)
23
23
  --help show this message
24
24
 
@@ -30,7 +30,7 @@ Examples:
30
30
  ostia run --runs 25 --warmup 3 "bun a.ts" "bun b.ts"
31
31
  ostia run --cpu --heap "bun src/server.ts"
32
32
  ostia run --format json "bun a.ts"
33
- `,ee=`ostia bench [flags] <suite.ts...>
33
+ `,te=`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).
@@ -38,14 +38,27 @@ in its own spawned child process (isolated from CLI startup state).
38
38
  Flags:
39
39
  --time-budget MS sampling budget per task; always runs at least this long (default: 500)
40
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
+ budget. Default: cost-aware - as many as fit in the budget (max 20),
42
+ but never below the floor the task's per-trial cost earns it: 3 at
43
+ <=1ms, +2 per decade of cost, 10 from ~3s up. Cheap tasks are
44
+ time-bound and collect thousands either way; only the few expensive
45
+ tasks in a suite pay for the extra rigor. A run that ends below its
46
+ cost-class floor (only possible with an explicit --min-samples or
47
+ per-task minSamples) carries a "low-sample-count" warning.
48
+ --jobs N|auto suite files to run at once, each still in its own process (default: 1).
49
+ Concurrent CPU-bound processes contend for cores, caches and turbo
50
+ headroom, so numbers taken at --jobs > 1 are noisier and not
51
+ like-for-like with a baseline measured at 1. "auto" = CPU count.
43
52
  --gc Bun.gc(true) between trials (default: off - hides allocation cost)
44
53
  --filter REGEX only run tasks whose "group/name" id matches this regex (substring,
45
54
  case-sensitive; unmatched tasks are skipped, not timed)
46
55
  --out-dir PATH directory for scratch IPC files (default: node_modules/.cache/ostia)
47
56
  --export-json PATH write the full ProfileDocument to PATH
48
- --format FORMAT table | json (default: table)
57
+ --format FORMAT table | json | jsonl | markdown | minimal (default: table)
58
+ "minimal" is one compact JSON object per task with no raw sample
59
+ array: {task, group, description, samples, mean, median, stddevPct,
60
+ relative, warnings[{code,data}]} in ns - built to pipe into an LLM
61
+ agent's context.
49
62
  --quiet suppress the rendered report (still writes --export-json)
50
63
  --help show this message
51
64
 
@@ -54,31 +67,35 @@ Suite files register tasks like:
54
67
  group("parse", () => {
55
68
  task("small input", () => parse(smallBuf))
56
69
  task("full pipeline", () => build(), { timeBudgetMs: 2000, minSamples: 10 })
57
- })
70
+ }, { description: "parser throughput on representative inputs" })
58
71
  Per-task options override --time-budget / --min-samples for that task only.
72
+ Optional { description } on group() and task() flows into the document (Workload.description
73
+ / Workload.groupDescription) so the intent travels with the numbers.
59
74
 
60
75
  Examples:
61
76
  ostia bench benches/parse.ts
62
77
  ostia bench --time-budget 1000 --min-samples 50 benches/*.ts
63
78
  ostia bench benches/*.ts --filter parse
64
- `,K=`ostia compare <base.json> <candidate.json>
79
+ ostia bench benches/*.ts --jobs auto --format minimal
80
+ `,G=`ostia compare <base.json> <candidate.json>
65
81
  ostia compare <candidate.json> --baseline <path.json>
66
82
 
67
83
  Compare two ProfileDocuments (matched by workload id) and rank timing/frame/heap deltas.
68
84
 
69
85
  Flags:
70
86
  --export-json PATH write the resulting document (with comparisons) to PATH
71
- --format FORMAT table | json (default: table)
87
+ --format FORMAT table | json | jsonl | markdown | minimal (default: table)
88
+ "minimal" adds delta: {medianPct, verdict, pass} to each task line
72
89
  --quiet suppress the rendered report (still writes --export-json)
73
90
  --help show this message
74
91
 
75
92
  Examples:
76
93
  ostia compare before.json after.json
77
94
  ostia compare after.json --baseline .ostia/baselines/main.json
78
- `,te=`ostia report <document.json> [--format table|json|markdown|jsonl]
95
+ `,re=`ostia report <document.json> [--format table|json|markdown|jsonl|minimal]
79
96
 
80
97
  Render a saved ProfileDocument.
81
- `,re=`ostia viz <document.json> --format FORMAT [--run <id>] [--out-dir PATH]
98
+ `,se=`ostia viz <document.json> --format FORMAT [--run <id>] [--out-dir PATH]
82
99
 
83
100
  Render CPU evidence from a saved ProfileDocument as a visualization artifact. Files,
84
101
  not a GUI - hand the output to speedscope.app, flamegraph.pl, or
@@ -99,7 +116,7 @@ Flags:
99
116
  Examples:
100
117
  ostia viz run.json --format speedscope --out-dir node_modules/.cache/ostia/viz
101
118
  ostia viz run.json --format collapsed | flamegraph.pl > flame.svg
102
- `,se=`ostia ci [--full] [--baseline NAME]
119
+ `,ne=`ostia ci [--full] [--baseline NAME]
103
120
 
104
121
  Load ostia.config.json, run configured workloads (reusing cached results when their
105
122
  fingerprint is unchanged), compare against the named baseline, and gate on regressions.
@@ -112,21 +129,22 @@ Flags:
112
129
  --help show this message
113
130
 
114
131
  Exit codes: 0 pass, 1 regression, 2 harness error (missing config/baseline, spawn failure).
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(", ")}
132
+ `;function oe(m){let l=[],h,P,g=!1,x=!1,C,y,F,D="table",N=!1,E=!1;for(let j=0;j<m.length;j++){let R=m[j];switch(R){case"--runs":h=Number(m[++j]);break;case"--warmup":P=Number(m[++j]);break;case"--cpu":g=!0;break;case"--heap":x=!0;break;case"--cpu-interval":C=Number(m[++j]);break;case"--out-dir":y=m[++j];break;case"--export-json":F=m[++j];break;case"--format":D=m[++j];break;case"--quiet":N=!0;break;case"--help":case"-h":E=!0;break;default:l.push(R)}}return{commands:l,runs:h,warmup:P,cpu:g,heap:x,cpuIntervalUs:C,outDir:y,exportJson:F,format:D,quiet:N,help:E}}async function ae(m){let l=oe(m);if(l.help||l.commands.length===0)return process.stdout.write(ee),l.help?0:2;if(!(l.format in n))return process.stderr.write(`Unknown --format "${l.format}". Expected one of: ${Object.keys(n).join(", ")}
116
133
  `),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)}
134
+ `),2}if(l.exportJson)await o(h,l.exportJson);if(!l.quiet){let x=await n[l.format].render(h,{});await I(x)}return h.runs.some((g)=>g.trials.some((x)=>x.exitCode!==void 0&&x.exitCode!==0))?1:0}function ie(m){let l=[],h,P,g,x=!1,C,y,F,D="table",N=!1,E=!1;for(let j=0;j<m.length;j++){let R=m[j];switch(R){case"--time-budget":h=Number(m[++j]);break;case"--min-samples":P=Number(m[++j]);break;case"--jobs":{let A=m[++j];g=A==="auto"?k():Number(A);break}case"--gc":x=!0;break;case"--filter":C=m[++j];break;case"--out-dir":y=m[++j];break;case"--export-json":F=m[++j];break;case"--format":D=m[++j];break;case"--quiet":N=!0;break;case"--help":case"-h":E=!0;break;default:l.push(R)}}return{suites:l,timeBudgetMs:h,minSamples:P,jobs:g,gc:x,filter:C,outDir:y,exportJson:F,format:D,quiet:N,help:E}}async function ue(m){let l=ie(m);if(l.help||l.suites.length===0)return process.stdout.write(te),l.help?0:2;if(!(l.format in n))return process.stderr.write(`Unknown --format "${l.format}". Expected one of: ${Object.keys(n).join(", ")}
135
+ `),2;if(l.jobs!==void 0&&!(l.jobs>=1))return process.stderr.write(`--jobs expects a positive integer or "auto".
136
+ `),2;let h;try{h=await p({suites:l.suites,timeBudgetMs:l.timeBudgetMs,minSamples:l.minSamples,jobs:l.jobs,gc:l.gc,filter:l.filter,outDir:l.outDir})}catch(P){return process.stderr.write(`Bench failed: ${P instanceof Error?P.message:String(P)}
137
+ `),2}if(l.exportJson)await o(h,l.exportJson);if(!l.quiet){let g=await n[l.format].render(h,{});await I(g)}return 0}function le(m){let l=[],h,P,g="table",x=!1,C=!1;for(let y=0;y<m.length;y++){let F=m[y];switch(F){case"--baseline":h=m[++y];break;case"--export-json":P=m[++y];break;case"--format":g=m[++y];break;case"--quiet":x=!0;break;case"--help":case"-h":C=!0;break;default:l.push(F)}}return{paths:l,baseline:h,exportJson:P,format:g,quiet:x,help:C}}async function ce(m){let l=le(m);if(l.help)return process.stdout.write(G),0;let h,P;if(l.baseline)h=l.baseline,P=l.paths[0];else h=l.paths[0],P=l.paths[1];if(!h||!P)return process.stdout.write(G),2;let g,x;try{[g,x]=await Promise.all([t(h),t(P)])}catch(D){return process.stderr.write(`Failed to load documents: ${D instanceof Error?D.message:String(D)}
138
+ `),2}let C=d(g,x),y={...x,comparisons:C};if(l.exportJson)await o(y,l.exportJson);if(!l.quiet){let N=await n[l.format].render(y,{});await I(N)}return C.some((D)=>D.verdict==="fail")?1:0}function de(m){let l,h="table",P=!1;for(let g=0;g<m.length;g++){let x=m[g];switch(x){case"--format":h=m[++g];break;case"--help":case"-h":P=!0;break;default:l=x}}return{path:l,format:h,help:P}}async function me(m){let l=de(m);if(l.help||!l.path)return process.stdout.write(re),l.help?0:2;let h;try{h=await t(l.path)}catch(x){return process.stderr.write(`Failed to load ${l.path}: ${x instanceof Error?x.message:String(x)}
139
+ `),2}let g=await n[l.format].render(h,{});return await I(g),0}var pe={ascii:"table"};function fe(m){let l,h,P,g,x=!1;for(let C=0;C<m.length;C++){let y=m[C];switch(y){case"--format":{let F=m[++C]??"";h=pe[F]??F;break}case"--run":P=m[++C];break;case"--out-dir":g=m[++C];break;case"--help":case"-h":x=!0;break;default:l=y}}return{path:l,format:h,runId:P,outDir:g,help:x}}async function he(m){let l=fe(m);if(l.help||!l.path||!l.format)return process.stdout.write(se),l.help?0:2;if(!(l.format in n))return process.stderr.write(`Unknown --format "${l.format}". Expected one of: ${Object.keys(n).join(", ")}, ascii
140
+ `),2;let h;try{h=await t(l.path)}catch(x){return process.stderr.write(`Failed to load ${l.path}: ${x instanceof Error?x.message:String(x)}
123
141
  `),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}".
124
142
  `:`No CPU evidence found in this document (no cpu-phase runs). Capture some with "ostia run --cpu ...".
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.
143
+ `),2;return await I(g,l.outDir),0}function ge(m){let l=!1,h,P,g=!1,x=!1;for(let C=0;C<m.length;C++)switch(m[C]){case"--full":l=!0;break;case"--baseline":h=m[++C];break;case"--export-json":P=m[++C];break;case"--quiet":g=!0;break;case"--help":case"-h":x=!0;break}return{full:l,baseline:h,exportJson:P,quiet:g,help:x}}async function be(m){let l=ge(m);if(l.help)return process.stdout.write(ne),0;let h=await W();if(!h)return process.stderr.write(`No ostia.config.json found. "ostia ci" needs configured workloads.
126
144
  `),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}
145
+ `),2;let P;try{P=await z({config:h,full:l.full,baselineName:l.baseline})}catch(g){if(g instanceof T)return process.stderr.write(`${g.message}
128
146
  `),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
147
+ `),2}if(l.exportJson)await o(P.document,l.exportJson);if(!l.quiet)process.stdout.write(K(P.summary));return P.summary.regressed>0?1:0}async function we(){let[m,...l]=process.argv.slice(2);switch(m){case"run":return ae(l);case"bench":return ue(l);case"compare":return ce(l);case"report":return me(l);case"ci":return be(l);case"viz":return he(l);case void 0:case"--help":case"-h":return process.stdout.write(`ostia - Bun-native profile IR engine
130
148
 
131
149
  Commands:
132
150
  run Run commands N times and report timing/CPU/heap
@@ -137,5 +155,5 @@ Commands:
137
155
  viz Render CPU evidence as collapsed/mermaid/speedscope/cpuprofile
138
156
 
139
157
  Run "ostia <command> --help" for details.
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));
158
+ `),m===void 0?2:0;default:return process.stderr.write(`Unknown subcommand "${m}". Run "ostia --help".
159
+ `),2}}if(import.meta.main)we().then((m)=>process.exit(m));
package/index.d.ts CHANGED
@@ -38,20 +38,31 @@ export interface ProfileDocument {
38
38
  comparisons?: Comparison[];
39
39
  }
40
40
 
41
- interface Workload {
41
+ export interface Workload {
42
42
  id: string;
43
43
  kind: "subprocess" | "inprocess";
44
44
  label?: string;
45
45
  command?: string[];
46
46
  shell?: string;
47
+ /** `task` is the "group/name" id the bench registry assigns; `group` is the
48
+ * enclosing `group()` name when there is one. Renderers prefer `group` over
49
+ * splitting `task` on "/", so task names may contain slashes. */
47
50
  entry?: {
48
51
  file: string;
49
52
  task: string;
53
+ group?: string;
50
54
  };
51
55
  /** Marks this task as the in-run Relative reference for its group (see
52
56
  * `task(name, fn, { baseline: true })`). At most one per group is
53
57
  * meaningful; renderers use the first they encounter. */
54
58
  baseline?: boolean;
59
+ /** What this task measures and why, from `task(name, fn, { description })`.
60
+ * Travels with the data so a reader of the document has intent, not just
61
+ * numbers. */
62
+ description?: string;
63
+ /** The enclosing group's `group(name, fn, { description })`. Repeated on every
64
+ * workload in the group so each record is self-contained. */
65
+ groupDescription?: string;
55
66
  }
56
67
 
57
68
  type Phase = "timing" | "cpu" | "heap" | "memstats";
@@ -168,9 +179,9 @@ interface JitTierBreakdown {
168
179
  }[];
169
180
  }
170
181
 
171
- type WarningCode = "slow-first-run" | "outliers-detected" | "fast-command" | "nonzero-exit" | "instrumented-timing" | "artifact-missing" | "empty-profile" | "below-timer-resolution" | "cache-fallback-rerun";
182
+ export type WarningCode = "slow-first-run" | "outliers-detected" | "fast-command" | "nonzero-exit" | "instrumented-timing" | "artifact-missing" | "empty-profile" | "below-timer-resolution" | "cache-fallback-rerun" | "low-sample-count";
172
183
 
173
- interface Warning {
184
+ export interface Warning {
174
185
  code: WarningCode;
175
186
  message: string;
176
187
  data?: Record<string, unknown>;
@@ -223,6 +234,12 @@ interface BenchOptions {
223
234
  minSamples?: number;
224
235
  gc?: boolean;
225
236
  filter?: string;
237
+ /** Suite files to run at once, each still in its own child process (default:
238
+ * 1). Files are independent by design, so this is a wall-clock win for
239
+ * multi-file suites, but concurrent CPU-bound processes contend for cores,
240
+ * caches, memory bandwidth and turbo headroom: timings taken under `jobs > 1`
241
+ * are noisier and not like-for-like with a baseline measured at 1. */
242
+ jobs?: number;
226
243
  outDir?: string;
227
244
  cwd?: string;
228
245
  }
@@ -238,9 +255,18 @@ export interface TaskOptions {
238
255
  /** Per-task hard floor on trials; overrides the suite-wide `--min-samples` /
239
256
  * `minSamples`. */
240
257
  minSamples?: number;
258
+ /** What this task measures and why. Flows into `Workload.description` so the
259
+ * intent travels with the numbers instead of living only in a source comment. */
260
+ description?: string;
241
261
  }
242
262
 
243
- export declare function group(name: string, fn: () => void): void;
263
+ export interface GroupOptions {
264
+ /** What this group measures and why. Flows into `Workload.groupDescription`
265
+ * on every task in the group. */
266
+ description?: string;
267
+ }
268
+
269
+ export declare function group(name: string, fn: () => void, opts?: GroupOptions): void;
244
270
 
245
271
  export declare function task(name: string, fn: () => unknown | Promise<unknown>, opts?: TaskOptions): void;
246
272
 
@@ -259,7 +285,7 @@ export declare function loadDocument(path: string): Promise<ProfileDocument>;
259
285
 
260
286
  export declare const renderers: Record<FormatName, Renderer<any>>;
261
287
 
262
- type FormatName = "table" | "json" | "markdown" | "jsonl" | "collapsed" | "mermaid" | "speedscope" | "cpuprofile";
288
+ type FormatName = "table" | "json" | "markdown" | "jsonl" | "minimal" | "collapsed" | "mermaid" | "speedscope" | "cpuprofile";
263
289
 
264
290
  interface RenderResult {
265
291
  text?: string;
@@ -273,3 +299,34 @@ interface Renderer<O = unknown> {
273
299
  name: FormatName;
274
300
  render(doc: ProfileDocument, options: O): Promise<RenderResult>;
275
301
  }
302
+
303
+ export interface MinimalLine {
304
+ task: string;
305
+ group?: string;
306
+ description?: string;
307
+ groupDescription?: string;
308
+ unit: "ns";
309
+ samples: number;
310
+ mean: number;
311
+ median: number;
312
+ stddev: number;
313
+ stddevPct: number;
314
+ min: number;
315
+ max: number;
316
+ /** Median over the group's reference median (its baseline task, else its
317
+ * fastest). Only present when the document has more than one timing run. */
318
+ relative?: number;
319
+ baseline?: true;
320
+ warnings: {
321
+ code: string;
322
+ data?: Record<string, unknown>;
323
+ }[];
324
+ /** From `comparisons` when present (ostia compare / ci): the change against
325
+ * the baseline document for this task. */
326
+ delta?: {
327
+ medianPct: number;
328
+ meanPct: number;
329
+ verdict: "improved" | "regressed" | "unchanged";
330
+ pass: boolean;
331
+ };
332
+ }
package/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // @bun
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};
2
+ import{p,d,n,w,I}from"./chunk-s1d2tx3w.js";import{o,t,F,v}from"./chunk-3rp84rbb.js";export{p as bench,d as compareDocuments,F as group,t as loadDocument,I as profile,n as renderers,w as run,o as saveDocument,v as task};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ostia",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Fast profiling and benchmarking for Bun.",
5
5
  "type": "module",
6
6
  "exports": {
package/runner.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- import{r,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));
3
+ import{r,P,i,s,o,l,m,C,N,x,D}from"./chunk-3rp84rbb.js";var J=500,z=20,A=3,H=10,j=2,v=0.1,X=1000,q=1e4;function G(n){let e=Math.log10(Math.max(1,n)/1e6),a=Math.round(A+j*e);return Math.min(H,Math.max(A,a))}function K(n,e){let a=Math.floor(e/n);return Math.min(z,Math.max(a,G(n)))}var y=0;function S(n){if(typeof n==="number")y+=n;else if(n!==void 0&&n!==null)y+=1}function B(n){return n!==null&&typeof n==="object"&&typeof n.then==="function"}function L(n,e){return Math.max(1,Math.ceil(X/n),Math.ceil(e/(n*q)))}async function U(n,e={}){let a=(e.timeBudgetMs??J)*1e6,b=a*(e.warmupFraction??v),T=Bun.nanoseconds(),f=0,h=0;while(h<b){let c=n();S(B(c)?await c:c),f++,h=Bun.nanoseconds()-T}let p;if(f>0)p=Math.max(1,h/f);else{let c=Bun.nanoseconds(),g=n();S(B(g)?await g:g),p=Math.max(1,Bun.nanoseconds()-c)}let t=L(p,a);if(t>1){let c=Bun.nanoseconds();for(let g=0;g<t;g++){let w=n();S(B(w)?await w:w)}p=Math.max(1,(Bun.nanoseconds()-c)/t),t=L(p,a)}let d=p*t,k=e.minSamples??K(d,a),u=[],M=Bun.nanoseconds(),F=0,O=0;while(O<k||F<a){let c=Bun.nanoseconds();for(let w=0;w<t;w++){let _=n();S(B(_)?await _:_)}let g=Bun.nanoseconds();if(u.push({i:O,wallNs:(g-c)/t}),O++,F=Bun.nanoseconds()-M,e.gc)Bun.gc(!0)}let W=u.map((c)=>c.wallNs),I=l(W),E=m(I,[],"inprocess"),R=G(d);if(u.length<R)E.push({code:"low-sample-count",message:`Only ${u.length} sample(s) at ~${Q(d)} per trial; ${R} is the floor for this cost class. Raise minSamples or the time budget for a steadier number.`,data:{samples:u.length,target:R,trialCostNs:d}});return{trials:u,timing:I,warnings:E}}function Q(n){if(n>=1e9)return`${(n/1e9).toFixed(2)}s`;if(n>=1e6)return`${(n/1e6).toFixed(1)}ms`;if(n>=1000)return`${(n/1000).toFixed(1)}\xB5s`;return`${n.toFixed(0)}ns`}async function V(){let[n,e,a]=process.argv.slice(2);if(!n||!e)return process.stderr.write(`bench runner: usage: runner.ts <suiteFile> <outputPath> [optsJson]
4
+ `),2;let b=a?JSON.parse(a):{};N(),await import(n);let T=C();if(T.length===0)return process.stderr.write(`bench runner: ${n} registered no tasks (no task() calls found).
5
+ `),2;let f=D(T,b.filter);if(f.length===0)return process.stderr.write(`bench runner: --filter ${JSON.stringify(b.filter)} matched zero of ${T.length} registered tasks in ${n}.
6
+ `),2;let h=[],p=[];for(let t of f){let d=x(t),k=P(n,d,{label:d,baseline:t.baseline,group:t.groupName,description:t.opts?.description,groupDescription:t.groupDescription});h.push(k);let u={...b,...t.opts?.timeBudgetMs!==void 0&&{timeBudgetMs:t.opts.timeBudgetMs},...t.opts?.minSamples!==void 0&&{minSamples:t.opts.minSamples}},M=await U(t.fn,u);p.push(i({workload:k,configFingerprint:s({timeBudgetMs:u.timeBudgetMs??null,minSamples:u.minSamples??null,gc:u.gc??!1}),trials:M.trials,timing:M.timing,warnings:M.warnings}))}return await o(r(h,p),e),0}V().then((n)=>process.exit(n));
package/chunk-m8zhsw7r.js DELETED
@@ -1,19 +0,0 @@
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};
package/chunk-qh19pbhc.js DELETED
@@ -1,4 +0,0 @@
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};