This commit is contained in:
syuilo 2026-06-25 21:41:02 +09:00
commit b161cf57bb
8 changed files with 37 additions and 32 deletions

View file

@ -13,16 +13,17 @@ import { gzipSync } from 'node:zlib';
import * as fs from 'node:fs/promises';
import * as fsSync from 'node:fs';
import * as http from 'node:http';
import * as util from './utility.mts';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const [repoDirArg, outputFileArg] = process.argv.slice(2);
const STARTUP_TIMEOUT = readIntegerEnv('MK_JS_FOOTPRINT_STARTUP_TIMEOUT_MS', 120000, 1);
const SETTLE_TIME = readIntegerEnv('MK_JS_FOOTPRINT_SETTLE_TIME_MS', 10000, 0);
const REQUEST_COUNT = readIntegerEnv('MK_JS_FOOTPRINT_REQUEST_COUNT', 10, 0);
const MAX_TABLE_ITEMS = readIntegerEnv('MK_JS_FOOTPRINT_MAX_ITEMS', 20, 1);
const STARTUP_TIMEOUT = util.readIntegerEnv('MK_JS_FOOTPRINT_STARTUP_TIMEOUT_MS', 120000, 1);
const SETTLE_TIME = util.readIntegerEnv('MK_JS_FOOTPRINT_SETTLE_TIME_MS', 10000, 0);
const REQUEST_COUNT = util.readIntegerEnv('MK_JS_FOOTPRINT_REQUEST_COUNT', 10, 0);
const MAX_TABLE_ITEMS = util.readIntegerEnv('MK_JS_FOOTPRINT_MAX_ITEMS', 20, 1);
const repoDir = resolve(repoDirArg);
const outputFile = resolve(outputFileArg);

View file

