()
| 495 | } |
| 496 | |
| 497 | async function main() { |
| 498 | const options = parseArgs(process.argv.slice(2)); |
| 499 | const port = await reserveLoopbackPort(); |
| 500 | const scratch = mkdtempSync(join(tmpdir(), "hunk-daemon-memory-")); |
| 501 | const child = Bun.spawn([process.execPath, "src/main.tsx", "daemon", "serve"], { |
| 502 | cwd: process.cwd(), |
| 503 | env: { |
| 504 | ...process.env, |
| 505 | HUNK_MCP_HOST: "127.0.0.1", |
| 506 | HUNK_MCP_PORT: String(port), |
| 507 | HUNK_CONFIG_HOME: scratch, |
| 508 | HUNK_NO_UPDATE_CHECK: "1", |
| 509 | }, |
| 510 | stdout: "pipe", |
| 511 | stderr: "pipe", |
| 512 | }); |
| 513 | |
| 514 | const samples: MemorySample[] = []; |
| 515 | |
| 516 | try { |
| 517 | const health = await waitUntil("daemon health", () => readHealth(port), 10_000); |
| 518 | const pid = health.pid; |
| 519 | console.log(`daemon pid=${pid} port=${port}`); |
| 520 | samples.push(await sample("startup", 0, pid, port)); |
| 521 | |
| 522 | for (let cycle = 1; cycle <= options.cycles; cycle += 1) { |
| 523 | const sockets: WebSocket[] = []; |
| 524 | const sessionIds = Array.from( |
| 525 | { length: options.sessionsPerCycle }, |
| 526 | (_, sessionIndex) => `memory-${cycle}-${sessionIndex}`, |
| 527 | ); |
| 528 | |
| 529 | for (let sessionIndex = 0; sessionIndex < sessionIds.length; sessionIndex += 1) { |
| 530 | sockets.push( |
| 531 | await openRegisteredSocket(port, sessionIds[sessionIndex]!, cycle, sessionIndex, options), |
| 532 | ); |
| 533 | } |
| 534 | |
| 535 | await waitUntil("session registration", async () => { |
| 536 | const nextHealth = await readHealth(port); |
| 537 | return nextHealth?.sessions === options.sessionsPerCycle ? nextHealth : null; |
| 538 | }); |
| 539 | await sendSnapshotUpdates(sockets, sessionIds, options.snapshotUpdatesPerCycle, options); |
| 540 | await exerciseSessionApi(port, sessionIds, options.apiRequestsPerCycle); |
| 541 | samples.push(await sample("live", cycle, pid, port)); |
| 542 | |
| 543 | await closeSockets(sockets); |
| 544 | await waitUntil("session cleanup", async () => { |
| 545 | const nextHealth = await readHealth(port); |
| 546 | return nextHealth?.sessions === 0 ? nextHealth : null; |
| 547 | }); |
| 548 | await Bun.sleep(options.settleMs); |
| 549 | const cleanupSample = await sample("cleanup", cycle, pid, port); |
| 550 | samples.push(cleanupSample); |
| 551 | |
| 552 | console.log( |
| 553 | `cycle=${cycle.toString().padStart(3)} cleanup_rss=${formatBytes(cleanupSample.rssBytes)} ` + |
| 554 | `heap=${formatBytes(cleanupSample.heapBytes)} hwm=${formatBytes(cleanupSample.highWaterRssBytes)}`, |
no test coverage detected