-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathperf.js
More file actions
59 lines (52 loc) · 1.78 KB
/
perf.js
File metadata and controls
59 lines (52 loc) · 1.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
const SAMPLES_PER_METRIC = 60
const LOG_EVERY_N = 20
const metrics = new Map()
const nowMs = () => (typeof performance !== 'undefined' ? performance.now() : Date.now())
const isEnabled = () => {
if (typeof window === 'undefined') { return false }
if (window.__perfMetrics === true) { return true }
try {
return localStorage.getItem('wiredove.perf') === '1'
} catch {
return false
}
}
const percentile = (values, p) => {
if (!values.length) { return 0 }
const sorted = [...values].sort((a, b) => a - b)
const idx = Math.min(sorted.length - 1, Math.max(0, Math.floor((sorted.length - 1) * p)))
return sorted[idx]
}
const pushMetric = (name, duration) => {
const record = metrics.get(name) || { values: [], count: 0 }
record.values.push(duration)
if (record.values.length > SAMPLES_PER_METRIC) {
record.values.shift()
}
record.count += 1
metrics.set(name, record)
if (record.count % LOG_EVERY_N !== 0) { return }
const p50 = percentile(record.values, 0.5)
const p95 = percentile(record.values, 0.95)
const avg = record.values.reduce((sum, value) => sum + value, 0) / record.values.length
console.log(`[perf] ${name} n=${record.values.length} avg=${avg.toFixed(1)}ms p50=${p50.toFixed(1)}ms p95=${p95.toFixed(1)}ms`)
}
export const perfStart = (name, detail = '') => {
if (!isEnabled()) { return null }
return { name, detail, t0: nowMs() }
}
export const perfEnd = (token) => {
if (!token || !token.name) { return 0 }
const duration = nowMs() - token.t0
const metricName = token.detail ? `${token.name}:${token.detail}` : token.name
pushMetric(metricName, duration)
return duration
}
export const perfMeasure = async (name, fn, detail = '') => {
const token = perfStart(name, detail)
try {
return await fn()
} finally {
perfEnd(token)
}
}