{"version":3,"file":"profiler.cjs","names":[],"sources":["../../src/perf/profiler.ts"],"sourcesContent":["import { cachedResponseBytes } from \"./cache-size\";\nimport { readDeviceProfile } from \"./device\";\nimport type {\n    InferenceProfiler,\n    InferenceReport,\n    InferenceReportOptions,\n    ProfiledModelSize,\n} from \"./types\";\n\n/**\n * Timing and cost accounting for a pipeline that runs on the user's device.\n */\n\n/**\n * Create a profiler for one run of a pipeline.\n *\n * Wrap each step in {@link InferenceProfiler.stage}, fold in durations you\n * already have (an SDK `speed` breakdown, say) with\n * {@link InferenceProfiler.mark}, then call `report()` once the run finishes.\n *\n * Stages are timed independently rather than as a tiling of the run, so\n * concurrent work is charged its real wall-clock span to each stage and the\n * timings can sum to more than `totalMs`. Surface that to users when you\n * render the breakdown — a bar chart implying a partition of the total would\n * be wrong for a pipeline that overlaps stages.\n *\n * @returns A profiler bound to the moment it was created.\n *\n * @example\n * ```typescript\n * import { createInferenceProfiler } from \"tempest-react-sdk\";\n * import { Detector } from \"tempest-react-sdk/vision\";\n *\n * const profiler = createInferenceProfiler();\n * const detector = await profiler.stage(\"load-model\", () =>\n *     Detector.create(\"/models/detect.onnx\"),\n * );\n * const results = await profiler.stage(\"detect\", () => detector.predict(blob));\n * profiler.mark(\"forward-pass\", results[0].speed.inference);\n *\n * const report = await profiler.report({\n *     models: [\n *         { name: \"detector\", cacheName: \"app-models\", url: \"/models/detect.onnx\" },\n *     ],\n * });\n * console.log(report.timings, report.totalMs, report.device, report.models);\n * ```\n */\nexport function createInferenceProfiler(): InferenceProfiler {\n    const startedAt = performance.now();\n    const timings = new Map<string, number>();\n\n    const add = (name: string, durationMs: number): void => {\n        timings.set(name, (timings.get(name) ?? 0) + durationMs);\n    };\n\n    return {\n        async stage<T>(name: string, run: () => Promise<T>): Promise<T> {\n            const from = performance.now();\n            try {\n                return await run();\n            } finally {\n                add(name, performance.now() - from);\n            }\n        },\n\n        stageSync<T>(name: string, run: () => T): T {\n            const from = performance.now();\n            try {\n                return run();\n            } finally {\n                add(name, performance.now() - from);\n            }\n        },\n\n        mark(name: string, durationMs: number): void {\n            add(name, durationMs);\n        },\n\n        async report(options: InferenceReportOptions = {}): Promise<InferenceReport> {\n            const totalMs = performance.now() - startedAt;\n            const models: ProfiledModelSize[] = await Promise.all(\n                (options.models ?? []).map(async (model) => ({\n                    name: model.name,\n                    bytes: await cachedResponseBytes(model.cacheName, model.url),\n                })),\n            );\n\n            return {\n                timings: Object.fromEntries(timings),\n                totalMs,\n                device: readDeviceProfile(),\n                models,\n                measuredAt: Date.now(),\n            };\n        },\n    };\n}\n"],"mappings":"8DAgDA,SAAgB,GAA6C,CACzD,IAAM,EAAY,YAAY,IAAI,EAC5B,EAAU,IAAI,IAEd,GAAO,EAAc,IAA6B,CACpD,EAAQ,IAAI,GAAO,EAAQ,IAAI,CAAI,GAAK,GAAK,CAAU,CAC3D,EAEA,MAAO,CACH,MAAM,MAAS,EAAc,EAAmC,CAC5D,IAAM,EAAO,YAAY,IAAI,EAC7B,GAAI,CACA,OAAO,MAAM,EAAI,CACrB,QAAU,CACN,EAAI,EAAM,YAAY,IAAI,EAAI,CAAI,CACtC,CACJ,EAEA,UAAa,EAAc,EAAiB,CACxC,IAAM,EAAO,YAAY,IAAI,EAC7B,GAAI,CACA,OAAO,EAAI,CACf,QAAU,CACN,EAAI,EAAM,YAAY,IAAI,EAAI,CAAI,CACtC,CACJ,EAEA,KAAK,EAAc,EAA0B,CACzC,EAAI,EAAM,CAAU,CACxB,EAEA,MAAM,OAAO,EAAkC,CAAC,EAA6B,CACzE,IAAM,EAAU,YAAY,IAAI,EAAI,EAC9B,EAA8B,MAAM,QAAQ,KAC7C,EAAQ,QAAU,CAAC,EAAA,CAAG,IAAI,KAAO,KAAW,CACzC,KAAM,EAAM,KACZ,MAAO,MAAM,EAAA,oBAAoB,EAAM,UAAW,EAAM,GAAG,CAC/D,EAAE,CACN,EAEA,MAAO,CACH,QAAS,OAAO,YAAY,CAAO,EACnC,UACA,OAAQ,EAAA,kBAAkB,EAC1B,SACA,WAAY,KAAK,IAAI,CACzB,CACJ,CACJ,CACJ"}