@camstack/addon-benchmark 0.1.32 → 0.2.0
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/dist/_stub.js +54343 -15828
- package/dist/_virtual_mf-localSharedImportMap___mfe_internal__addon_benchmark_page-bQNWCtal.mjs +156 -0
- package/dist/_virtual_mf___mfe_internal__addon_benchmark_page__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.js-DSTkBuYy.mjs +25 -0
- package/dist/_virtual_mf___mfe_internal__addon_benchmark_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CICN6dKn.mjs +26 -0
- package/dist/_virtual_mf___mfe_internal__addon_benchmark_page__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-lv97RBhq.mjs +89 -0
- package/dist/_virtual_mf___mfe_internal__addon_benchmark_page__loadShare___mf_0_trpc_mf_1_client__loadShare__.js-DtWmo0vJ.mjs +58 -0
- package/dist/_virtual_mf___mfe_internal__addon_benchmark_page__loadShare___mf_0_trpc_mf_1_react_mf_2_query__loadShare__.js-Bh7FS7ML.mjs +62 -0
- package/dist/_virtual_mf___mfe_internal__addon_benchmark_page__loadShare__react__loadShare__.js-DHm30T13.mjs +70 -0
- package/dist/_virtual_mf___mfe_internal__addon_benchmark_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-SOU_VnTj.mjs +34 -0
- package/dist/_virtual_mf___mfe_internal__addon_benchmark_page__loadShare__react_mf_2_dom__loadShare__.js-DQaf3kYb.mjs +45 -0
- package/dist/_virtual_mf___mfe_internal__addon_benchmark_page__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-DUzuN6aS.mjs +34 -0
- package/dist/addon-benchmark.css +3 -1
- package/dist/hostInit-sayMKkNX.mjs +129 -0
- package/dist/index.js +105 -52
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +107 -63
- package/dist/index.mjs.map +1 -1
- package/dist/remoteEntry.js +2 -5
- package/dist/remoteEntry.ssr.js +33 -0
- package/dist/rolldown-runtime-HEgqtunE.mjs +20 -0
- package/dist/virtualExposes-erbhyesj.mjs +27 -0
- package/dist/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_benchmark_page__remoteEntry_js-C6uSRkaU.mjs +2866 -0
- package/dist/virtual_mf-exposes-ssr___mfe_internal__addon_benchmark_page__remoteEntry_js-D9DseO5a.mjs +10 -0
- package/package.json +7 -7
- package/dist/@mf-types/compiled-types/benchmark-schemas.d.ts +0 -580
- package/dist/@mf-types/compiled-types/benchmark-schemas.d.ts.map +0 -1
- package/dist/@mf-types/compiled-types/components/NodeSelector.d.ts +0 -7
- package/dist/@mf-types/compiled-types/components/NodeSelector.d.ts.map +0 -1
- package/dist/@mf-types/compiled-types/page.d.ts +0 -4
- package/dist/@mf-types/compiled-types/page.d.ts.map +0 -1
- package/dist/@mf-types/compiled-types/tabs/AudioTab.d.ts +0 -6
- package/dist/@mf-types/compiled-types/tabs/AudioTab.d.ts.map +0 -1
- package/dist/@mf-types/compiled-types/tabs/DecoderTab.d.ts +0 -8
- package/dist/@mf-types/compiled-types/tabs/DecoderTab.d.ts.map +0 -1
- package/dist/@mf-types/compiled-types/tabs/HistoryTab.d.ts +0 -6
- package/dist/@mf-types/compiled-types/tabs/HistoryTab.d.ts.map +0 -1
- package/dist/@mf-types/compiled-types/tabs/ImageTab.d.ts +0 -6
- package/dist/@mf-types/compiled-types/tabs/ImageTab.d.ts.map +0 -1
- package/dist/@mf-types/compiled-types/tabs/PipelineTab.d.ts +0 -5
- package/dist/@mf-types/compiled-types/tabs/PipelineTab.d.ts.map +0 -1
- package/dist/@mf-types/compiled-types/tabs/WebRTCTab.d.ts +0 -5
- package/dist/@mf-types/compiled-types/tabs/WebRTCTab.d.ts.map +0 -1
- package/dist/@mf-types/compiled-types/webrtc/webrtc-probe.d.ts +0 -68
- package/dist/@mf-types/compiled-types/webrtc/webrtc-probe.d.ts.map +0 -1
- package/dist/ReactKonva-BzgWPfbd.mjs +0 -14906
- package/dist/__mfe_internal__addon_benchmark_page__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.mjs-h5aXOPSA.mjs +0 -12
- package/dist/__mfe_internal__addon_benchmark_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-BfP5_L-n.mjs +0 -19
- package/dist/__mfe_internal__addon_benchmark_page__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.mjs-BLZ56qK0.mjs +0 -104
- package/dist/__mfe_internal__addon_benchmark_page__loadShare___mf_0_trpc_mf_1_client__loadShare__.mjs-BVQD7n0x.mjs +0 -85
- package/dist/__mfe_internal__addon_benchmark_page__loadShare___mf_0_trpc_mf_1_react_mf_2_query__loadShare__.mjs-BXYVnRIg.mjs +0 -62
- package/dist/__mfe_internal__addon_benchmark_page__loadShare__react__loadShare__.mjs-BrIwppg6.mjs +0 -88
- package/dist/__mfe_internal__addon_benchmark_page__loadShare__react__loadShare__.mjs_commonjs-proxy-CfFpaugZ.mjs +0 -29
- package/dist/__mfe_internal__addon_benchmark_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.mjs-rG8Cwul7.mjs +0 -36
- package/dist/__mfe_internal__addon_benchmark_page__loadShare__react_mf_2_dom__loadShare__.mjs-DJwYdRXA.mjs +0 -45
- package/dist/__mfe_internal__addon_benchmark_page__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-BWiw3wbD.mjs +0 -6
- package/dist/__mfe_internal__addon_benchmark_page__loadShare__react_mf_2_dom_mf_1_client__loadShare__.mjs-DJYmMG8o.mjs +0 -34
- package/dist/_virtual_mf-localSharedImportMap___mfe_internal__addon_benchmark_page-B2fB5zg2.mjs +0 -157
- package/dist/client-CAqGcL-G.mjs +0 -9836
- package/dist/getErrorShape-BPSzUA7W-TlK8ipWe.mjs +0 -211
- package/dist/hostInit-ByF79bJr.mjs +0 -168
- package/dist/index-CNHkgWy5.mjs +0 -725
- package/dist/index-CSUlSQBk.mjs +0 -185
- package/dist/index-CWkKuNLr.mjs +0 -232
- package/dist/index-CWoZBQRi.mjs +0 -22989
- package/dist/index-CxPX0kA5.mjs +0 -2603
- package/dist/index-DCic4ySS.mjs +0 -1655
- package/dist/index-DE7FE8uw.mjs +0 -435
- package/dist/index-Dy2V7VOm.mjs +0 -14379
- package/dist/index-xncRG7-x.mjs +0 -2713
- package/dist/jsx-runtime-Dhah4Ixf.mjs +0 -55
- package/dist/schemas-ClCuS4qa.mjs +0 -3594
- package/dist/virtualExposes-pfue1WZv.mjs +0 -42
- package/dist/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_benchmark_page__remoteEntry_js-BHSvSGD1.mjs +0 -2974
package/dist/index.js
CHANGED
|
@@ -14775,7 +14775,9 @@ var MultiCameraStressResultSchema = external_exports.object({
|
|
|
14775
14775
|
var import_types2 = require("@camstack/types");
|
|
14776
14776
|
var benchmarkActions = (0, import_types2.defineCustomActions)({
|
|
14777
14777
|
// Pipeline tester
|
|
14778
|
-
runPipelineTest: (0, import_types2.customAction)(PipelineRunInputSchema, import_types2.PipelineRunResultBridge, {
|
|
14778
|
+
runPipelineTest: (0, import_types2.customAction)(PipelineRunInputSchema, import_types2.PipelineRunResultBridge, {
|
|
14779
|
+
kind: "mutation"
|
|
14780
|
+
}),
|
|
14779
14781
|
/**
|
|
14780
14782
|
* Decode a JPEG once on the server and cache the resulting raw RGB
|
|
14781
14783
|
* buffer keyed by a returned `frameId`. Subsequent `runPipelineTest`
|
|
@@ -14801,7 +14803,9 @@ var benchmarkActions = (0, import_types2.defineCustomActions)({
|
|
|
14801
14803
|
* `pipelineExecutor.runPipelineBatch` cap call. Returns N
|
|
14802
14804
|
* `FrameResult`s plus aggregate timing.
|
|
14803
14805
|
*/
|
|
14804
|
-
runPipelineBatchTest: (0, import_types2.customAction)(PipelineRunBatchInputSchema, PipelineRunBatchResultSchema, {
|
|
14806
|
+
runPipelineBatchTest: (0, import_types2.customAction)(PipelineRunBatchInputSchema, PipelineRunBatchResultSchema, {
|
|
14807
|
+
kind: "mutation"
|
|
14808
|
+
}),
|
|
14805
14809
|
/**
|
|
14806
14810
|
* Multi-camera stress tester — runs the full multi-camera workload
|
|
14807
14811
|
* loop in-process (decode JPEG once, then N parallel "cameras" each
|
|
@@ -14809,7 +14813,11 @@ var benchmarkActions = (0, import_types2.defineCustomActions)({
|
|
|
14809
14813
|
* only aggregate detection-rate stats. Used to measure the pool's
|
|
14810
14814
|
* true throughput ceiling without per-call tRPC overhead.
|
|
14811
14815
|
*/
|
|
14812
|
-
runMultiCameraStressTest: (0, import_types2.customAction)(
|
|
14816
|
+
runMultiCameraStressTest: (0, import_types2.customAction)(
|
|
14817
|
+
MultiCameraStressInputSchema,
|
|
14818
|
+
MultiCameraStressResultSchema,
|
|
14819
|
+
{ kind: "mutation" }
|
|
14820
|
+
),
|
|
14813
14821
|
// History (shared across pipeline + decoder-perf entries)
|
|
14814
14822
|
listBenchmarkHistory: (0, import_types2.customAction)(external_exports.void(), external_exports.array(HistoryEntrySchema).readonly()),
|
|
14815
14823
|
saveBenchmarkResult: (0, import_types2.customAction)(
|
|
@@ -14827,18 +14835,14 @@ var benchmarkActions = (0, import_types2.defineCustomActions)({
|
|
|
14827
14835
|
external_exports.object({ success: external_exports.literal(true) }),
|
|
14828
14836
|
{ kind: "mutation" }
|
|
14829
14837
|
),
|
|
14830
|
-
clearBenchmarkHistory: (0, import_types2.customAction)(
|
|
14831
|
-
|
|
14832
|
-
|
|
14833
|
-
{ kind: "mutation" }
|
|
14834
|
-
),
|
|
14838
|
+
clearBenchmarkHistory: (0, import_types2.customAction)(external_exports.void(), external_exports.object({ success: external_exports.literal(true) }), {
|
|
14839
|
+
kind: "mutation"
|
|
14840
|
+
}),
|
|
14835
14841
|
// Decoder perf — fixture discovery + run control
|
|
14836
14842
|
listDecoderFixtures: (0, import_types2.customAction)(external_exports.void(), external_exports.array(DecoderFixtureSchema).readonly()),
|
|
14837
|
-
runDecoderPerformanceTest: (0, import_types2.customAction)(
|
|
14838
|
-
|
|
14839
|
-
|
|
14840
|
-
{ kind: "mutation" }
|
|
14841
|
-
),
|
|
14843
|
+
runDecoderPerformanceTest: (0, import_types2.customAction)(DecoderPerfInputSchema, DecoderPerfResultSchema, {
|
|
14844
|
+
kind: "mutation"
|
|
14845
|
+
}),
|
|
14842
14846
|
abortDecoderPerformanceTest: (0, import_types2.customAction)(
|
|
14843
14847
|
external_exports.object({ sessionId: external_exports.string() }),
|
|
14844
14848
|
external_exports.object({ aborted: external_exports.boolean() }),
|
|
@@ -14855,18 +14859,20 @@ var import_types3 = require("@camstack/types");
|
|
|
14855
14859
|
var CHUNK_SIZE = 4096;
|
|
14856
14860
|
function emitProgress(eventBus, payload) {
|
|
14857
14861
|
if (!eventBus) return;
|
|
14858
|
-
eventBus.emit(
|
|
14859
|
-
|
|
14860
|
-
|
|
14861
|
-
|
|
14862
|
-
|
|
14863
|
-
|
|
14864
|
-
|
|
14865
|
-
|
|
14866
|
-
|
|
14867
|
-
|
|
14868
|
-
|
|
14869
|
-
|
|
14862
|
+
eventBus.emit(
|
|
14863
|
+
(0, import_types3.createEvent)(
|
|
14864
|
+
"benchmark.progress",
|
|
14865
|
+
{ type: "benchmark", id: "decoder-perf" },
|
|
14866
|
+
{
|
|
14867
|
+
kind: payload.kind,
|
|
14868
|
+
sessionId: payload.sessionId,
|
|
14869
|
+
phase: payload.phase,
|
|
14870
|
+
tSec: payload.tSec,
|
|
14871
|
+
sample: payload.sample ? { ...payload.sample } : void 0,
|
|
14872
|
+
message: payload.message
|
|
14873
|
+
}
|
|
14874
|
+
)
|
|
14875
|
+
);
|
|
14870
14876
|
}
|
|
14871
14877
|
function slope(xs, ys) {
|
|
14872
14878
|
if (xs.length < 2) return 0;
|
|
@@ -14921,7 +14927,9 @@ async function destroySessions(api, handles, logger) {
|
|
|
14921
14927
|
try {
|
|
14922
14928
|
await api.decoder.destroySession.query({ sessionId: h.sessionId, nodeId: h.nodeId });
|
|
14923
14929
|
} catch (err) {
|
|
14924
|
-
logger.warn("destroySession failed", {
|
|
14930
|
+
logger.warn("destroySession failed", {
|
|
14931
|
+
meta: { sessionId: h.sessionId, error: err instanceof Error ? err.message : String(err) }
|
|
14932
|
+
});
|
|
14925
14933
|
}
|
|
14926
14934
|
}
|
|
14927
14935
|
}
|
|
@@ -14961,7 +14969,12 @@ async function runDecoderPerfTest(input, deps) {
|
|
|
14961
14969
|
const sessionId = input.sessionId;
|
|
14962
14970
|
const samples = [];
|
|
14963
14971
|
const startWall = import_node_perf_hooks.performance.now();
|
|
14964
|
-
emitProgress(eventBus, {
|
|
14972
|
+
emitProgress(eventBus, {
|
|
14973
|
+
kind: "decoder-perf",
|
|
14974
|
+
sessionId,
|
|
14975
|
+
phase: "init",
|
|
14976
|
+
message: "initialising"
|
|
14977
|
+
});
|
|
14965
14978
|
if (input.source.kind !== "sample") {
|
|
14966
14979
|
const msg = "decoder perf: stream source not yet implemented \u2014 use a sample fixture";
|
|
14967
14980
|
emitProgress(eventBus, { kind: "decoder-perf", sessionId, phase: "error", message: msg });
|
|
@@ -14992,9 +15005,13 @@ async function runDecoderPerfTest(input, deps) {
|
|
|
14992
15005
|
const instances = await api.metricsProvider.listAddonInstances.query();
|
|
14993
15006
|
const workerInstances = instances.filter((i) => i.role === "worker");
|
|
14994
15007
|
if (workerInstances.length === 0) {
|
|
14995
|
-
logger.info(
|
|
15008
|
+
logger.info(
|
|
15009
|
+
"decoder perf: no isolated worker detected \u2014 hub-local measurement (process.memoryUsage) mixes decoder + hub workload"
|
|
15010
|
+
);
|
|
14996
15011
|
} else {
|
|
14997
|
-
logger.info("decoder perf: worker instances visible", {
|
|
15012
|
+
logger.info("decoder perf: worker instances visible", {
|
|
15013
|
+
meta: { workers: workerInstances.map((w) => w.addonId) }
|
|
15014
|
+
});
|
|
14998
15015
|
}
|
|
14999
15016
|
} catch {
|
|
15000
15017
|
}
|
|
@@ -15003,7 +15020,12 @@ async function runDecoderPerfTest(input, deps) {
|
|
|
15003
15020
|
handles = await createSessions(api, input, codec2);
|
|
15004
15021
|
} catch (err) {
|
|
15005
15022
|
const msg = err instanceof Error ? err.message : String(err);
|
|
15006
|
-
emitProgress(eventBus, {
|
|
15023
|
+
emitProgress(eventBus, {
|
|
15024
|
+
kind: "decoder-perf",
|
|
15025
|
+
sessionId,
|
|
15026
|
+
phase: "error",
|
|
15027
|
+
message: `createSession failed: ${msg}`
|
|
15028
|
+
});
|
|
15007
15029
|
return {
|
|
15008
15030
|
sessionId,
|
|
15009
15031
|
verdict: "error",
|
|
@@ -15025,7 +15047,13 @@ async function runDecoderPerfTest(input, deps) {
|
|
|
15025
15047
|
let nextFeedAt = feedTickerStart;
|
|
15026
15048
|
let nextSampleAt = feedTickerStart + warmupMs;
|
|
15027
15049
|
let aborted2 = false;
|
|
15028
|
-
emitProgress(eventBus, {
|
|
15050
|
+
emitProgress(eventBus, {
|
|
15051
|
+
kind: "decoder-perf",
|
|
15052
|
+
sessionId,
|
|
15053
|
+
phase: "warmup",
|
|
15054
|
+
tSec: 0,
|
|
15055
|
+
message: `warming up ${input.warmupSec}s`
|
|
15056
|
+
});
|
|
15029
15057
|
const loopUntil = feedTickerStart + warmupMs + durationMs;
|
|
15030
15058
|
while (import_node_perf_hooks.performance.now() < loopUntil) {
|
|
15031
15059
|
if (abortFlag.aborted) {
|
|
@@ -15040,7 +15068,12 @@ async function runDecoderPerfTest(input, deps) {
|
|
|
15040
15068
|
try {
|
|
15041
15069
|
await pushChunk(api, h, fixture);
|
|
15042
15070
|
} catch (err) {
|
|
15043
|
-
logger.warn("pushPacket failed", {
|
|
15071
|
+
logger.warn("pushPacket failed", {
|
|
15072
|
+
meta: {
|
|
15073
|
+
sessionId: h.sessionId,
|
|
15074
|
+
error: err instanceof Error ? err.message : String(err)
|
|
15075
|
+
}
|
|
15076
|
+
});
|
|
15044
15077
|
}
|
|
15045
15078
|
}
|
|
15046
15079
|
nextFeedAt += frameIntervalMs;
|
|
@@ -15101,7 +15134,11 @@ async function runDecoderPerfTest(input, deps) {
|
|
|
15101
15134
|
verdict,
|
|
15102
15135
|
aborted: aborted2,
|
|
15103
15136
|
samples,
|
|
15104
|
-
slopes: {
|
|
15137
|
+
slopes: {
|
|
15138
|
+
rssMBMin: rssSlopeMBMin,
|
|
15139
|
+
heapMBMin: heapSlopeMBMin,
|
|
15140
|
+
externalMBMin: externalSlopeMBMin
|
|
15141
|
+
},
|
|
15105
15142
|
totals: { wallSec, framesEmitted, fpsPerCamera, cpuAvgPct, droppedFrames },
|
|
15106
15143
|
config: input
|
|
15107
15144
|
};
|
|
@@ -15112,9 +15149,21 @@ var KEY_BENCHMARK_HISTORY = "benchmarkHistory";
|
|
|
15112
15149
|
var MAX_HISTORY_ENTRIES = 100;
|
|
15113
15150
|
var HistoryArraySchema = external_exports.array(HistoryEntrySchema);
|
|
15114
15151
|
var FIXTURE_META = {
|
|
15115
|
-
"camera-sim-360p.h264": {
|
|
15116
|
-
|
|
15117
|
-
|
|
15152
|
+
"camera-sim-360p.h264": {
|
|
15153
|
+
codec: "h264",
|
|
15154
|
+
resolutionLabel: "360p",
|
|
15155
|
+
description: "Synthetic 360p H.264 \u2014 light workload"
|
|
15156
|
+
},
|
|
15157
|
+
"camera-sim-1080p.h264": {
|
|
15158
|
+
codec: "h264",
|
|
15159
|
+
resolutionLabel: "1080p",
|
|
15160
|
+
description: "Synthetic 1080p H.264 \u2014 production-like"
|
|
15161
|
+
},
|
|
15162
|
+
"camera-sim-1440p-h265.hevc": {
|
|
15163
|
+
codec: "h265",
|
|
15164
|
+
resolutionLabel: "1440p",
|
|
15165
|
+
description: "Synthetic 1440p H.265 \u2014 hardware decode stress"
|
|
15166
|
+
}
|
|
15118
15167
|
};
|
|
15119
15168
|
function resolveFixturesDir() {
|
|
15120
15169
|
const here = (0, import_node_url.fileURLToPath)(importMetaUrl);
|
|
@@ -15236,7 +15285,8 @@ var BenchmarkAddon = class extends import_types4.BaseAddon {
|
|
|
15236
15285
|
}
|
|
15237
15286
|
});
|
|
15238
15287
|
const cached2 = frameId ? this.frameCache.get(frameId) : void 0;
|
|
15239
|
-
if (frameId && !cached2)
|
|
15288
|
+
if (frameId && !cached2)
|
|
15289
|
+
throw new Error(`runPipelineTest: frameId ${frameId} not in cache (expired or never cached)`);
|
|
15240
15290
|
const cachedImage = cached2 ? new Uint8Array(cached2.jpeg) : void 0;
|
|
15241
15291
|
const image = cachedImage ?? (imageBase64 ? new Uint8Array(Buffer.from(imageBase64, "base64")) : void 0);
|
|
15242
15292
|
const stepsToRun = steps.length > 0 ? [...steps] : await (async () => {
|
|
@@ -15414,23 +15464,26 @@ var BenchmarkAddon = class extends import_types4.BaseAddon {
|
|
|
15414
15464
|
}
|
|
15415
15465
|
};
|
|
15416
15466
|
const start = Date.now();
|
|
15417
|
-
const cameraTasks = Array.from(
|
|
15418
|
-
|
|
15419
|
-
|
|
15420
|
-
|
|
15421
|
-
|
|
15422
|
-
|
|
15423
|
-
|
|
15424
|
-
|
|
15425
|
-
|
|
15426
|
-
|
|
15427
|
-
|
|
15428
|
-
|
|
15429
|
-
|
|
15430
|
-
|
|
15467
|
+
const cameraTasks = Array.from(
|
|
15468
|
+
{ length: simulatedCameras },
|
|
15469
|
+
(_, camIdx) => (async () => {
|
|
15470
|
+
for (let i = 0; i < batchesPerCamera; i++) {
|
|
15471
|
+
const dispatches = [
|
|
15472
|
+
dispatchOne(batchedFrames, true, `c${camIdx}-r${i}-b`)
|
|
15473
|
+
];
|
|
15474
|
+
for (let j = 0; j < extraSinglesPerRound; j++) {
|
|
15475
|
+
dispatches.push(dispatchOne(singleFrames, false, `c${camIdx}-r${i}-s${j}`));
|
|
15476
|
+
}
|
|
15477
|
+
await Promise.all(dispatches);
|
|
15478
|
+
countedDetections += batchSize;
|
|
15479
|
+
totalCalls += 1 + extraSinglesPerRound;
|
|
15480
|
+
totalFrames += batchSize + extraSinglesPerRound;
|
|
15481
|
+
}
|
|
15482
|
+
})()
|
|
15483
|
+
);
|
|
15431
15484
|
await Promise.all(cameraTasks);
|
|
15432
15485
|
const totalMs = Date.now() - start;
|
|
15433
|
-
const sortedCall = [...callMsList].
|
|
15486
|
+
const sortedCall = [...callMsList].toSorted((a, b) => a - b);
|
|
15434
15487
|
const pct = (xs, p) => {
|
|
15435
15488
|
if (xs.length === 0) return 0;
|
|
15436
15489
|
const idx = Math.min(xs.length - 1, Math.floor(xs.length * p));
|