Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
209 commits
Select commit Hold shift + click to select a range
bd7e506
test(perf): require deterministic synthetic benchmark corpus
seonghobae Aug 20, 2026
e913b9e
feat(perf): add deterministic multilingual corpus generator
seonghobae Aug 20, 2026
0f94141
test(perf): lock synthetic corpus identities
seonghobae Aug 20, 2026
b94f124
test(perf): require mixed script and raster size corpus
seonghobae Aug 20, 2026
1ff7021
feat(perf): add mixed script and raster size fixtures
seonghobae Aug 20, 2026
322dc64
test(perf): lock mixed script corpus identities
seonghobae Aug 20, 2026
45a74f8
test(perf): assert distinct raster fixture count
seonghobae Aug 20, 2026
5831e7c
test(perf): require deterministic Office benchmark fixtures
seonghobae Aug 20, 2026
4f702a3
perf: generate deterministic Office benchmark fixtures
seonghobae Aug 20, 2026
bf1fe4e
perf: lock deterministic Office benchmark fixtures
seonghobae Aug 20, 2026
0a67a3e
test(perf): require XLSX and PPTX benchmark fixtures
seonghobae Aug 20, 2026
f6e795d
perf: generate deterministic XLSX and PPTX fixtures
seonghobae Aug 20, 2026
940275a
perf: lock deterministic Office fixture matrix
seonghobae Aug 20, 2026
326e4de
test(perf): require deterministic benchmark statistics summary
seonghobae Aug 20, 2026
897a978
feat(perf): add deterministic benchmark statistics summary
seonghobae Aug 20, 2026
6a4dd66
test(perf): reject benchmark input output alias
seonghobae Aug 20, 2026
a838dbe
fix(perf): preserve benchmark sample inputs
seonghobae Aug 20, 2026
fe61395
test(perf): reject hard-linked summary evidence aliases
seonghobae Aug 21, 2026
33d5c45
fix(perf): preserve hard-linked benchmark source evidence
seonghobae Aug 21, 2026
676555f
test(perf): prove oversized samples preflight whole-file reads
seonghobae Aug 21, 2026
72db249
fix(perf): bound benchmark sample reads before allocation
seonghobae Aug 21, 2026
9766bcf
test(perf): require immutable benchmark provenance
seonghobae Aug 21, 2026
738d3e7
feat(perf): bind summaries to immutable provenance
seonghobae Aug 21, 2026
864fa8b
test(perf): require strict UTF-8 benchmark evidence
seonghobae Aug 21, 2026
bc887c0
fix(perf): reject malformed UTF-8 benchmark evidence
seonghobae Aug 21, 2026
596c48e
test(perf): preflight invalid summary destinations
seonghobae Aug 21, 2026
f072e74
fix(perf): preflight benchmark output destinations
seonghobae Aug 21, 2026
3efb68c
test(perf): reject arbitrary benchmark metadata
seonghobae Aug 21, 2026
6cb6418
fix(perf): reject unsupported benchmark metadata
seonghobae Aug 21, 2026
ba35b28
test(perf): require explicit benchmark regression comparator
seonghobae Aug 21, 2026
9504ead
feat(perf): add explicit benchmark regression comparator
seonghobae Aug 21, 2026
f5439a1
test(perf): prove comparator rejects blocking FIFO inputs
seonghobae Aug 21, 2026
13c09c5
test(perf): prove summarizer rejects blocking FIFO inputs
seonghobae Aug 21, 2026
dbf5345
fix(perf): validate comparator inputs without blocking
seonghobae Aug 21, 2026
e98faee
fix(perf): validate sample inputs without blocking
seonghobae Aug 21, 2026
d820150
test(perf): reject dangling benchmark output symlinks
seonghobae Aug 21, 2026
42c9516
fix(perf): reject dangling benchmark output symlinks
seonghobae Aug 21, 2026
2b2f537
test(perf): fail closed on regression percentage overflow
seonghobae Aug 21, 2026
712cd9d
fix(perf): fail closed on regression percentage overflow
seonghobae Aug 21, 2026
1604f20
test(perf): require provenance-bound regression receipts
seonghobae Aug 21, 2026
ceac649
fix(perf): bind regression receipts to exact evidence
seonghobae Aug 21, 2026
4dc7984
test(perf): align comparator receipt contract
seonghobae Aug 21, 2026
36af472
test(perf): reject aliased summary destinations
seonghobae Aug 21, 2026
a869556
fix(perf): reject aliased summary outputs
seonghobae Aug 21, 2026
1902b63
test(perf): reject vacuous same-artifact comparisons
seonghobae Aug 21, 2026
a746787
fix(perf): reject same-artifact regression evidence
seonghobae Aug 22, 2026
8e32114
test(perf): use distinct artifacts in comparator receipts
seonghobae Aug 22, 2026
f6b87db
test(perf): reject private-looking benchmark evidence identifiers
seonghobae Aug 22, 2026
b6fef32
test(perf): keep hardware mismatch fixture privacy-safe
seonghobae Aug 22, 2026
4a7786c
fix(perf): constrain benchmark evidence identifiers
seonghobae Aug 22, 2026
37ec73e
fix(perf): validate comparison evidence identifiers
seonghobae Aug 22, 2026
142499d
test(perf): reject private-looking benchmark units
seonghobae Aug 22, 2026
7248c18
test(perf): reject private units at comparator boundary
seonghobae Aug 22, 2026
92eaeb1
fix(perf): constrain benchmark measurement units
seonghobae Aug 22, 2026
3fe89a3
fix(perf): validate comparator measurement units
seonghobae Aug 22, 2026
3e1f345
test(perf): require markdown measurement harness
seonghobae Aug 22, 2026
124e944
feat(perf): add bounded markdown runtime measurement
seonghobae Aug 22, 2026
a08eb09
test(perf): bind markdown measurements to measured artifact
seonghobae Aug 22, 2026
e29e569
test(perf): use exact measured module digests
seonghobae Aug 22, 2026
866ca00
fix(perf): verify measured markdown artifact provenance
seonghobae Aug 22, 2026
1ecdba3
test(perf): reject measurement output aliasing module
seonghobae Aug 22, 2026
b5373c9
fix(perf): preserve measured module from output writes
seonghobae Aug 22, 2026
4fb4f3f
test(perf): reject non-local file URL authorities
seonghobae Aug 22, 2026
2bcd1de
fix(perf): require local file URL authority
seonghobae Aug 22, 2026
398c16b
test(perf): redact measured module failures
seonghobae Aug 22, 2026
8369d42
fix(perf): redact measured module failures
seonghobae Aug 22, 2026
df31a76
test(perf): require deterministic demo chunking
seonghobae Aug 22, 2026
0ec9731
feat(perf): classify demo vendor chunks
seonghobae Aug 22, 2026
490795b
fix(perf): split oversized demo bundle
seonghobae Aug 22, 2026
84aab25
test(perf): require revision-evidence measurement harness
seonghobae Aug 22, 2026
1f64915
feat(perf): measure packed revision-evidence latency
seonghobae Aug 22, 2026
407b8a1
test(perf): reject symlinked summary inputs
seonghobae Aug 22, 2026
5882974
fix(perf): reject symlinked summary evidence
seonghobae Aug 22, 2026
24d05fd
test(perf): redact hostile revision result accessors
seonghobae Aug 22, 2026
10b071d
fix(perf): contain hostile revision result accessors
seonghobae Aug 22, 2026
286bc07
test(perf): define retained-memory settling RED contract
seonghobae Aug 22, 2026
ef33eba
feat(perf): analyze retained-memory settling
seonghobae Aug 22, 2026
e4cab92
test(perf): reject mismatched memory evidence profiles
seonghobae Aug 22, 2026
e671a5a
fix(perf): bind memory benchmark id to profile
seonghobae Aug 22, 2026
5a6944c
test(perf): reject inexact memory medians
seonghobae Aug 23, 2026
a1b5201
fix(perf): fail closed on inexact memory medians
seonghobae Aug 23, 2026
80c8bbb
test(perf): reject mismatched benchmark profiles
seonghobae Aug 23, 2026
dcf8b65
fix(perf): bind benchmark ids to document profiles
seonghobae Aug 23, 2026
b240eac
test(perf): reject mismatched sample profiles
seonghobae Aug 23, 2026
00b062e
fix(perf): bind sample ids to document profiles
seonghobae Aug 23, 2026
1a76294
test(perf): reject corpus output symlink escape
seonghobae Aug 23, 2026
abf7d89
fix(perf): protect corpus output paths
seonghobae Aug 23, 2026
4002bc4
test(perf): redact benchmark output path failures
seonghobae Aug 23, 2026
1528f0e
fix(perf): redact benchmark output path failures
seonghobae Aug 23, 2026
da69be6
test(perf): redact revision output path failures
seonghobae Aug 23, 2026
523c986
fix(perf): redact revision output path failures
seonghobae Aug 23, 2026
28a45ac
test(perf): redact summary output preparation failures
seonghobae Aug 23, 2026
d44925e
fix(perf): redact output directory preparation failures
seonghobae Aug 23, 2026
d454176
test(perf): redact Markdown output publication failures
seonghobae Aug 23, 2026
e066321
fix(perf): redact Markdown output publication failures
seonghobae Aug 23, 2026
0b724e0
test(perf): redact revision output publication failures
seonghobae Aug 23, 2026
12a48b4
fix(perf): redact revision output publication failures
seonghobae Aug 23, 2026
86a771e
test(perf): require single-command benchmark suite
seonghobae Aug 23, 2026
9a618bc
feat(perf): compose single-command benchmark suite
seonghobae Aug 23, 2026
c41f101
test(perf): reject symlink benchmark output directories
seonghobae Aug 23, 2026
18fe738
fix(perf): reject symlink suite output roots
seonghobae Aug 23, 2026
156b8e3
test(perf): reject symlink summary output directory
seonghobae Aug 23, 2026
52ba733
fix(perf): reject symlink summary directories
seonghobae Aug 23, 2026
bd3eb04
test(perf): reject symlinked summary ancestors
seonghobae Aug 23, 2026
3b722e4
fix(perf): reject symlinked summary ancestors
seonghobae Aug 23, 2026
eb15b2f
test(perf): reject symlinked suite ancestors
seonghobae Aug 23, 2026
0cfd5a9
fix(perf): reject symlinked suite ancestors
seonghobae Aug 23, 2026
f1adf74
test(perf): reject symlinked markdown output ancestors
seonghobae Aug 23, 2026
0ac8712
fix(perf): reject symlinked markdown output ancestors
seonghobae Aug 23, 2026
2bcf06c
test(perf): reject symlinked revision output ancestors
seonghobae Aug 23, 2026
2e9332e
fix(perf): reject symlinked revision output ancestors
seonghobae Aug 23, 2026
ea00fe9
fix(perf): preserve path-redacted summary failures
seonghobae Aug 23, 2026
dba7505
test(perf): reject symlinked sample input
seonghobae Aug 23, 2026
9afff91
fix(perf): reject symlinked summary sample input
seonghobae Aug 23, 2026
824561c
fix(perf): preserve nonregular input diagnostics
seonghobae Aug 23, 2026
a7b6bc9
test(perf): cover markdown input path privacy
seonghobae Aug 23, 2026
dd35f07
fix(perf): redact markdown input path errors
seonghobae Aug 23, 2026
1781400
test(perf): cover markdown module path privacy
seonghobae Aug 23, 2026
17bb601
fix(perf): redact markdown module path errors
seonghobae Aug 23, 2026
2d22587
test(perf): reproduce revision module path leak
seonghobae Aug 23, 2026
0547812
fix(perf): redact revision module path errors
seonghobae Aug 23, 2026
cecef7d
test(perf): reproduce revision input path leak
seonghobae Aug 23, 2026
f412c50
fix(perf): redact revision file-open path errors
seonghobae Aug 23, 2026
df1ac90
test(perf): reproduce existing-output alias path leaks
seonghobae Aug 23, 2026
9488aad
fix(perf): validate Markdown input before alias stat
seonghobae Aug 23, 2026
d2a7a1f
fix(perf): validate revision input before alias stat
seonghobae Aug 23, 2026
82155d3
test(perf): reproduce summary input path leak
seonghobae Aug 23, 2026
463f100
fix(perf): redact summary input inspection failures
seonghobae Aug 23, 2026
f4400a6
test(perf): expose retained-memory input path leakage
seonghobae Aug 23, 2026
5d1a62e
fix(perf): redact retained-memory input inspection failures
seonghobae Aug 23, 2026
6a6ee59
test(perf): expose comparator input path leakage
seonghobae Aug 23, 2026
00bdb5b
fix(perf): redact comparator input inspection failures
seonghobae Aug 23, 2026
45c6f41
test(perf): expose Office fixture output symlink overwrite
seonghobae Aug 23, 2026
e4d3478
fix(perf): fail closed on Office fixture output symlinks
seonghobae Aug 23, 2026
5fe6023
test(perf): expose Office fixture output directory symlinks
seonghobae Aug 23, 2026
7983e66
fix(perf): reject Office fixture output directory symlinks
seonghobae Aug 23, 2026
31dee74
test(perf): reject hard-linked Office fixture outputs
seonghobae Aug 23, 2026
233f81e
fix(perf): reject hard-linked Office fixture outputs
seonghobae Aug 23, 2026
cdd9e34
test(perf): expose summary output hard-link overwrite
seonghobae Aug 24, 2026
36d8830
fix(perf): reject hard-linked summary outputs
seonghobae Aug 24, 2026
2222364
chore(perf): preserve summary metadata formatting
seonghobae Aug 24, 2026
3ddee5a
fix(perf): preserve summary alias diagnostics
seonghobae Aug 24, 2026
399a67a
test(perf): expose producer output hard-link overwrite
seonghobae Aug 24, 2026
1b7da55
fix(perf): reject hard-linked Markdown output
seonghobae Aug 24, 2026
a48c1d4
fix(perf): reject hard-linked revision output
seonghobae Aug 24, 2026
2f94a6b
test(perf): require revision evidence in single-command suite
seonghobae Aug 24, 2026
49baff6
feat(perf): compose revision evidence in current benchmark suite
seonghobae Aug 24, 2026
2614a79
fix(perf): preserve measured-script argument order
seonghobae Aug 24, 2026
7ae8007
test(perf): keep suite symlink regression on current CLI
seonghobae Aug 24, 2026
eb6e8ac
test(perf): require atomic suite evidence publication
seonghobae Aug 24, 2026
0af333b
fix(perf): remove partial suite evidence on failure
seonghobae Aug 24, 2026
d609faa
test(perf): require packed artifact benchmark provenance
seonghobae Aug 24, 2026
a49ea9d
fix(perf): bind suite to packed npm artifact
seonghobae Aug 24, 2026
f0c9d8f
test(perf): reject mislabeled benchmark runtime provenance
seonghobae Aug 24, 2026
0c9f3f3
fix(perf): attest active benchmark runtime
seonghobae Aug 24, 2026
5c8f6f8
test(perf): bind suite manifest to run provenance
seonghobae Aug 24, 2026
946c715
fix(perf): bind suite manifest to run provenance
seonghobae Aug 24, 2026
413b0f3
test(perf): attest packed suite run provenance
seonghobae Aug 25, 2026
f136388
test(perf): bind benchmark source provenance to checkout
seonghobae Aug 25, 2026
9876531
fix(perf): verify benchmark source checkout provenance
seonghobae Aug 25, 2026
4a9661f
fix(perf): reject dirty benchmark provenance
seonghobae Aug 25, 2026
b376877
test(perf): isolate checkout provenance regression
seonghobae Aug 25, 2026
8b7b6df
test(perf): require Office duration and RSS evidence
seonghobae Aug 25, 2026
38a287c
test(perf): bind Office evidence to canonical fixtures
seonghobae Aug 25, 2026
a5275f9
feat(perf): measure canonical Office render latency and RSS
seonghobae Aug 25, 2026
e6598e8
test(perf): bound hung Office render sample RED
seonghobae Aug 25, 2026
7128b6c
fix(perf): bound Office render sample duration
seonghobae Aug 25, 2026
1572af1
test(perf): require child fixture re-verification
seonghobae Aug 25, 2026
28053fd
fix(perf): bind Office child to canonical fixture
seonghobae Aug 25, 2026
a6ab00f
test(perf): pass canonical child identity
seonghobae Aug 25, 2026
2251be8
test(perf): bind packed benchmark to verified tarball bytes
seonghobae Aug 25, 2026
0055f24
test(perf): exercise packed tarball interposition
seonghobae Aug 25, 2026
4033e2c
fix(perf): snapshot verified packed artifact before extraction
seonghobae Aug 25, 2026
c455ec1
fix(test): preserve generated benchmark source interpolation
seonghobae Aug 25, 2026
5abc237
test(perf): reject mutable existing suite evidence targets
seonghobae Aug 25, 2026
9621133
fix(perf): preserve existing benchmark evidence directories
seonghobae Aug 25, 2026
1949f18
test(perf): cover core existing-output race boundary
seonghobae Aug 25, 2026
92683c2
fix(perf): fail closed on existing evidence output
seonghobae Aug 25, 2026
c16fe9c
test(perf): preserve existing measurement evidence
seonghobae Aug 25, 2026
856c1e9
fix(perf): preserve existing markdown evidence
seonghobae Aug 25, 2026
1b7710a
fix(perf): preserve existing revision evidence
seonghobae Aug 25, 2026
71b1fc5
test(perf): require HTML serialization measurement
seonghobae Aug 25, 2026
8851d5d
feat(perf): measure HTML serialization direction
seonghobae Aug 25, 2026
cf8fd2e
test(perf): require HTML serialization in benchmark suite
seonghobae Aug 25, 2026
94ad4f8
feat(perf): include HTML serialization in suite
seonghobae Aug 25, 2026
0d8557d
test(perf): require packed HTML serialization evidence
seonghobae Aug 25, 2026
c220538
test(perf): reject mismatched benchmark source checkout
seonghobae Aug 25, 2026
67b499c
fix(perf): bind benchmark evidence to checked-out source
seonghobae Aug 25, 2026
fd73da7
test(perf): bind suite source provenance to checkout
seonghobae Aug 25, 2026
5547e4d
test(perf): use live checkout SHA for HTML suite
seonghobae Aug 25, 2026
aa9be79
fix(perf): reject wrong source SHA before benchmark evidence
seonghobae Aug 25, 2026
0001bb9
fix(perf): restore packed HTML benchmark composition
seonghobae Aug 25, 2026
48363ba
test(perf): reject false producer provenance
seonghobae Aug 26, 2026
a83a425
fix(perf): bind Markdown evidence to live source
seonghobae Aug 26, 2026
d4e7883
fix(perf): bind revision evidence to live source
seonghobae Aug 26, 2026
19c8c28
fix(test): preserve producer provenance typing
seonghobae Aug 26, 2026
fa91c06
fix(test): use live Markdown benchmark provenance
seonghobae Aug 26, 2026
d46dc2f
fix(test): use live revision benchmark provenance
seonghobae Aug 26, 2026
c3d9fa6
fix(test): use active suite runtime provenance
seonghobae Aug 26, 2026
65cb302
fix(test): bind producer immutability fixtures to active provenance
seonghobae Aug 26, 2026
8f1480a
fix(test): bind Markdown privacy fixtures to active provenance
seonghobae Aug 26, 2026
aba2d3b
fix(test): bind HTML serialization fixtures to active provenance
seonghobae Aug 26, 2026
d334b95
fix(test): bind HTML suite runtime to active provenance
seonghobae Aug 26, 2026
fc54c8c
test(perf): reject source movement during Office measurement
seonghobae Aug 26, 2026
227418d
fix(perf): bind Office evidence to stable source revision
seonghobae Aug 26, 2026
483c3fc
test(perf): reject source movement during direct measurement
seonghobae Aug 26, 2026
65e6327
test(perf): build isolated git shim for source-move RED
seonghobae Aug 26, 2026
8a7e49c
fix(perf): recheck source provenance after markdown measurement
seonghobae Aug 26, 2026
a5123c7
fix(perf): recheck source provenance after revision measurement
seonghobae Aug 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
309 changes: 309 additions & 0 deletions benchmarks/analyze-memory-settling.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
import {
closeSync,
constants,
fstatSync,
lstatSync,
openSync,
readSync,
} from 'node:fs';
import { resolve } from 'node:path';

