89 lines
3.0 KiB
JavaScript
89 lines
3.0 KiB
JavaScript
import test from 'brittle'
|
|
import { readFile } from 'node:fs/promises'
|
|
import { createContext, runInContext } from 'node:vm'
|
|
import { dirname, join } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
const helpersPath = join(__dirname, '../lib/baretop/baretop-ui-helpers.js')
|
|
const composePath = join(__dirname, '../lib/baretop/baretop-compose.js')
|
|
const largeProcPath = join(__dirname, 'fixtures/baretop-large-process-table.json')
|
|
const largeNetPath = join(__dirname, 'fixtures/baretop-large-net-summary.json')
|
|
|
|
function pctl(samples, p) {
|
|
const sorted = samples.slice().sort((a, b) => a - b)
|
|
if (!sorted.length) return 0
|
|
const idx = Math.max(
|
|
0,
|
|
Math.min(sorted.length - 1, Math.floor((p / 100) * (sorted.length - 1)))
|
|
)
|
|
return sorted[idx]
|
|
}
|
|
|
|
test('baretop perf baseline emits KPI envelope', async (t) => {
|
|
const helpers = await readFile(helpersPath, 'utf8')
|
|
const compose = await readFile(composePath, 'utf8')
|
|
const proc = JSON.parse(await readFile(largeProcPath, 'utf8'))
|
|
const net = JSON.parse(await readFile(largeNetPath, 'utf8'))
|
|
const ctx = createContext({})
|
|
runInContext(helpers + '\n' + compose, ctx)
|
|
|
|
const composeSamples = []
|
|
const emitSamples = []
|
|
const emitBytes = []
|
|
const dropRatio = []
|
|
const fetchSamples = []
|
|
|
|
for (let i = 0; i < 40; i++) {
|
|
const t0 = Date.now()
|
|
const rows = ctx.bareTopSortProcessRows(
|
|
ctx.bareTopProcessRowsFromTable(proc),
|
|
'cpu',
|
|
false,
|
|
{ sortWallMs: 1000 }
|
|
)
|
|
const netLines = ctx.bareTopNetTabLines(net, 120, { maxLines: 220 })
|
|
const frame = ['baretop-perf-baseline', 'rows=' + rows.length].concat(netLines)
|
|
const composeMs = Date.now() - t0
|
|
composeSamples.push(composeMs)
|
|
fetchSamples.push(5 + (i % 4))
|
|
const e0 = Date.now()
|
|
const emit = ctx.bareTopEmitFrame(
|
|
{},
|
|
{ write() {} },
|
|
frame.join('\r\n'),
|
|
{
|
|
prevLines: null,
|
|
rows: 40,
|
|
cols: 120,
|
|
incrementalFrameDiff: false,
|
|
useLineHash: false,
|
|
fullscreenPanel: false,
|
|
cup: (r, c) => `\\x1b[${r};${c}H`
|
|
}
|
|
)
|
|
emitSamples.push(Date.now() - e0)
|
|
emitBytes.push(emit.wrotePatch ? emit.patchLen : frame.join('\r\n').length)
|
|
dropRatio.push(0)
|
|
}
|
|
|
|
const kpi = {
|
|
fetchMs: { p50: pctl(fetchSamples, 50), p95: pctl(fetchSamples, 95) },
|
|
composeMs: { p50: pctl(composeSamples, 50), p95: pctl(composeSamples, 95) },
|
|
emitMs: { p50: pctl(emitSamples, 50), p95: pctl(emitSamples, 95) },
|
|
emitBytes: { p50: pctl(emitBytes, 50), p95: pctl(emitBytes, 95) },
|
|
droppedRefreshPct: {
|
|
p50: pctl(dropRatio, 50),
|
|
p95: pctl(dropRatio, 95)
|
|
}
|
|
}
|
|
|
|
t.ok(kpi.fetchMs.p50 >= 0)
|
|
t.ok(kpi.composeMs.p95 >= kpi.composeMs.p50)
|
|
t.ok(kpi.emitBytes.p95 >= kpi.emitBytes.p50)
|
|
t.ok(kpi.droppedRefreshPct.p50 >= 0)
|
|
t.ok(kpi.composeMs.p95 <= 30, 'compose p95 budget <= 30ms')
|
|
t.ok(kpi.emitMs.p95 <= 15, 'emit p95 budget <= 15ms')
|
|
t.ok(kpi.fetchMs.p95 <= 12, 'fetch p95 budget <= 12ms')
|
|
})
|