@fraczak/k 7.0.1 → 7.1.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/CHANGELOG.md +78 -0
- package/DOCS/BIG_PICTURE.md +5 -5
- package/DOCS/FILE_FORMATS.md +241 -18
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +9 -9
- package/DOCS/PATTERNS.md +3 -3
- package/DOCS/POLYMORPHIC_IR.md +104 -0
- package/DOCS/PROFILING_AND_TRACING.md +60 -72
- package/DOCS/REPL.md +3 -3
- package/DOCS/book/03-types-as-finite-automata.md +4 -4
- package/DOCS/book/06-values-in-memory.md +9 -9
- package/DOCS/book/08-operational-semantics-and-execution.md +1 -1
- package/DOCS/book/09-compiler-architecture.md +2 -2
- package/DOCS/book/10-from-ast-to-intermediate-representation.md +2 -2
- package/DOCS/book/14-canonical-serialization.md +1 -1
- package/Examples/arithmetics.k +2 -2
- package/Examples/bnat.k +1 -1
- package/Examples/karatsuba-mult.k +2 -2
- package/JOURNAL.md +288 -0
- package/README.md +13 -10
- package/access-table.mjs +343 -0
- package/backend-api.mjs +18 -0
- package/backends/llvm/README.md +20 -21
- package/backends/llvm/bin/k-llvm-build.mjs +105 -32
- package/backends/llvm/bin/k-llvm-compile.mjs +63 -24
- package/backends/llvm/bin/k-llvm.mjs +292 -0
- package/backends/llvm/runtime/krt.c +41 -0
- package/backends/llvm/runtime/krt.h +2 -0
- package/backends/llvm/src/cli.mjs +95 -17
- package/backends/llvm/src/executable.mjs +132 -15
- package/backends/llvm/src/kvm2llvm.mjs +50 -23
- package/backends/llvm/src/llvm.mjs +133 -20
- package/backends/llvm/tests/integration.sh +11 -11
- package/backends/llvm/{bin → tests}/k-llvm-run.mjs +48 -22
- package/backends/llvm/tests/perf-support.mjs +25 -58
- package/backends/llvm/tests/test-llvm.mjs +25 -4
- package/backends/wasm/bin/k-wasm-compile.mjs +46 -20
- package/backends/wasm/bin/k-wasm-run.mjs +61 -20
- package/backends/wasm/bin/k-wasm.mjs +47 -13
- package/backends/wasm/src/cli.mjs +141 -19
- package/backends/wasm/src/wasm.mjs +132 -24
- package/backends/wasm/tests/test-wasm.mjs +5 -5
- package/browser/repl-browser.mjs +16 -5
- package/browser/vfs-data.mjs +5 -5
- package/codecs/k-parse.mjs +29 -8
- package/codecs/k-print.mjs +22 -6
- package/codecs/runtime/codec-sdk.mjs +8 -4
- package/codecs/show.mjs +20 -6
- package/core.k +8 -8
- package/harness/format.mjs +2 -2
- package/harness/registry.mjs +0 -2
- package/k.mjs +56 -16
- package/kir.mjs +200 -75
- package/kvm.mjs +49 -12
- package/objects/compile.mjs +37 -23
- package/objects/decompile.mjs +40 -10
- package/objects/extract-aliases.mjs +44 -14
- package/objects/inspect.mjs +19 -14
- package/objects/validate.mjs +18 -11
- package/package.json +10 -7
- package/pkir.mjs +772 -0
- package/repl.mjs +36 -18
- package/scripts/benchmark-idempotency.mjs +12 -8
- package/scripts/benchmark.mjs +5 -9
- package/scripts/build-repl-html.mjs +16 -4
- package/scripts/perf-ieee.mjs +253 -103
- package/scripts/perf-int.mjs +585 -297
- package/scripts/perf-multiplication.mjs +66 -25
- package/scripts/perf-poly.mjs +292 -164
- package/scripts/run-tests.mjs +3 -0
- package/tests/code-derivation/pattern-envelope.mjs +4 -4
- package/tests/test-access-table.mjs +213 -0
- package/tests/test-kvm-polymorphic.mjs +2 -2
- package/tests/test-pkir.mjs +530 -0
- package/tests/test-polymorphic-tdd.mjs +196 -0
- package/tests/test-repl-html.mjs +15 -2
- package/tests/test-repl.mjs +30 -1
- package/backends/arm64/README.md +0 -103
- package/backends/arm64/bin/k-arm64-compile.mjs +0 -93
- package/backends/arm64/bin/k-arm64-run.mjs +0 -58
- package/backends/arm64/bin/k-arm64.mjs +0 -88
- package/backends/arm64/scripts/run-tests.mjs +0 -57
- package/backends/arm64/src/arm64.mjs +0 -229
- package/backends/arm64/src/cli.mjs +0 -155
- package/backends/arm64/src/kvm2arm64.mjs +0 -906
- package/backends/arm64/src/runtime.c +0 -744
- package/backends/arm64/tests/integration.sh +0 -112
- package/backends/arm64/tests/test-arm64.mjs +0 -240
- package/backends/llvm/bin/k-llvm-jit.mjs +0 -160
- package/harness/adapters/arm64.mjs +0 -105
package/scripts/perf-poly.mjs
CHANGED
|
@@ -24,8 +24,6 @@ import {
|
|
|
24
24
|
csvEnv,
|
|
25
25
|
formatTiming,
|
|
26
26
|
createLLVMRunner,
|
|
27
|
-
createARM64Runner,
|
|
28
|
-
arm64LaneName,
|
|
29
27
|
llvmLaneName,
|
|
30
28
|
makeCacheDir,
|
|
31
29
|
parseNonNegativeIntEnv,
|
|
@@ -56,7 +54,6 @@ import {
|
|
|
56
54
|
writeValueToArena
|
|
57
55
|
} from "../backends/wasm/tests/perf-support.mjs";
|
|
58
56
|
|
|
59
|
-
import { compileARM64ArtifactFromObject } from "../backends/arm64/src/arm64.mjs";
|
|
60
57
|
import { compileWasmArtifactFromObject } from "../backends/wasm/src/wasm.mjs";
|
|
61
58
|
import { inputPatternForObjectRelation } from "../backends/llvm/src/executable.mjs";
|
|
62
59
|
|
|
@@ -65,7 +62,7 @@ function printHelp() {
|
|
|
65
62
|
|
|
66
63
|
Polymorphic List Operations Benchmark Harness.
|
|
67
64
|
Benchmarks reverse, concat, split_by, get_nth, and length on
|
|
68
|
-
Examples/poly.k across Native JS, kVM interpreter, LLVM, Wasm, and
|
|
65
|
+
Examples/poly.k across Native JS, kVM interpreter, LLVM, Wasm, and PKIR.
|
|
69
66
|
|
|
70
67
|
Options:
|
|
71
68
|
--trace
|
|
@@ -74,18 +71,20 @@ Options:
|
|
|
74
71
|
Enable per-function call count profiling.
|
|
75
72
|
--wasm-in-process
|
|
76
73
|
Run WebAssembly in-process instead of persistent subprocess runner.
|
|
74
|
+
--pkir-only
|
|
75
|
+
Run only PKIR backend.
|
|
77
76
|
-h, --help
|
|
78
77
|
Show this help message and exit.
|
|
79
78
|
|
|
80
79
|
Environment Variables:
|
|
81
80
|
BACKENDS
|
|
82
|
-
Target backend to run: 'llvm', 'wasm', or '
|
|
81
|
+
Target backend to run: 'llvm', 'wasm', or 'pkir'.
|
|
83
82
|
LLVM_ONLY
|
|
84
83
|
Run only LLVM backend ('1' to enable).
|
|
85
84
|
WASM_ONLY
|
|
86
85
|
Run only WebAssembly backend ('1' to enable).
|
|
87
|
-
|
|
88
|
-
Run only
|
|
86
|
+
PKIR_ONLY
|
|
87
|
+
Run only PKIR backend ('1' to enable).
|
|
89
88
|
BACKENDS_ONLY
|
|
90
89
|
Skip JS and kVM interpreter baselines ('1' to enable).
|
|
91
90
|
LIST_LENGTH
|
|
@@ -96,14 +95,6 @@ Environment Variables:
|
|
|
96
95
|
Enable nanosecond execution tracing ('1' to enable).
|
|
97
96
|
PROFILE, K_PROFILE
|
|
98
97
|
Enable per-function call count profiling ('1' to enable).
|
|
99
|
-
ARM64_WARMUP_ITERATIONS
|
|
100
|
-
Warmup iterations for ARM64 backend (default: 1).
|
|
101
|
-
ARM64_OPT
|
|
102
|
-
ARM64 backend optimization flags (default: -O2).
|
|
103
|
-
ARM64_SPAWN_PER_CALL
|
|
104
|
-
Spawn process per ARM64 call instead of persistent ('1' or '0').
|
|
105
|
-
ARM64_PIPELINE
|
|
106
|
-
Use persistent pipelined runner for ARM64 ('1' or '0').
|
|
107
98
|
LLVM_WARMUP_ITERATIONS
|
|
108
99
|
Warmup iterations for LLVM backend (default: 1).
|
|
109
100
|
LLVM_SPAWN_PER_CALL
|
|
@@ -129,15 +120,52 @@ if (process.argv.includes("-h") || process.argv.includes("--help")) {
|
|
|
129
120
|
|
|
130
121
|
// Backend selection
|
|
131
122
|
const backendsEnv = process.env.BACKENDS?.toLowerCase();
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
123
|
+
const backendsList = backendsEnv
|
|
124
|
+
? backendsEnv.split(",").map(s => s.trim())
|
|
125
|
+
: null;
|
|
126
|
+
const llvmPkirOnly = process.env.LLVM_PKIR_ONLY === "1"
|
|
127
|
+
|| (backendsList && backendsList.length === 1 &&
|
|
128
|
+
backendsList[0] === "llvm-pkir")
|
|
129
|
+
|| process.argv.includes("--llvm-pkir-only");
|
|
130
|
+
const pkirOnly = !llvmPkirOnly && (
|
|
131
|
+
process.env.PKIR_ONLY === "1"
|
|
132
|
+
|| (backendsList && backendsList.length === 1 &&
|
|
133
|
+
backendsList[0] === "pkir")
|
|
134
|
+
|| process.argv.includes("--pkir-only")
|
|
135
|
+
);
|
|
136
|
+
const llvmOnly = !pkirOnly && !llvmPkirOnly && (
|
|
137
|
+
process.env.LLVM_ONLY === "1"
|
|
138
|
+
|| (backendsList && backendsList.length === 1 &&
|
|
139
|
+
backendsList[0] === "llvm")
|
|
140
|
+
);
|
|
141
|
+
const wasmOnly = !pkirOnly && !llvmPkirOnly && !llvmOnly && (
|
|
142
|
+
process.env.WASM_ONLY === "1"
|
|
143
|
+
|| (backendsList && backendsList.length === 1 &&
|
|
144
|
+
backendsList[0] === "wasm")
|
|
145
|
+
);
|
|
146
|
+
const runLLVM = backendsList
|
|
147
|
+
? backendsList.includes("llvm")
|
|
148
|
+
: !wasmOnly && !pkirOnly && !llvmPkirOnly;
|
|
149
|
+
const runLLVMPKIR = backendsList
|
|
150
|
+
? backendsList.includes("llvm-pkir")
|
|
151
|
+
: !wasmOnly && !pkirOnly && !llvmOnly;
|
|
152
|
+
const runWasm = backendsList
|
|
153
|
+
? backendsList.includes("wasm")
|
|
154
|
+
: !llvmOnly && !pkirOnly && !llvmPkirOnly;
|
|
155
|
+
const runPKIR = backendsList
|
|
156
|
+
? backendsList.includes("pkir")
|
|
157
|
+
: !llvmOnly && !wasmOnly && !llvmPkirOnly;
|
|
158
|
+
const runBaselines = !process.env.BACKENDS_ONLY
|
|
159
|
+
&& (backendsList == null || backendsList.includes("kvm") ||
|
|
160
|
+
backendsList.includes("js"))
|
|
161
|
+
&& !llvmOnly && !wasmOnly && !pkirOnly && !llvmPkirOnly;
|
|
162
|
+
|
|
163
|
+
function llvmLaneNameStr() {
|
|
164
|
+
return llvmLaneName();
|
|
165
|
+
}
|
|
166
|
+
function llvmPkirLaneNameStr() {
|
|
167
|
+
return llvmLaneName().replace("LLVM", "LLVM-PKIR");
|
|
168
|
+
}
|
|
141
169
|
|
|
142
170
|
const ops = ["reverse", "concat", "split_by", "get_nth", "length"];
|
|
143
171
|
const benchNames = Object.fromEntries(ops.map(op => [op, `bench_${op}`]));
|
|
@@ -146,10 +174,6 @@ const iterations = parsePositiveIntEnv("ITERATIONS", 3);
|
|
|
146
174
|
const runTrace = process.argv.includes("--trace") || process.env.TRACE === "1" || process.env.K_TRACE === "1";
|
|
147
175
|
const runProfile = runTrace || process.argv.includes("--profile") || process.env.K_PROFILE === "1" || process.env.PROFILE === "1";
|
|
148
176
|
|
|
149
|
-
// ARM64 options
|
|
150
|
-
const arm64WarmupIterations = parseNonNegativeIntEnv("ARM64_WARMUP_ITERATIONS", 1);
|
|
151
|
-
const arm64OptLevel = process.env.ARM64_OPT || "-O2";
|
|
152
|
-
|
|
153
177
|
// LLVM options
|
|
154
178
|
const llvmWarmupIterations = parseNonNegativeIntEnv("LLVM_WARMUP_ITERATIONS", 1);
|
|
155
179
|
const cacheDir = makeCacheDir("k-poly-perf-");
|
|
@@ -164,6 +188,9 @@ function wasmLaneName() {
|
|
|
164
188
|
const mode = wasmPipe ? "persistent" : "in-process";
|
|
165
189
|
return `WebAssembly (${mode})`;
|
|
166
190
|
}
|
|
191
|
+
function pkirLaneName() {
|
|
192
|
+
return "PKIR (Wasm persistent)";
|
|
193
|
+
}
|
|
167
194
|
|
|
168
195
|
|
|
169
196
|
console.log("==> Loading @fraczak/k/Examples/arithmetics.k as library");
|
|
@@ -193,7 +220,7 @@ function buildExportPreamble(exports, libraries) {
|
|
|
193
220
|
return lines.join("\n") + "\n";
|
|
194
221
|
}
|
|
195
222
|
|
|
196
|
-
const neededExports = ["0", "int", "inc", "dec", "nat", "zero_int?"];
|
|
223
|
+
const neededExports = ["0", "int", "inc", "dec", "nat", "zero_int?", "neg?", "GT"];
|
|
197
224
|
const exportPreamble = buildExportPreamble(neededExports, [arithmeticsLib]);
|
|
198
225
|
const polyLib = loadLibrary(compileLibrary(exportPreamble + polySource, {
|
|
199
226
|
source: polyPath,
|
|
@@ -219,7 +246,7 @@ for (const op of ops) {
|
|
|
219
246
|
}
|
|
220
247
|
|
|
221
248
|
function intValue(text) {
|
|
222
|
-
return
|
|
249
|
+
return parseIntValue(text);
|
|
223
250
|
}
|
|
224
251
|
|
|
225
252
|
function makeList(elements) {
|
|
@@ -315,13 +342,37 @@ if (runLLVM) {
|
|
|
315
342
|
relHash: relation.relHash,
|
|
316
343
|
inputPattern: tc.inputPattern,
|
|
317
344
|
cacheDir,
|
|
318
|
-
sourceLabel:
|
|
345
|
+
sourceLabel:
|
|
346
|
+
`@fraczak/k/Examples/poly.k#${relation.relationName}`,
|
|
347
|
+
usePKIR: false
|
|
319
348
|
});
|
|
320
349
|
}
|
|
321
350
|
codes.load(state.codes);
|
|
322
351
|
printCompileFailures(testSuite);
|
|
323
352
|
}
|
|
324
353
|
|
|
354
|
+
// Setup LLVM-PKIR
|
|
355
|
+
if (runLLVMPKIR) {
|
|
356
|
+
console.log("==> Compiling LLVM-PKIR executables");
|
|
357
|
+
for (const tc of testSuite) {
|
|
358
|
+
const relation = relations[tc.op];
|
|
359
|
+
tc.llvmPKIR = tryCompileCase({
|
|
360
|
+
object: relation.object,
|
|
361
|
+
relationName: relation.relationName,
|
|
362
|
+
relHash: relation.relHash,
|
|
363
|
+
inputPattern: tc.inputPattern,
|
|
364
|
+
cacheDir,
|
|
365
|
+
sourceLabel:
|
|
366
|
+
`@fraczak/k/Examples/poly.k#${relation.relationName}`,
|
|
367
|
+
usePKIR: true
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
codes.load(state.codes);
|
|
371
|
+
printCompileFailures(
|
|
372
|
+
testSuite.map(tc => ({ ...tc, llvm: tc.llvmPKIR }))
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
|
|
325
376
|
// Setup Wasm
|
|
326
377
|
let wasmExports = null;
|
|
327
378
|
let wasmProfileFunctions = [];
|
|
@@ -364,6 +415,34 @@ if (runWasm) {
|
|
|
364
415
|
}
|
|
365
416
|
}
|
|
366
417
|
|
|
418
|
+
// Setup PKIR (persistent runner)
|
|
419
|
+
const pkirExes = new Map();
|
|
420
|
+
if (runPKIR) {
|
|
421
|
+
console.log("==> Compiling PKIR executables (persistent runner)...");
|
|
422
|
+
for (const tc of testSuite) {
|
|
423
|
+
const relation = relations[tc.op];
|
|
424
|
+
try {
|
|
425
|
+
const wasmPath = path.join(cacheDir, `perf_poly_pkir_${tc.op}.wasm`);
|
|
426
|
+
const exePath = path.join(cacheDir, `perf_poly_pkir_${tc.op}.exe`);
|
|
427
|
+
const wasmBuf = await compileWasmArtifactFromObject(relation.object, {
|
|
428
|
+
entry: relation.relHash,
|
|
429
|
+
usePKIR: true
|
|
430
|
+
});
|
|
431
|
+
fs.writeFileSync(wasmPath, wasmBuf);
|
|
432
|
+
const runBin = fileURLToPath(import.meta.resolve("../backends/wasm/bin/k-wasm-run.mjs"));
|
|
433
|
+
fs.writeFileSync(exePath, `#!/bin/sh\nexec node "${runBin}" "${wasmPath}" "$@"\n`, { mode: 0o755 });
|
|
434
|
+
tc.pkir = { status: "ok", exePath, wasmPath };
|
|
435
|
+
pkirExes.set(tc.op, tc.pkir);
|
|
436
|
+
} catch (error) {
|
|
437
|
+
tc.pkir = {
|
|
438
|
+
status: "failed",
|
|
439
|
+
error: error.stack || error.message || String(error)
|
|
440
|
+
};
|
|
441
|
+
pkirExes.set(tc.op, tc.pkir);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
367
446
|
function createWasmRunner(testSuite) {
|
|
368
447
|
const wasmCases = testSuite.filter(tc => tc.wasm?.status === "ok");
|
|
369
448
|
const servers = new Map();
|
|
@@ -392,39 +471,32 @@ function createWasmRunner(testSuite) {
|
|
|
392
471
|
};
|
|
393
472
|
}
|
|
394
473
|
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
compileARM64ArtifactFromObject(relation.object, {
|
|
404
|
-
entry: relation.relationName,
|
|
405
|
-
inputPattern: tc.inputPattern,
|
|
406
|
-
outputPattern: tc.outputPattern,
|
|
407
|
-
outputPath: exePath,
|
|
408
|
-
optLevel: arm64OptLevel,
|
|
409
|
-
profile: runProfile
|
|
410
|
-
});
|
|
411
|
-
tc.arm64 = { status: "ok", exePath };
|
|
412
|
-
arm64Exes.set(tc.op, tc.arm64);
|
|
413
|
-
} catch (error) {
|
|
414
|
-
tc.arm64 = {
|
|
415
|
-
status: "failed",
|
|
416
|
-
error: error.stack || error.message || String(error)
|
|
417
|
-
};
|
|
418
|
-
arm64Exes.set(tc.op, tc.arm64);
|
|
474
|
+
function createPKIRRunner(testSuite) {
|
|
475
|
+
const pkirCases = testSuite.filter(tc => tc.pkir?.status === "ok");
|
|
476
|
+
const servers = new Map();
|
|
477
|
+
function serverFor(exePath) {
|
|
478
|
+
let server = servers.get(exePath);
|
|
479
|
+
if (server == null) {
|
|
480
|
+
server = new PersistentExecutable(exePath);
|
|
481
|
+
servers.set(exePath, server);
|
|
419
482
|
}
|
|
483
|
+
return server;
|
|
420
484
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
485
|
+
|
|
486
|
+
return {
|
|
487
|
+
async run(iterations) {
|
|
488
|
+
if (pkirCases.length === 0) return null;
|
|
489
|
+
return runTimedIterationsAsync(iterations, async () => {
|
|
490
|
+
for (const tc of pkirCases) {
|
|
491
|
+
await serverFor(tc.pkir.exePath).request(tc.inputWire);
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
},
|
|
495
|
+
serverFor,
|
|
496
|
+
close() {
|
|
497
|
+
for (const server of servers.values()) server.close();
|
|
426
498
|
}
|
|
427
|
-
}
|
|
499
|
+
};
|
|
428
500
|
}
|
|
429
501
|
|
|
430
502
|
function printBenchmarkDescription() {
|
|
@@ -434,9 +506,10 @@ function printBenchmarkDescription() {
|
|
|
434
506
|
lanes.push("Native JS (Envelope-Free)");
|
|
435
507
|
lanes.push("kVM Interpreter (Env-Free)");
|
|
436
508
|
}
|
|
437
|
-
if (runLLVM) lanes.push(
|
|
509
|
+
if (runLLVM) lanes.push(llvmLaneNameStr());
|
|
510
|
+
if (runLLVMPKIR) lanes.push(llvmPkirLaneNameStr());
|
|
438
511
|
if (runWasm) lanes.push(wasmLaneName());
|
|
439
|
-
if (
|
|
512
|
+
if (runPKIR) lanes.push(pkirLaneName());
|
|
440
513
|
|
|
441
514
|
console.log("==> Benchmark description");
|
|
442
515
|
console.log(" source: @fraczak/k/Examples/poly.k");
|
|
@@ -448,16 +521,17 @@ function printBenchmarkDescription() {
|
|
|
448
521
|
console.log(` llvm-ready cases: ${testSuite.filter(tc => tc.llvm?.status === "ok").length}`);
|
|
449
522
|
console.log(` llvm warmup iterations: ${llvmWarmupIterations}`);
|
|
450
523
|
}
|
|
524
|
+
if (runLLVMPKIR) {
|
|
525
|
+
console.log(` llvm-pkir ready cases: ${testSuite.filter(tc => tc.llvmPKIR?.status === "ok").length}`);
|
|
526
|
+
console.log(` llvm-pkir warmup iterations: ${llvmWarmupIterations}`);
|
|
527
|
+
}
|
|
451
528
|
if (runWasm) {
|
|
452
529
|
console.log(` wasm runner mode: ${wasmPipe ? "persistent pipe" : "in-process"}`);
|
|
453
530
|
console.log(` wasm warmup iterations: ${wasmWarmupIterations}`);
|
|
454
531
|
if (!wasmPipe) console.log(` wasm arena reset: ${wasmReset ? "yes" : "no"}`);
|
|
455
532
|
}
|
|
456
|
-
if (
|
|
457
|
-
console.log(`
|
|
458
|
-
console.log(` arm64 warmup iterations: ${arm64WarmupIterations}`);
|
|
459
|
-
console.log(` arm64 opt level: ${arm64OptLevel}`);
|
|
460
|
-
console.log(` arm64 runner mode: ${process.env.ARM64_SPAWN_PER_CALL === "1" ? "spawn per call" : "persistent"}`);
|
|
533
|
+
if (runPKIR) {
|
|
534
|
+
console.log(` pkir warmup iterations: ${wasmWarmupIterations}`);
|
|
461
535
|
}
|
|
462
536
|
console.log(` iterations: ${iterations}`);
|
|
463
537
|
console.log(` benchmark lanes: ${lanes.join("; ")}`);
|
|
@@ -494,6 +568,23 @@ if (runLLVM) {
|
|
|
494
568
|
}
|
|
495
569
|
}
|
|
496
570
|
|
|
571
|
+
// 2b. LLVM-PKIR lane
|
|
572
|
+
let llvmPkirResult = null;
|
|
573
|
+
if (runLLVMPKIR) {
|
|
574
|
+
const llvmPkirCases = testSuite.map(tc => ({ ...tc, llvm: tc.llvmPKIR }));
|
|
575
|
+
const llvmPkirRunner = createLLVMRunner(llvmPkirCases);
|
|
576
|
+
try {
|
|
577
|
+
if (llvmWarmupIterations > 0) {
|
|
578
|
+
console.log(`==> Warming LLVM-PKIR executables (${llvmWarmupIterations} iterations)...`);
|
|
579
|
+
await llvmPkirRunner.run(llvmWarmupIterations);
|
|
580
|
+
}
|
|
581
|
+
console.log(`==> Running LLVM-PKIR (${iterations} iterations)...`);
|
|
582
|
+
llvmPkirResult = await llvmPkirRunner.run(iterations);
|
|
583
|
+
} finally {
|
|
584
|
+
llvmPkirRunner.close();
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
497
588
|
// 3. Wasm lane
|
|
498
589
|
let wasmResult = null;
|
|
499
590
|
if (runWasm) {
|
|
@@ -539,22 +630,21 @@ if (runWasm) {
|
|
|
539
630
|
}
|
|
540
631
|
}
|
|
541
632
|
|
|
542
|
-
// 4.
|
|
543
|
-
let
|
|
544
|
-
if (
|
|
545
|
-
const
|
|
546
|
-
if (
|
|
547
|
-
const
|
|
633
|
+
// 4. PKIR lane
|
|
634
|
+
let pkirResult = null;
|
|
635
|
+
if (runPKIR) {
|
|
636
|
+
const pkirCases = testSuite.filter(tc => tc.pkir?.status === "ok");
|
|
637
|
+
if (pkirCases.length === testSuite.length) {
|
|
638
|
+
const pkirRunner = createPKIRRunner(testSuite);
|
|
548
639
|
try {
|
|
549
|
-
if (
|
|
550
|
-
console.log(`==> Warming
|
|
551
|
-
await
|
|
640
|
+
if (wasmWarmupIterations > 0) {
|
|
641
|
+
console.log(`==> Warming PKIR (${wasmWarmupIterations} iterations)...`);
|
|
642
|
+
await pkirRunner.run(wasmWarmupIterations);
|
|
552
643
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
arm64Result = await arm64Runner.run(iterations);
|
|
644
|
+
console.log(`==> Running PKIR (${iterations} iterations)...`);
|
|
645
|
+
pkirResult = await pkirRunner.run(iterations);
|
|
556
646
|
} finally {
|
|
557
|
-
|
|
647
|
+
pkirRunner.close();
|
|
558
648
|
}
|
|
559
649
|
}
|
|
560
650
|
}
|
|
@@ -570,14 +660,18 @@ if (runBaselines) {
|
|
|
570
660
|
console.log(`${laneIndex++}. kVM Interpreter (Env-Free): ${formatTiming(kvmFreeResult)}`);
|
|
571
661
|
}
|
|
572
662
|
if (runLLVM) {
|
|
573
|
-
|
|
663
|
+
const name = llvmLaneNameStr().padEnd(29);
|
|
664
|
+
console.log(`${laneIndex++}. ${name} ${formatTiming(llvmResult)}`);
|
|
665
|
+
}
|
|
666
|
+
if (runLLVMPKIR) {
|
|
667
|
+
const name = llvmPkirLaneNameStr().padEnd(29);
|
|
668
|
+
console.log(`${laneIndex++}. ${name} ${formatTiming(llvmPkirResult)}`);
|
|
574
669
|
}
|
|
575
670
|
if (runWasm) {
|
|
576
671
|
console.log(`${laneIndex++}. ${wasmLaneName().padEnd(29)} ${formatTiming(wasmResult)}`);
|
|
577
672
|
}
|
|
578
|
-
if (
|
|
579
|
-
|
|
580
|
-
console.log(`${laneIndex++}. ${arm64LaneName(arm64OptLevel).padEnd(29)} ${timingStr}`);
|
|
673
|
+
if (runPKIR) {
|
|
674
|
+
console.log(`${laneIndex++}. ${pkirLaneName().padEnd(29)} ${formatTiming(pkirResult)}`);
|
|
581
675
|
}
|
|
582
676
|
console.log("=====================================================================\n");
|
|
583
677
|
|
|
@@ -605,6 +699,23 @@ for (const tc of testSuite) {
|
|
|
605
699
|
}
|
|
606
700
|
}
|
|
607
701
|
|
|
702
|
+
if (runLLVMPKIR) {
|
|
703
|
+
if (tc.llvmPKIR.status !== "ok") {
|
|
704
|
+
tc.llvmPkirConformance = "compile-failed";
|
|
705
|
+
} else {
|
|
706
|
+
try {
|
|
707
|
+
const outputWire = await runExecutable(tc.llvmPKIR.exePath, tc.inputWire);
|
|
708
|
+
const actual = decodeWire(outputWire).value;
|
|
709
|
+
assert.ok(safeDeepEqual(actual, tc.expected), `LLVM-PKIR output mismatch for ${tc.op}`);
|
|
710
|
+
tc.llvmPkirConformance = "ok";
|
|
711
|
+
} catch (error) {
|
|
712
|
+
tc.llvmPkirConformance = "failed";
|
|
713
|
+
tc.llvmPKIR.error = error.stack || error.message || String(error);
|
|
714
|
+
console.log(`LLVM-PKIR conformance failure for ${tc.op}:`, tc.llvmPKIR.error.split("\n")[0]);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
608
719
|
if (runWasm) {
|
|
609
720
|
if (wasmPipe) {
|
|
610
721
|
if (tc.wasm?.status !== "ok") {
|
|
@@ -644,22 +755,23 @@ for (const tc of testSuite) {
|
|
|
644
755
|
}
|
|
645
756
|
}
|
|
646
757
|
|
|
647
|
-
if (
|
|
648
|
-
if (tc.
|
|
649
|
-
tc.
|
|
758
|
+
if (runPKIR) {
|
|
759
|
+
if (tc.pkir?.status !== "ok") {
|
|
760
|
+
tc.pkirConformance = "compile-failed";
|
|
650
761
|
} else {
|
|
651
762
|
try {
|
|
652
|
-
const outputWire = await runExecutable(tc.
|
|
763
|
+
const outputWire = await runExecutable(tc.pkir.exePath, tc.inputWire);
|
|
653
764
|
const actual = decodeWire(outputWire).value;
|
|
654
|
-
assert.ok(safeDeepEqual(actual, tc.expected), `
|
|
655
|
-
tc.
|
|
765
|
+
assert.ok(safeDeepEqual(actual, tc.expected), `PKIR output mismatch for ${tc.op}`);
|
|
766
|
+
tc.pkirConformance = "ok";
|
|
656
767
|
} catch (error) {
|
|
657
|
-
tc.
|
|
658
|
-
tc.
|
|
659
|
-
console.log(`
|
|
768
|
+
tc.pkirConformance = "failed";
|
|
769
|
+
tc.pkir.error = error.stack || error.message || String(error);
|
|
770
|
+
console.log(`PKIR conformance failure for ${tc.op}:`, tc.pkir.error.split("\n")[0]);
|
|
660
771
|
}
|
|
661
772
|
}
|
|
662
773
|
}
|
|
774
|
+
|
|
663
775
|
}
|
|
664
776
|
|
|
665
777
|
const validationSummary = [];
|
|
@@ -668,19 +780,24 @@ if (runLLVM) {
|
|
|
668
780
|
const llvmOk = testSuite.filter(tc => tc.llvmConformance === "ok").length;
|
|
669
781
|
validationSummary.push(`LLVM ${llvmOk}/${testSuite.length}`);
|
|
670
782
|
}
|
|
783
|
+
if (runLLVMPKIR) {
|
|
784
|
+
const pkirOk = testSuite.filter(tc => tc.llvmPkirConformance === "ok").length;
|
|
785
|
+
validationSummary.push(`LLVM-PKIR ${pkirOk}/${testSuite.length}`);
|
|
786
|
+
}
|
|
671
787
|
if (runWasm) {
|
|
672
788
|
const wasmOk = testSuite.filter(tc => tc.wasmConformance === "ok").length;
|
|
673
789
|
validationSummary.push(`Wasm ${wasmOk}/${testSuite.length}`);
|
|
674
790
|
}
|
|
675
|
-
if (
|
|
676
|
-
const
|
|
677
|
-
validationSummary.push(`
|
|
791
|
+
if (runPKIR) {
|
|
792
|
+
const pkirOk = testSuite.filter(tc => tc.pkirConformance === "ok").length;
|
|
793
|
+
validationSummary.push(`PKIR ${pkirOk}/${testSuite.length}`);
|
|
678
794
|
}
|
|
679
795
|
|
|
680
796
|
console.log(`Conformance validation: ${validationSummary.join(", ")} cases match expected values.`);
|
|
681
797
|
if (runLLVM && shouldStrictFail(testSuite)) process.exitCode = 1;
|
|
798
|
+
if (runLLVMPKIR && shouldStrictFail(testSuite.map(tc => ({ ...tc, llvm: tc.llvmPKIR })))) process.exitCode = 1;
|
|
682
799
|
if (runWasm && testSuite.some(tc => tc.wasmConformance !== "ok")) process.exitCode = 1;
|
|
683
|
-
if (
|
|
800
|
+
if (runPKIR && testSuite.some(tc => tc.pkirConformance !== "ok")) process.exitCode = 1;
|
|
684
801
|
|
|
685
802
|
if (runTrace && process.exitCode !== 1) {
|
|
686
803
|
console.log("\n=================== RUNNING MACRO-PHASE TRACING ===================");
|
|
@@ -696,6 +813,18 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
696
813
|
}
|
|
697
814
|
}
|
|
698
815
|
|
|
816
|
+
const llvmPkirServers = new Map();
|
|
817
|
+
if (runLLVMPKIR) {
|
|
818
|
+
for (const tc of testSuite) {
|
|
819
|
+
if (tc.llvmPKIR?.status === "ok") {
|
|
820
|
+
llvmPkirServers.set(
|
|
821
|
+
tc.op,
|
|
822
|
+
new PersistentExecutable(tc.llvmPKIR.exePath)
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
699
828
|
const wasmServers = new Map();
|
|
700
829
|
if (runWasm && wasmPipe) {
|
|
701
830
|
for (const tc of testSuite) {
|
|
@@ -705,11 +834,11 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
705
834
|
}
|
|
706
835
|
}
|
|
707
836
|
|
|
708
|
-
const
|
|
709
|
-
if (
|
|
837
|
+
const pkirServers = new Map();
|
|
838
|
+
if (runPKIR) {
|
|
710
839
|
for (const tc of testSuite) {
|
|
711
|
-
if (tc.
|
|
712
|
-
|
|
840
|
+
if (tc.pkir?.status === "ok") {
|
|
841
|
+
pkirServers.set(tc.op, new PersistentExecutable(tc.pkir.exePath));
|
|
713
842
|
}
|
|
714
843
|
}
|
|
715
844
|
}
|
|
@@ -746,43 +875,28 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
746
875
|
const op = tc.op;
|
|
747
876
|
const opData = { op, label: tc.label };
|
|
748
877
|
|
|
749
|
-
//
|
|
750
|
-
if (
|
|
751
|
-
const server =
|
|
878
|
+
// 2. LLVM
|
|
879
|
+
if (llvmServers.has(op)) {
|
|
880
|
+
const server = llvmServers.get(op);
|
|
752
881
|
for (let i = 0; i < 3; i++) await server.requestWithTrace(tc.inputWire);
|
|
753
882
|
const samples = [];
|
|
754
|
-
let arm64Profile = null;
|
|
755
883
|
for (let i = 0; i < sampleReps; i++) {
|
|
756
884
|
const res = await server.requestWithTrace(tc.inputWire);
|
|
757
|
-
if (res.trace)
|
|
758
|
-
samples.push(res.trace);
|
|
759
|
-
if (res.trace.profile) arm64Profile = res.trace.profile;
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
opData.arm64 = averageTrace(samples);
|
|
763
|
-
if (arm64Profile) {
|
|
764
|
-
if (arm64Profile.__main__ !== undefined) {
|
|
765
|
-
if (arm64Profile[op] !== undefined) {
|
|
766
|
-
arm64Profile[benchNames[op]] = arm64Profile.__main__;
|
|
767
|
-
} else {
|
|
768
|
-
arm64Profile[op] = arm64Profile.__main__;
|
|
769
|
-
}
|
|
770
|
-
delete arm64Profile.__main__;
|
|
771
|
-
}
|
|
772
|
-
opData.arm64Profile = arm64Profile;
|
|
885
|
+
if (res.trace) samples.push(res.trace);
|
|
773
886
|
}
|
|
887
|
+
opData.llvm = averageTrace(samples);
|
|
774
888
|
}
|
|
775
889
|
|
|
776
|
-
//
|
|
777
|
-
if (
|
|
778
|
-
const server =
|
|
890
|
+
// 2b. LLVM-PKIR
|
|
891
|
+
if (llvmPkirServers.has(op)) {
|
|
892
|
+
const server = llvmPkirServers.get(op);
|
|
779
893
|
for (let i = 0; i < 3; i++) await server.requestWithTrace(tc.inputWire);
|
|
780
894
|
const samples = [];
|
|
781
895
|
for (let i = 0; i < sampleReps; i++) {
|
|
782
896
|
const res = await server.requestWithTrace(tc.inputWire);
|
|
783
897
|
if (res.trace) samples.push(res.trace);
|
|
784
898
|
}
|
|
785
|
-
opData.
|
|
899
|
+
opData.llvmPkir = averageTrace(samples);
|
|
786
900
|
}
|
|
787
901
|
|
|
788
902
|
// 3. Wasm
|
|
@@ -845,6 +959,18 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
845
959
|
}
|
|
846
960
|
}
|
|
847
961
|
|
|
962
|
+
// PKIR
|
|
963
|
+
if (runPKIR && pkirServers.has(op)) {
|
|
964
|
+
const server = pkirServers.get(op);
|
|
965
|
+
for (let i = 0; i < 3; i++) await server.requestWithTrace(tc.inputWire);
|
|
966
|
+
const samples = [];
|
|
967
|
+
for (let i = 0; i < sampleReps; i++) {
|
|
968
|
+
const res = await server.requestWithTrace(tc.inputWire);
|
|
969
|
+
if (res.trace) samples.push(res.trace);
|
|
970
|
+
}
|
|
971
|
+
opData.pkir = averageTrace(samples);
|
|
972
|
+
}
|
|
973
|
+
|
|
848
974
|
// 4. kVM
|
|
849
975
|
if (runBaselines) {
|
|
850
976
|
const relDef = relations[op].relDef;
|
|
@@ -891,8 +1017,9 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
891
1017
|
}
|
|
892
1018
|
|
|
893
1019
|
for (const s of llvmServers.values()) s.close();
|
|
894
|
-
for (const s of
|
|
1020
|
+
for (const s of llvmPkirServers.values()) s.close();
|
|
895
1021
|
for (const s of wasmServers.values()) s.close();
|
|
1022
|
+
for (const s of pkirServers.values()) s.close();
|
|
896
1023
|
|
|
897
1024
|
function formatUs(ns) {
|
|
898
1025
|
if (ns == null || ns === 0) return " - ";
|
|
@@ -911,26 +1038,36 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
911
1038
|
{ name: "Total Request Time", key: "totalNs", isTotal: true }
|
|
912
1039
|
];
|
|
913
1040
|
|
|
1041
|
+
const activeTraceLanes = [];
|
|
1042
|
+
if (runLLVM) {
|
|
1043
|
+
activeTraceLanes.push({ id: "llvm", label: "LLVM" });
|
|
1044
|
+
}
|
|
1045
|
+
if (runLLVMPKIR) {
|
|
1046
|
+
activeTraceLanes.push({ id: "llvmPkir", label: "LLVM-PKIR" });
|
|
1047
|
+
}
|
|
1048
|
+
if (runWasm) activeTraceLanes.push({ id: "wasm", label: "WebAssembly" });
|
|
1049
|
+
if (runPKIR) activeTraceLanes.push({ id: "pkir", label: "PKIR (Wasm)" });
|
|
1050
|
+
if (runBaselines) activeTraceLanes.push({ id: "kvm", label: "kVM Interp" });
|
|
1051
|
+
|
|
1052
|
+
const traceHeader = ["Phase ", ...activeTraceLanes.map(l => l.label.padEnd(13))].join(" | ");
|
|
1053
|
+
const traceDivider = ["------------------------", ...activeTraceLanes.map(() => "-------------")].join("-+-");
|
|
1054
|
+
|
|
914
1055
|
for (const item of phaseResults) {
|
|
915
1056
|
console.log(`\n--- Operation: ${item.op} (${item.label}) ---`);
|
|
916
|
-
console.log(
|
|
917
|
-
console.log(
|
|
1057
|
+
console.log(traceHeader);
|
|
1058
|
+
console.log(traceDivider);
|
|
918
1059
|
for (const phase of phases) {
|
|
919
1060
|
if (phase.isTotal) {
|
|
920
|
-
console.log(
|
|
1061
|
+
console.log(traceDivider);
|
|
921
1062
|
}
|
|
922
1063
|
const pName = phase.name.padEnd(24);
|
|
923
|
-
const
|
|
924
|
-
|
|
925
|
-
const wasmCol = formatUs(item.wasm?.[phase.key]);
|
|
926
|
-
const kvmCol = formatUs(item.kvm?.[phase.key]);
|
|
927
|
-
console.log(`${pName} | ${arm64Col} | ${llvmCol} | ${wasmCol} | ${kvmCol}`);
|
|
1064
|
+
const cols = [pName, ...activeTraceLanes.map(l => formatUs(item[l.id]?.[phase.key]))];
|
|
1065
|
+
console.log(cols.join(" | "));
|
|
928
1066
|
}
|
|
929
1067
|
|
|
930
|
-
const hasProfile = item.
|
|
1068
|
+
const hasProfile = item.wasmProfile || item.kvmProfile;
|
|
931
1069
|
if (hasProfile) {
|
|
932
1070
|
const allFuncs = new Set([
|
|
933
|
-
...Object.keys(item.arm64Profile || {}),
|
|
934
1071
|
...Object.keys(item.wasmProfile || {}),
|
|
935
1072
|
...Object.keys(item.kvmProfile || {})
|
|
936
1073
|
]);
|
|
@@ -945,37 +1082,33 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
945
1082
|
});
|
|
946
1083
|
|
|
947
1084
|
console.log(`\n Function Call Profile: ${item.op}`);
|
|
948
|
-
console.log(" Function Name |
|
|
949
|
-
console.log("
|
|
950
|
-
let
|
|
1085
|
+
console.log(" Function Name | WebAssembly Calls | kVM Interp Calls");
|
|
1086
|
+
console.log(" -------------------------+-------------------+------------------");
|
|
1087
|
+
let wasmTotal = 0, kvmTotal = 0;
|
|
951
1088
|
for (const fn of sortedFuncs) {
|
|
952
|
-
const aCount = item.arm64Profile?.[fn] ?? 0;
|
|
953
1089
|
const wCount = item.wasmProfile?.[fn] ?? 0;
|
|
954
1090
|
const kCount = item.kvmProfile?.[fn] ?? 0;
|
|
955
|
-
arm64Total += aCount;
|
|
956
1091
|
wasmTotal += wCount;
|
|
957
1092
|
kvmTotal += kCount;
|
|
958
1093
|
const fnCol = fn.padEnd(24);
|
|
959
|
-
const aStr = (aCount > 0 ? String(aCount) : "-").padStart(17);
|
|
960
1094
|
const wStr = (wCount > 0 ? String(wCount) : "-").padStart(17);
|
|
961
1095
|
const kStr = (kCount > 0 ? String(kCount) : "-").padStart(16);
|
|
962
|
-
console.log(` ${fnCol} | ${
|
|
1096
|
+
console.log(` ${fnCol} | ${wStr} | ${kStr}`);
|
|
963
1097
|
}
|
|
964
|
-
console.log("
|
|
1098
|
+
console.log(" -------------------------+-------------------+------------------");
|
|
965
1099
|
const totCol = "Total Calls".padEnd(24);
|
|
966
|
-
const aTotStr = String(arm64Total).padStart(17);
|
|
967
1100
|
const wTotStr = String(wasmTotal).padStart(17);
|
|
968
1101
|
const kTotStr = String(kvmTotal).padStart(16);
|
|
969
|
-
console.log(` ${totCol} | ${
|
|
1102
|
+
console.log(` ${totCol} | ${wTotStr} | ${kTotStr}`);
|
|
970
1103
|
}
|
|
971
1104
|
}
|
|
972
1105
|
|
|
973
1106
|
console.log(`\n=== AVERAGE ACROSS ALL ${phaseResults.length} OPERATIONS ===`);
|
|
974
|
-
console.log(
|
|
975
|
-
console.log(
|
|
1107
|
+
console.log(traceHeader);
|
|
1108
|
+
console.log(traceDivider);
|
|
976
1109
|
for (const phase of phases) {
|
|
977
1110
|
if (phase.isTotal) {
|
|
978
|
-
console.log(
|
|
1111
|
+
console.log(traceDivider);
|
|
979
1112
|
}
|
|
980
1113
|
const pName = phase.name.padEnd(24);
|
|
981
1114
|
const avg = (backend) => {
|
|
@@ -983,30 +1116,25 @@ if (runTrace && process.exitCode !== 1) {
|
|
|
983
1116
|
if (vals.length === 0) return null;
|
|
984
1117
|
return vals.reduce((a, b) => a + b, 0) / vals.length;
|
|
985
1118
|
};
|
|
986
|
-
const
|
|
987
|
-
|
|
988
|
-
const wasmCol = formatUs(avg("wasm"));
|
|
989
|
-
const kvmCol = formatUs(avg("kvm"));
|
|
990
|
-
console.log(`${pName} | ${arm64Col} | ${llvmCol} | ${wasmCol} | ${kvmCol}`);
|
|
1119
|
+
const cols = [pName, ...activeTraceLanes.map(l => formatUs(avg(l.id)))];
|
|
1120
|
+
console.log(cols.join(" | "));
|
|
991
1121
|
}
|
|
992
1122
|
|
|
993
|
-
if (phaseResults.some(r => r.
|
|
1123
|
+
if (phaseResults.some(r => r.wasmProfile || r.kvmProfile)) {
|
|
994
1124
|
console.log("\n=== FUNCTION CALL COUNT SUMMARY ACROSS ALL OPERATIONS ===");
|
|
995
|
-
console.log("Operation (Case) |
|
|
996
|
-
console.log("
|
|
997
|
-
let
|
|
1125
|
+
console.log("Operation (Case) | WebAssembly Calls | kVM Interp Calls");
|
|
1126
|
+
console.log("-------------------------+-------------------+------------------");
|
|
1127
|
+
let wasmGrand = 0, kvmGrand = 0;
|
|
998
1128
|
for (const r of phaseResults) {
|
|
999
|
-
const aSum = Object.values(r.arm64Profile || {}).reduce((a, b) => a + b, 0);
|
|
1000
1129
|
const wSum = Object.values(r.wasmProfile || {}).reduce((a, b) => a + b, 0);
|
|
1001
1130
|
const kSum = Object.values(r.kvmProfile || {}).reduce((a, b) => a + b, 0);
|
|
1002
|
-
arm64Grand += aSum;
|
|
1003
1131
|
wasmGrand += wSum;
|
|
1004
1132
|
kvmGrand += kSum;
|
|
1005
1133
|
const opCol = `${r.op} (${r.label})`.slice(0, 24).padEnd(24);
|
|
1006
|
-
console.log(`${opCol} | ${String(
|
|
1134
|
+
console.log(`${opCol} | ${String(wSum).padStart(17)} | ${String(kSum).padStart(16)}`);
|
|
1007
1135
|
}
|
|
1008
|
-
console.log("
|
|
1009
|
-
console.log(`${"Total Calls".padEnd(24)} | ${String(
|
|
1136
|
+
console.log("-------------------------+-------------------+------------------");
|
|
1137
|
+
console.log(`${"Total Calls".padEnd(24)} | ${String(wasmGrand).padStart(17)} | ${String(kvmGrand).padStart(16)}`);
|
|
1010
1138
|
}
|
|
1011
1139
|
console.log("=====================================================================\n");
|
|
1012
1140
|
}
|