Files
Curse/.github/workflows/get-backend-memory.yml
2025-12-03 04:05:29 +00:00

148 lines
4.9 KiB
YAML

# this name is used in report-backend-memory.yml so be careful when change name
name: Get backend memory usage
on:
pull_request:
branches:
- master
- develop
paths:
- packages/backend/**
- packages/misskey-js/**
- .github/workflows/get-backend-memory.yml
jobs:
get-memory-usage:
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
matrix:
memory-json-name: [memory-base.json, memory-head.json]
include:
- memory-json-name: memory-base.json
ref: ${{ github.base_ref }}
- memory-json-name: memory-head.json
ref: refs/pull/${{ github.event.number }}/merge
services:
postgres:
image: postgres:18
ports:
- 54312:5432
env:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:7
ports:
- 56312:6379
steps:
- uses: actions/checkout@v4.3.0
with:
ref: ${{ matrix.ref }}
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
- name: Use Node.js
uses: actions/setup-node@v4.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure
run: cp .github/misskey/test.yml .config/default.yml
- name: Build
run: pnpm build
- name: Run migrations
run: pnpm --filter backend migrate
- name: Measure memory usage
run: |
# Inline script to start the server and measure memory usage
# This is inlined to work with both base and head refs
node --input-type=module -e '
import { fork } from "node:child_process";
import { setTimeout } from "node:timers/promises";
import { readFile } from "node:fs/promises";
import { execSync } from "node:child_process";
const STARTUP_TIMEOUT = 120000;
const MEMORY_SETTLE_TIME = 10000;
async function measureMemory() {
const serverProcess = fork("./packages/backend/built/boot/entry.js", [], {
cwd: process.cwd(),
env: { ...process.env, NODE_ENV: "test" },
stdio: ["pipe", "pipe", "pipe", "ipc"],
});
let serverReady = false;
serverProcess.on("message", (msg) => { if (msg === "ok") serverReady = true; });
serverProcess.stdout?.on("data", (d) => process.stderr.write("[server] " + d));
serverProcess.stderr?.on("data", (d) => process.stderr.write("[server] " + d));
serverProcess.on("error", (e) => process.stderr.write("[error] " + e + "\n"));
const start = Date.now();
while (!serverReady) {
if (Date.now() - start > STARTUP_TIMEOUT) {
serverProcess.kill("SIGTERM");
throw new Error("Server startup timeout");
}
await setTimeout(100);
}
const startupTime = Date.now() - start;
process.stderr.write("Server started in " + startupTime + "ms\n");
await setTimeout(MEMORY_SETTLE_TIME);
const pid = serverProcess.pid;
let memoryInfo;
try {
const status = await readFile("/proc/" + pid + "/status", "utf-8");
const rss = status.match(/VmRSS:\s+(\d+)\s+kB/);
memoryInfo = { rss: rss ? parseInt(rss[1], 10) * 1024 : null };
} catch {
try {
const ps = execSync("ps -o rss= -p " + pid, { encoding: "utf-8" });
memoryInfo = { rss: parseInt(ps.trim(), 10) * 1024 };
} catch {
memoryInfo = { rss: null, error: "Could not measure memory" };
}
}
serverProcess.kill("SIGTERM");
let exited = false;
await new Promise((resolve) => {
serverProcess.on("exit", () => { exited = true; resolve(); });
setTimeout(10000).then(() => { if (!exited) serverProcess.kill("SIGKILL"); resolve(); });
});
console.log(JSON.stringify({ timestamp: new Date().toISOString(), startupTimeMs: startupTime, memory: memoryInfo }, null, 2));
}
measureMemory().catch((e) => { console.error(JSON.stringify({ error: e.message })); process.exit(1); });
' > ${{ matrix.memory-json-name }}
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: memory-artifact-${{ matrix.memory-json-name }}
path: ${{ matrix.memory-json-name }}
save-pr-number:
runs-on: ubuntu-latest
permissions: {}
steps:
- name: Save PR number
env:
PR_NUMBER: ${{ github.event.number }}
run: |
echo "$PR_NUMBER" > ./pr_number
- uses: actions/upload-artifact@v4
with:
name: memory-artifact-pr-number
path: pr_number