perf(javascript): index structured observations by path

Build package, JSON-module and source-map indexes once instead of rescanning every observation list per file. Preserve first-observation lookup semantics when paths repeat and share each JSON lookup with the file projection.

Validation: duplicate-observation consumer regression and reconstruction suites. Flameox captured before/after CPU profiles on 3,000 JSON files; the complete CLI output stayed byte-identical. Exploratory samples do not establish an end-to-end timing improvement.
This commit is contained in:
morluto
2026-10-11 05:33:21 +08:00
parent 684199ba0b
commit 69fe5b6010
2 changed files with 147 additions and 13 deletions
@@ -115,9 +115,18 @@ export const addJavaScriptArtifactContainers = (
export const addJavaScriptArtifactFiles = (
context: JavaScriptArtifactGraphContext,
): void => {
const packagesByPath = indexFirstByPath(context.analysis.packages);
const jsonModulesByPath = indexFirstByPath(context.analysis.json_modules);
const sourceMapsByPath = indexFirstByPath(context.analysis.source_maps);
for (const analyzed of context.analysis.files) {
const { file } = analyzed;
const target = createFileTarget(context, file, analyzed.javascript);
const jsonValue = jsonModulesByPath.get(file.path);
const target = createFileTarget(
context,
file,
analyzed.javascript,
jsonValue,
);
context.fileNodes.set(file.path, target);
if (file.kind === "javascript") context.assetNodes.set(file.path, target);
const entry = createAsarEntry(context, file);
@@ -163,9 +172,7 @@ export const addJavaScriptArtifactFiles = (
? "JavaScript syntax could not be parsed."
: `JavaScript text was unavailable: ${file.text.reason}.`,
});
const packageValue = context.analysis.packages.find(
({ path }) => path === file.path,
);
const packageValue = packagesByPath.get(file.path);
if (packageValue !== undefined && packageValue.status !== "included")
addUnavailableStaticParseScope(context, {
file,
@@ -173,9 +180,6 @@ export const addJavaScriptArtifactFiles = (
operation: "parse-package-json",
limitation: packageValue.limitation,
});
const jsonValue = context.analysis.json_modules.find(
({ path }) => path === file.path,
);
if (jsonValue !== undefined && jsonValue.status !== "included")
addUnavailableStaticParseScope(context, {
file,
@@ -183,9 +187,7 @@ export const addJavaScriptArtifactFiles = (
operation: "parse-json-module",
limitation: jsonValue.limitation,
});
const sourceMap = context.analysis.source_maps.find(
({ path }) => path === file.path,
);
const sourceMap = sourceMapsByPath.get(file.path);
if (sourceMap !== undefined && sourceMap.status === "invalid")
addUnavailableStaticParseScope(context, {
file,
@@ -270,11 +272,9 @@ const createFileTarget = (
context: JavaScriptArtifactGraphContext,
file: JavaScriptArtifactFile,
javascript: JavaScriptModuleArtifactAnalysis["files"][number]["javascript"],
json: JavaScriptModuleArtifactAnalysis["json_modules"][number] | undefined,
): ApplicationNode => {
const kind = artifactFileNodeKind(file.kind);
const json = context.analysis.json_modules.find(
({ path }) => path === file.path,
);
return context.accumulator.addNode({
kind,
identity: {
@@ -309,6 +309,16 @@ const createFileTarget = (
});
};
const indexFirstByPath = <Value extends { readonly path: string }>(
values: readonly Value[],
): ReadonlyMap<string, Value> => {
const index = new Map<string, Value>();
for (const value of values) {
if (!index.has(value.path)) index.set(value.path, value);
}
return index;
};
const createAsarEntry = (
context: JavaScriptArtifactGraphContext,
file: JavaScriptArtifactFile,
@@ -0,0 +1,124 @@
import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import { expect, it } from "vitest";
import { scanCanonicalArtifactInventory } from "../../fixtures/artifactInventory.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { readJavaScriptArtifactFiles } from "../../support/javascriptApplicationScope.js";
import { analyzeJavaScriptArtifactFiles } from "../../../src/application/javascript/JavaScriptArtifactAnalysis.js";
import { buildJavaScriptArtifactGraph } from "../../../src/application/javascript/JavaScriptArtifactGraphBuilder.js";
import { createJavaScriptArtifactReader } from "../../../src/artifacts/javascript/JavaScriptArtifactReader.js";
import type {
JavaScriptJsonModuleObservation,
JavaScriptPackageObservation,
JavaScriptSourceMapObservation,
} from "../../../src/application/javascript/JavaScriptArtifactAnalysisTypes.js";
it("uses the first structured observation when paths repeat", async () => {
const root = await createTestTempDirectory("rea-artifact-graph-index-");
await Promise.all([
writeFile(join(root, "package.json"), JSON.stringify({ name: "fixture" })),
writeFile(join(root, "data.json"), JSON.stringify({ actual: true })),
writeFile(join(root, "app.js"), "//# sourceMappingURL=app.js.map"),
writeFile(
join(root, "app.js.map"),
JSON.stringify({
version: 3,
sources: ["app.ts"],
names: [],
mappings: "",
}),
),
]);
const snapshot = await scanCanonicalArtifactInventory(root, {});
const reader = createJavaScriptArtifactReader(root, "directory");
try {
const files = await readJavaScriptArtifactFiles(reader, snapshot);
const analysis = analyzeJavaScriptArtifactFiles(files);
const packageObservation = analysis.packages.find(
({ path }) => path === "package.json",
);
const jsonObservation = analysis.json_modules.find(
({ path }) => path === "data.json",
);
const sourceMapObservation = analysis.source_maps.find(
({ path }) => path === "app.js.map",
);
expect(packageObservation).toBeDefined();
expect(jsonObservation).toBeDefined();
expect(sourceMapObservation).toBeDefined();
if (
packageObservation === undefined ||
jsonObservation === undefined ||
sourceMapObservation === undefined
)
throw new TypeError("Expected structured artifact observations");
const graph = buildJavaScriptArtifactGraph(snapshot, files, {
...analysis,
packages: [
packageObservation,
{
...packageObservation,
status: "invalid",
name: null,
version: null,
main: null,
renderer: null,
limitation: "later duplicate",
} satisfies JavaScriptPackageObservation,
],
json_modules: [
jsonObservation,
{
...jsonObservation,
status: "invalid",
top_level_keys: [],
omitted_top_level_keys: 0,
limitation: "later duplicate",
} satisfies JavaScriptJsonModuleObservation,
],
source_maps: [
sourceMapObservation,
{
...sourceMapObservation,
status: "invalid",
sources: [],
limitation: "later duplicate",
} satisfies JavaScriptSourceMapObservation,
],
});
const dataFile = graph.nodes.find(({ observations }) =>
observations.some(({ properties }) => properties.path === "data.json"),
);
expect(dataFile?.observations[0]?.properties).toMatchObject({
json_parse_status: "included",
json_top_level_keys: ["actual"],
omitted_json_top_level_keys: 0,
});
const unavailablePaths = graph.nodes
.filter(({ kind }) => kind === "unknown")
.flatMap(({ observations }) =>
observations.map(({ properties }) => ({
path: properties.path,
operation: properties.operation,
})),
);
expect(unavailablePaths).not.toContainEqual({
path: "package.json",
operation: "parse-package-json",
});
expect(unavailablePaths).not.toContainEqual({
path: "data.json",
operation: "parse-json-module",
});
expect(unavailablePaths).not.toContainEqual({
path: "app.js.map",
operation: "parse-local-source-map",
});
} finally {
await reader.close();
}
});