const MAX_INPUT_BYTES = 1024 * 1024;
const READ_CHUNK_BYTES = 64 * 1024;
const MAX_SAMPLES = 1_000_000;
const READ_ONLY_NONBLOCKING =
constants.O_RDONLY |
(constants.O_NONBLOCK ?? 0) |
(constants.O_NOFOLLOW ?? 0);
const BENCHMARK_ID_PREFIX = 'editor-lifecycle-retained-memory-';
const BENCHMARK_ID_PATTERN =
/^editor-lifecycle-retained-memory-(?:small|medium|large|stress)$/u;
const SHA1_PATTERN = /^[0-9a-f]{40}$/u;
const SHA256_PATTERN = /^[0-9a-f]{64}$/u;
const RUNTIME_ID_PATTERN =
/^(?:node|python|chromium|firefox|webkit|playwright)-[0-9]+(?:\.[0-9]+){1,3}$/u;
const REFERENCE_HARDWARE_ID_PATTERN =
/^(?:github-actions-(?:ubuntu|windows|macos)-[0-9]+(?:\.[0-9]+){0,2}-(?:x64|arm64)|refhw-sha256-[0-9a-f]{64})$/u;
const DOCUMENT_PROFILES = new Set(['small', 'medium', 'large', 'stress']);
const EVIDENCE_KEYS = new Set([
'contractVersion',
'benchmarkId',
'unit',
'sourceCommitSha',
'artifactSha256',
'documentProfile',
'runtimeId',
'referenceHardwareId',
'warmupSamples',
'samples',
]);
const UTF8_DECODER = new TextDecoder('utf-8', { fatal: true });

