Use the 95th percentile for startup capacity

This commit is contained in:
2026-10-08 11:36:57 -04:00
parent 8863e8a882
commit a33b897cd0
3 changed files with 26 additions and 9 deletions
+19 -3
View File
@@ -196,13 +196,29 @@ describe('measured instance capacity', () => {
expect(db().prepare('SELECT * FROM ec_instance_resource_samples').all()).toHaveLength(1);
expect(capacityCalibration(hostId).running.source).toBe('bootstrap');
});
it('uses a running percentile and startup peaks without padding, keeping admission reads cached', async () => {
for (let minute = 0; minute < 100; minute++) await report(minute, { cpuCores: minute === 0 ? 2 : 0.1 });
it.each(['startup', 'running'] as const)('uses the %s 95th percentile for CPU and memory, keeping admission reads cached', async phase => {
await learned();
// Repeated starts or running observations include isolated CPU and
// memory outliers in different minutes; neither should set the allowance.
const uptimeSeconds = phase === 'startup' ? 60 : 600;
for (let minute = 25; minute < 125; minute++) await report(minute, {
uptimeSeconds, cpuCores: minute === 25 ? 2 : 0.4, memoryBytes: minute === 26 ? 3 * GiB : GiB / 2
});
const { db } = await import('../../src/lib/server/db/index.js');
const { capacityCalibration } = await import('../../src/lib/server/hosts/calibration.js');
const prepare = vi.spyOn(db(), 'prepare');
expect(capacityCalibration(hostId).running.cpuCores).toBe(0.1);
expect(capacityCalibration(hostId)[phase]).toMatchObject({ source: 'host', cpuCores: 0.4, memoryBytes: GiB / 2 });
expect(capacityCalibration('new-host')[phase]).toMatchObject({ source: 'fleet', cpuCores: 0.4, memoryBytes: GiB / 2 });
expect(prepare.mock.calls.some(([sql]) => sql.includes('ec_instance_resource_samples'))).toBe(false);
prepare.mockRestore();
// Both phases still raise immediately for fresh spikes, hold that value
// within the minute, then return to P95 on the next recalculation.
await report(124.25, { uptimeSeconds, cpuCores: 3, memoryBytes: 2 * GiB });
expect(capacityCalibration(hostId)[phase]).toMatchObject({ cpuCores: 3, memoryBytes: 2 * GiB });
await report(124.5, { uptimeSeconds, cpuCores: 0.4, memoryBytes: GiB / 2 });
expect(capacityCalibration(hostId)[phase]).toMatchObject({ cpuCores: 3, memoryBytes: 2 * GiB });
await report(125, { uptimeSeconds, cpuCores: 0.4, memoryBytes: GiB / 2 });
expect(capacityCalibration(hostId)[phase]).toMatchObject({ cpuCores: 0.4, memoryBytes: GiB / 2 });
});
});