@ -5,7 +5,7 @@
import { readFile, writeFile } from 'node:fs/promises';
import * as util from './utility.mts';
import { heapSnapshotCategories, type MemoryReport } from './measure-backend-memory-comparison.mts';
import { type MemoryReport } from './measure-backend-memory-comparison.mts';
const [baseFile, headFile, outputFile, baseJsFootprintFile, headJsFootprintFile] = process.argv.slice(2);
@ -190,12 +190,12 @@ function formatPlainDelta(baseValue: number, headValue: number, formatter = util
return `${sign}${formatter(Math.abs(delta))}`;
}
function getHeapSnapshotCategoryValue(report: MemoryReport, phase: typeof memoryReportPhases[number]['key'], category: typeof heapSnapshotCategories[number]) {
function getHeapSnapshotCategoryValue(report: MemoryReport, phase: typeof memoryReportPhases[number]['key'], category: typeof util.heapSnapshotCategories[number]) {
const value = report.summary[phase]?.heapSnapshot?.categories?.[category];
return Number.isFinite(value) ? value : null;
}
function getHeapSnapshotCategoryValueFromSample(sample: MemoryReport['samples'][number], phase: typeof memoryReportPhases[number]['key'], category: typeof heapSnapshotCategories[number]) {
function getHeapSnapshotCategoryValueFromSample(sample: MemoryReport['samples'][number], phase: typeof memoryReportPhases[number]['key'], category: typeof util.heapSnapshotCategories[number]) {
const value = sample.phases[phase]?.heapSnapshot?.categories?.[category];
return Number.isFinite(value) ? value : null;
}
@ -222,7 +222,7 @@ function renderHeapSnapshotSankey(report: MemoryReport, phase: typeof memoryRepo
const total = getHeapSnapshotCategoryValue(report, phase, 'Total');
if (total == null || total <= 0) return null;
function getHeapSnapshotBreakdownEntries(category: typeof heapSnapshotCategories[number]) {
function getHeapSnapshotBreakdownEntries(category: typeof util.heapSnapshotCategories[number]) {
const breakdown = report.summary[phase].heapSnapshot?.breakdowns?.[category];
if (breakdown == null || typeof breakdown !== 'object') return [];
@ -231,7 +231,7 @@ function renderHeapSnapshotSankey(report: MemoryReport, phase: typeof memoryRepo
.toSorted((a, b) => b[1] - a[1]);
}
const categories = heapSnapshotCategories
const categories = util.heapSnapshotCategories
.filter(category => category !== 'Total')
.map(category => {
const value = getHeapSnapshotCategoryValue(report, phase, category);
@ -315,7 +315,7 @@ function renderHeapSnapshotSankey(report: MemoryReport, phase: typeof memoryRepo
return lines.join('\n');
}
function pairedHeapSnapshotDeltaSummary(base: MemoryReport, head: MemoryReport, phase: typeof memoryReportPhases[number]['key'], category: typeof heapSnapshotCategories[number]) {
function pairedHeapSnapshotDeltaSummary(base: MemoryReport, head: MemoryReport, phase: typeof memoryReportPhases[number]['key'], category: typeof util.heapSnapshotCategories[number]) {
const baseSamplesByRound = getSamplesByRound(base);
const headSamplesByRound = getSamplesByRound(head);
const values = [] as number[];
@ -356,7 +356,7 @@ function renderHeapSnapshotTable(base: MemoryReport, head: MemoryReport, phase:
return `**${category}**<br>${basePercent}${headPercent}`;
}
function getHeapSnapshotSampleSpread(report: MemoryReport, phase: typeof memoryReportPhases[number]['key'], category: typeof heapSnapshotCategories[number]) {
function getHeapSnapshotSampleSpread(report: MemoryReport, phase: typeof memoryReportPhases[number]['key'], category: typeof util.heapSnapshotCategories[number]) {
const values = report.samples
.map(sample => getHeapSnapshotCategoryValueFromSample(sample, phase, category))
.filter(value => Number.isFinite(value)) as number[];
@ -366,7 +366,7 @@ function renderHeapSnapshotTable(base: MemoryReport, head: MemoryReport, phase:
return util.median(values.map(value => Math.abs(value - center)));
}
for (const category of heapSnapshotCategories) {
for (const category of util.heapSnapshotCategories) {
const baseValue = getHeapSnapshotCategoryValue(base, phase, category);
const headValue = getHeapSnapshotCategoryValue(head, phase, category);
if (baseValue == null || headValue == null) continue;

View file

@ -10,16 +10,6 @@ import * as util from './utility.mts';
import type { MemoryReportRaw } from '../../packages/backend/scripts/measure-memory.mts';
const phases = ['afterGc'] as const;
export const heapSnapshotCategories = [
'Total',
'Code',
'Strings',
'JS arrays',
'Typed arrays',
'System objects',
'Other JS objects',
'Other non-JS objects',
] as const;
export type MemoryReport = {
timestamp: string;
@ -39,9 +29,9 @@ export type MemoryReport = {
summary: Record<typeof phases[number], {
memoryUsage: Record<string, number>;
heapSnapshot?: {
categories: Record<typeof heapSnapshotCategories[number], number>;
nodeCounts: Record<typeof heapSnapshotCategories[number], number>;
breakdowns?: Record<typeof heapSnapshotCategories[number], Record<string, number>>;
categories: Record<typeof util.heapSnapshotCategories[number], number>;
nodeCounts: Record<typeof util.heapSnapshotCategories[number], number>;
breakdowns?: Record<typeof util.heapSnapshotCategories[number], Record<string, number>>;
};
}>;
samples: (MemoryReportRaw['samples'][number] & {
@ -82,9 +72,9 @@ async function resetState(repoDir: string) {
}
function summarizeHeapSnapshotBreakdowns(samples: MemoryReport['samples'], phase: typeof phases[number]) {
const breakdowns = {} as Record<typeof heapSnapshotCategories[number], Record<string, number>>;
const breakdowns = {} as Record<typeof util.heapSnapshotCategories[number], Record<string, number>>;
for (const category of heapSnapshotCategories) {
for (const category of util.heapSnapshotCategories) {
if (category === 'Total') continue;
const childKeys = new Set<string>();
@ -144,8 +134,8 @@ function summarizeSamples(samples: MemoryReport['samples']) {
summary[phase].memoryUsage[key] = util.median(values);
}
const heapSnapshotCategoryValues = {} as Record<typeof heapSnapshotCategories[number], number>;
for (const category of heapSnapshotCategories) {
const heapSnapshotCategoryValues = {} as Record<typeof util.heapSnapshotCategories[number], number>;
for (const category of util.heapSnapshotCategories) {
const values = samples
.map(sample => sample.phases[phase].heapSnapshot?.categories?.[category])
.filter(value => Number.isFinite(value)) as number[];
@ -153,8 +143,8 @@ function summarizeSamples(samples: MemoryReport['samples']) {
if (values.length > 0) heapSnapshotCategoryValues[category] = util.median(values);
}
const heapSnapshotNodeCountValues = {} as Record<typeof heapSnapshotCategories[number], number>;
for (const category of heapSnapshotCategories) {
const heapSnapshotNodeCountValues = {} as Record<typeof util.heapSnapshotCategories[number], number>;
for (const category of util.heapSnapshotCategories) {
const values = samples
.map(sample => sample.phases[phase].heapSnapshot?.nodeCounts?.[category])
.filter(value => Number.isFinite(value)) as number[];

View file

@ -7,6 +7,17 @@ import { spawn } from 'node:child_process';
import { promises as fs } from 'node:fs';
import path from 'node:path';
export const heapSnapshotCategories = [
'Total',
'Code',
'Strings',
'JS arrays',
'Typed arrays',
'System objects',
'Other JS objects',
'Other non-JS objects',
] as const;
export function median(values: number[]) {
const sorted = values.toSorted((a, b) => a - b);
const center = Math.floor(sorted.length / 2);

View file

@ -25,6 +25,7 @@ on:
- pnpm-lock.yaml
- pnpm-workspace.yaml
- .node-version
- .github/scripts/utility.mts
- .github/scripts/frontend-js-size.mts
- .github/workflows/frontend-bundle-report.yml
- .github/workflows/frontend-bundle-report-comment.yml

View file

@ -20,6 +20,7 @@ on:
- pnpm-lock.yaml
- pnpm-workspace.yaml
- .node-version
- .github/scripts/utility.mts
- .github/scripts/frontend-js-size.mts
- .github/workflows/frontend-bundle-report.yml
- .github/workflows/frontend-bundle-report-comment.yml

View file

@ -9,6 +9,7 @@ on:
paths:
- packages/backend/**
- packages/misskey-js/**
- .github/scripts/utility.mts
- .github/scripts/backend-memory-report.mts
- .github/scripts/measure-backend-memory-comparison.mts
- .github/scripts/backend-js-footprint.mjs

View file

@ -1 +1 @@
22.15.0
22.18.0