Reuse normalized conversion cache records

This commit is contained in:
flash555588 2026-06-27 06:54:59 +08:00
parent 9964ab1b27
commit cfb47203b9
4 changed files with 635 additions and 584 deletions

View file

@ -41,6 +41,7 @@
- Performance: read absolute-path model files without an extra full-buffer copy when Node returns a whole file buffer, reducing memory spikes for large converted GLB assets.
- Performance: overlap direct-view model file reads with preview backend creation so large files spend less time in the loading phase before parsing starts.
- Performance: reuse source file stats across conversion-cache checks, reducing repeated filesystem metadata reads on slow or synced storage.
- Performance: reuse already-normalized converted-asset cache records during plugin startup, avoiding unnecessary cache cleanup work on healthy state.
- Performance: cache Three.js and Babylon renderable geometry stats so large-model performance/quality snapshots do not repeatedly traverse the full scene.
- Performance: skip automatic direct-view evidence registration for heavy/extreme models and delay medium-model registration to reduce post-load UI stalls.
- Performance: avoid rescanning heading-pin metadata on unrelated store updates, reducing workspace startup and state-change work in large vaults.

1164
main.js

File diff suppressed because one or more lines are too long

View file

@ -53,6 +53,27 @@ describe("createConvertedAssetCache", () => {
expect(changes).toEqual([[newer]]);
});
it("reuses already normalized initial records without emitting cleanup", () => {
const newest = createRecord({
sourcePath: "models/newest.step",
outputPath: "models/newest.glb",
createdAt: NOW,
});
const older = createRecord({
sourcePath: "models/older.step",
outputPath: "models/older.glb",
createdAt: NOW - 1_000,
});
const changes: ConvertedAssetRecord[][] = [];
const cache = createConvertedAssetCache([newest, older], records => changes.push(records));
expect(cache.entries()).toEqual([newest, older]);
expect(cache.get("models/newest.step", "step", "glb")).toEqual(newest);
expect(cache.get("models/older.step", "step", "glb")).toEqual(older);
expect(changes).toHaveLength(0);
});
it("emits sorted snapshots when setting and replacing records", () => {
const changes: ConvertedAssetRecord[][] = [];
const cache = createConvertedAssetCache([], records => changes.push(records));

View file

@ -51,6 +51,34 @@ function normalizeRecords(records: readonly ConvertedAssetRecord[], now = Date.n
.slice(0, MAX_CONVERTED_ASSET_RECORDS);
}
function reuseNormalizedRecords(
records: readonly ConvertedAssetRecord[],
now: number,
): readonly ConvertedAssetRecord[] | null {
if (records.length > MAX_CONVERTED_ASSET_RECORDS) {
return null;
}
const seen = new Set<string>();
let previousCreatedAt = Number.POSITIVE_INFINITY;
for (const record of records) {
if (!isRecordUsable(record, now)) {
return null;
}
const key = makeKey(record.sourcePath, record.sourceExt, record.targetExt);
if (seen.has(key)) {
return null;
}
if (record.createdAt > previousCreatedAt) {
return null;
}
seen.add(key);
previousCreatedAt = record.createdAt;
}
return records;
}
function sameRecord(a: ConvertedAssetRecord | undefined, b: ConvertedAssetRecord | undefined): boolean {
return !!a && !!b &&
a.cacheVersion === b.cacheVersion &&
@ -80,7 +108,8 @@ export function createConvertedAssetCache(
}
}
const normalizedInitialRecords = normalizeRecords(initialRecords);
const now = Date.now();
const normalizedInitialRecords = reuseNormalizedRecords(initialRecords, now) ?? normalizeRecords(initialRecords, now);
const map = new Map<string, ConvertedAssetRecord>(
normalizedInitialRecords.map((record) => [makeKey(record.sourcePath, record.sourceExt, record.targetExt), record]),
);
@ -96,7 +125,7 @@ export function createConvertedAssetCache(
normalizedInitialRecords.some((record, index) => !sameRecord(record, initialRecords[index]));
if (initialChanged) {
onChange?.(normalizedInitialRecords);
onChange?.([...normalizedInitialRecords]);
}
return {