function resolveArguments(argv) {
if (
argv.length !== 6 ||
argv[0] !== '--input' ||
argv[1].length === 0 ||
argv[2] !== '--window-size' ||
argv[3].trim().length === 0 ||
argv[4] !== '--max-growth-bytes' ||
argv[5].trim().length === 0
) {
throw new Error(
'Usage: node benchmarks/analyze-memory-settling.mjs --input <evidence.json> --window-size <positive-integer> --max-growth-bytes <number>',
);
}

const windowSize = Number(argv[3]);
if (!Number.isSafeInteger(windowSize) || windowSize <= 0) {
throw new Error('Memory settling window size must be a positive safe integer.');
}

const maxGrowthBytes = Number(argv[5]);
if (!Number.isFinite(maxGrowthBytes) || maxGrowthBytes < 0) {
throw new Error(
'Memory settling max growth bytes must be a finite non-negative number.',
);
}

return Object.freeze({
inputPath: resolve(argv[1]),
windowSize,
maxGrowthBytes,
});
}

function inspectEvidenceInputPath(path) {
try {
return lstatSync(path, { throwIfNoEntry: false });
} catch {
throw new Error('Memory settling evidence input must be a regular file.');
}
}

function readBoundedJson(path) {
const pathMetadata = inspectEvidenceInputPath(path);
if (pathMetadata === undefined || pathMetadata.isSymbolicLink()) {
throw new Error(
'Memory settling evidence input must be a regular non-symlink file.',
);
}
if (!pathMetadata.isFile()) {
throw new Error('Memory settling evidence input must be a regular file.');
}

const descriptor = openSync(path, READ_ONLY_NONBLOCKING);
try {
const metadata = fstatSync(descriptor);
if (!metadata.isFile()) {
throw new Error('Memory settling evidence input must be a regular file.');
}
if (metadata.size > MAX_INPUT_BYTES) {
throw new Error('Memory settling evidence input exceeds the supported size.');
}

const chunks = [];
let totalBytes = 0;
while (totalBytes <= MAX_INPUT_BYTES) {
const remainingBudget = MAX_INPUT_BYTES + 1 - totalBytes;
const chunk = Buffer.allocUnsafe(
Math.min(READ_CHUNK_BYTES, remainingBudget),
);
const bytesRead = readSync(
descriptor,
chunk,
0,
chunk.byteLength,
null,
);
if (bytesRead === 0) break;
totalBytes += bytesRead;
if (totalBytes > MAX_INPUT_BYTES) {
throw new Error(
'Memory settling evidence input exceeds the supported size.',
);
}
chunks.push(chunk.subarray(0, bytesRead));
}

let text;
try {
text = UTF8_DECODER.decode(Buffer.concat(chunks, totalBytes));
} catch {
throw new Error('Memory settling evidence input must be valid UTF-8 JSON.');
}

try {
return JSON.parse(text);
} catch {
throw new Error('Memory settling evidence input must be valid JSON.');
}
} finally {
closeSync(descriptor);
}
}

