- Added performance markers in `ndView.tsx` to track startup and rendering times. - Implemented caching logic for custom train data in `useAllTrainDiagram.tsx` with timestamps for data readiness. - Optimized station data retrieval in `useStationList.tsx` by creating indexes for faster access. - Refactored train delay data handling in `useTrainDelayData.tsx` to improve cleanup on unmount. - Introduced tests for shared in-flight requests and timetable cache functionality to ensure reliability.
72 lines
2.0 KiB
TypeScript
72 lines
2.0 KiB
TypeScript
type StartupData = Record<string, unknown> | undefined;
|
|
|
|
const isDevelopment = typeof __DEV__ !== "undefined" && __DEV__;
|
|
const startedAt = Date.now();
|
|
const marks: Array<{ name: string; elapsedMs: number; data?: StartupData }> = [];
|
|
const onceKeys = new Set<string>();
|
|
const stateValues = new Map<string, string>();
|
|
let reportTimers: ReturnType<typeof setTimeout>[] = [];
|
|
|
|
const serialize = (data: StartupData): string => {
|
|
if (data === undefined) return "";
|
|
try {
|
|
return ` data=${JSON.stringify(data)}`;
|
|
} catch {
|
|
return " data=<unserializable>";
|
|
}
|
|
};
|
|
|
|
export const markStartup = (name: string, data?: StartupData): void => {
|
|
if (!isDevelopment) return;
|
|
const elapsedMs = Date.now() - startedAt;
|
|
marks.push({ name, elapsedMs, data });
|
|
console.log(`[STARTUP PERF] ${name} +${elapsedMs}ms${serialize(data)}`);
|
|
};
|
|
|
|
export const markStartupOnce = (
|
|
key: string,
|
|
name: string,
|
|
data?: StartupData,
|
|
): void => {
|
|
if (!isDevelopment || onceKeys.has(key)) return;
|
|
onceKeys.add(key);
|
|
markStartup(name, data);
|
|
};
|
|
|
|
export const markStartupState = (
|
|
key: string,
|
|
name: string,
|
|
data: StartupData,
|
|
): void => {
|
|
if (!isDevelopment) return;
|
|
let serialized = "";
|
|
try {
|
|
serialized = JSON.stringify(data);
|
|
} catch {
|
|
serialized = "<unserializable>";
|
|
}
|
|
if (stateValues.get(key) === serialized) return;
|
|
stateValues.set(key, serialized);
|
|
markStartup(name, data);
|
|
};
|
|
|
|
export const scheduleStartupReports = (): void => {
|
|
if (!isDevelopment || reportTimers.length > 0) return;
|
|
reportTimers = [3000, 10000].map((delayMs) =>
|
|
setTimeout(() => {
|
|
const elapsedMs = Date.now() - startedAt;
|
|
console.log(`[STARTUP PERF REPORT] t+${elapsedMs}ms`);
|
|
for (const entry of marks) {
|
|
console.log(
|
|
` ${entry.name} +${entry.elapsedMs}ms${serialize(entry.data)}`,
|
|
);
|
|
}
|
|
}, delayMs),
|
|
);
|
|
};
|
|
|
|
export const isStartupScanActive = (windowMs = 15000): boolean =>
|
|
isDevelopment && Date.now() - startedAt <= windowMs;
|
|
|
|
markStartupOnce("scanner-loaded", "scanner module loaded");
|