vue3-core/benchmark/client/profiling.ts

80 lines
1.9 KiB
TypeScript

/* eslint-disable no-console */
/* eslint-disable no-restricted-syntax */
/* eslint-disable no-restricted-globals */
declare module globalThis {
let doProfile: boolean
let recordTime: boolean
let times: Record<string, number[]>
}
globalThis.recordTime = true
globalThis.doProfile = false
export const defer = () => new Promise(r => requestIdleCallback(r))
const times: Record<string, number[]> = (globalThis.times = {})
export function wrap(
id: string,
fn: (...args: any[]) => any,
): (...args: any[]) => Promise<void> {
return async (...args) => {
if (!globalThis.recordTime) {
return fn(...args)
}
document.body.classList.remove('done')
const { doProfile } = globalThis
await defer()
doProfile && console.profile(id)
const start = performance.now()
fn(...args)
await defer()
const time = performance.now() - start
const prevTimes = times[id] || (times[id] = [])
prevTimes.push(time)
const { min, max, median, mean, std } = compute(prevTimes)
const msg =
`${id}: min: ${min} / ` +
`max: ${max} / ` +
`median: ${median}ms / ` +
`mean: ${mean}ms / ` +
`time: ${time.toFixed(2)}ms / ` +
`std: ${std} ` +
`over ${prevTimes.length} runs`
doProfile && console.profileEnd(id)
console.log(msg)
const timeEl = document.getElementById('time')!
timeEl.textContent = msg
document.body.classList.add('done')
}
}
function compute(array: number[]) {
const n = array.length
const max = Math.max(...array)
const min = Math.min(...array)
const mean = array.reduce((a, b) => a + b) / n
const std = Math.sqrt(
array.map(x => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n,
)
const median = array.slice().sort((a, b) => a - b)[Math.floor(n / 2)]
return {
max: round(max),
min: round(min),
mean: round(mean),
std: round(std),
median: round(median),
}
}
function round(n: number) {
return +n.toFixed(2)
}