function validateEvidence(value) {
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
throw new Error('Memory settling evidence input must be an object.');
}
const keys = Object.keys(value);
if (
keys.length !== EVIDENCE_KEYS.size ||
keys.some((key) => !EVIDENCE_KEYS.has(key))
) {
throw new Error('Memory settling evidence input has an unsupported shape.');
}
if (value.contractVersion !== 1) {
throw new Error('Memory settling evidence contractVersion must be 1.');
}
if (
typeof value.benchmarkId !== 'string' ||
!BENCHMARK_ID_PATTERN.test(value.benchmarkId)
) {
throw new Error('Memory settling evidence benchmarkId is invalid.');
}
if (value.unit !== 'bytes') {
throw new Error('Memory settling evidence unit must be bytes.');
}
if (
typeof value.sourceCommitSha !== 'string' ||
!SHA1_PATTERN.test(value.sourceCommitSha)
) {
throw new Error('Memory settling evidence sourceCommitSha is invalid.');
}
if (
typeof value.artifactSha256 !== 'string' ||
!SHA256_PATTERN.test(value.artifactSha256)
) {
throw new Error('Memory settling evidence artifactSha256 is invalid.');
}
if (
typeof value.documentProfile !== 'string' ||
!DOCUMENT_PROFILES.has(value.documentProfile)
) {
throw new Error('Memory settling evidence documentProfile is invalid.');
}
if (
value.benchmarkId.slice(BENCHMARK_ID_PREFIX.length) !== value.documentProfile
) {
throw new Error(
'Memory settling evidence benchmark profile must match documentProfile.',
);
}
if (
typeof value.runtimeId !== 'string' ||
!RUNTIME_ID_PATTERN.test(value.runtimeId)
) {
throw new Error('Memory settling evidence runtimeId is invalid.');
}
if (
typeof value.referenceHardwareId !== 'string' ||
!REFERENCE_HARDWARE_ID_PATTERN.test(value.referenceHardwareId)
) {
throw new Error('Memory settling evidence referenceHardwareId is invalid.');
}
if (
!Number.isSafeInteger(value.warmupSamples) ||
value.warmupSamples < 0 ||
value.warmupSamples > MAX_SAMPLES
) {
throw new Error('Memory settling evidence warmupSamples is invalid.');
}
if (
!Array.isArray(value.samples) ||
value.samples.length === 0 ||
value.samples.length > MAX_SAMPLES ||
value.samples.some(
(sample) =>
!Number.isSafeInteger(sample) || sample < 0,
)
) {
throw new Error(
'Memory settling evidence samples must be bounded non-negative safe integers.',
);
}
if (value.warmupSamples >= value.samples.length) {
throw new Error('Memory settling evidence warmupSamples is invalid.');
}

return Object.freeze({
benchmarkId: value.benchmarkId,
unit: value.unit,
sourceCommitSha: value.sourceCommitSha,
artifactSha256: value.artifactSha256,
documentProfile: value.documentProfile,
runtimeId: value.runtimeId,
referenceHardwareId: value.referenceHardwareId,
warmupSamples: value.warmupSamples,
samples: Object.freeze([...value.samples]),
});
}

function median(values) {
const sorted = [...values].sort((left, right) => left - right);
const midpoint = Math.floor(sorted.length / 2);
if (sorted.length % 2 === 1) return sorted[midpoint];

const left = sorted[midpoint - 1];
const right = sorted[midpoint];
const distance = right - left;
const wholeMidpoint = left + Math.floor(distance / 2);
if (distance % 2 === 1 && wholeMidpoint >= 2 ** 52) {
throw new Error(
'Memory settling window median must be exactly representable.',
);
}
return wholeMidpoint + (distance % 2) / 2;
}

function analyze(evidence, windowSize, maxGrowthBytes) {
const settledSamples = evidence.samples.slice(evidence.warmupSamples);
if (settledSamples.length < windowSize * 2) {
throw new Error(
'Memory settling evidence requires warmup plus two disjoint comparison windows.',
);
}

const firstWindowMedianBytes = median(settledSamples.slice(0, windowSize));
const lastWindowMedianBytes = median(settledSamples.slice(-windowSize));
const retainedGrowthBytes = lastWindowMedianBytes - firstWindowMedianBytes;

return Object.freeze({
contractVersion: 1,
benchmarkId: evidence.benchmarkId,
unit: evidence.unit,
sourceCommitSha: evidence.sourceCommitSha,
artifactSha256: evidence.artifactSha256,
documentProfile: evidence.documentProfile,
runtimeId: evidence.runtimeId,
referenceHardwareId: evidence.referenceHardwareId,
sampleCount: evidence.samples.length,
warmupSamples: evidence.warmupSamples,
windowSize,
firstWindowMedianBytes,
lastWindowMedianBytes,
retainedGrowthBytes,
maxGrowthBytes,
passed: retainedGrowthBytes <= maxGrowthBytes,
});
}

function main() {
const { inputPath, windowSize, maxGrowthBytes } = resolveArguments(
process.argv.slice(2),
);
const evidence = validateEvidence(readBoundedJson(inputPath));
const result = analyze(evidence, windowSize, maxGrowthBytes);
process.stdout.write(`${JSON.stringify(result)}\n`);
if (!result.passed) process.exitCode = 1;
}

try {
main();
} catch (error) {
const message =
error instanceof Error ? error.message : 'Memory settling analysis failed.';
process.stderr.write(`${message}\n`);
process.exitCode = 1;
}
Loading
Loading