Skip to content

Commit

Permalink
workflow: add quick benchmark (#266)
Browse files Browse the repository at this point in the history
  • Loading branch information
sxzz committed Aug 6, 2024
1 parent 669c295 commit 25f8502
Show file tree
Hide file tree
Showing 19 changed files with 747 additions and 103 deletions.
1 change: 1 addition & 0 deletions benchmark/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
results/*
10 changes: 6 additions & 4 deletions playground/src/bench/App.vue → benchmark/client/App.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<script setup lang="ts">
import { ref, shallowRef } from 'vue'
<script setup lang="ts" vapor>
import { ref, shallowRef } from '@vue/vapor'
import { buildData } from './data'
import { defer, wrap } from './profiling'
const isVapor = !!import.meta.env.IS_VAPOR
const selected = ref<number>()
const rows = shallowRef<
{
Expand Down Expand Up @@ -75,14 +77,14 @@ async function bench() {
</script>

<template>
<h1>Vue.js Vapor Benchmark</h1>
<h1>Vue.js ({{ isVapor ? 'Vapor' : 'Virtual DOM' }}) Benchmark</h1>
<div
id="control"
style="display: flex; flex-direction: column; width: fit-content; gap: 6px"
>
<button @click="bench">Benchmark mounting</button>
<button id="run" @click="run">Create 1,000 rows</button>
<button id="runlots" @click="runLots">Create 10,000 rows</button>
<button id="runLots" @click="runLots">Create 10,000 rows</button>
<button id="add" @click="add">Append 1,000 rows</button>
<button id="update" @click="update">Update every 10th row</button>
<button id="clear" @click="clear">Clear</button>
Expand Down
File renamed without changes.
17 changes: 17 additions & 0 deletions benchmark/client/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue Vapor Benchmark</title>
<style>
html {
color-scheme: light dark;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="./index.ts"></script>
</body>
</html>
5 changes: 5 additions & 0 deletions benchmark/client/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
if (import.meta.env.IS_VAPOR) {
import('./vapor')
} else {
import('./vdom')
}
79 changes: 79 additions & 0 deletions benchmark/client/profiling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* 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)
}
4 changes: 4 additions & 0 deletions benchmark/client/vapor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { createVaporApp } from '@vue/vapor'
import App from './App.vue'

createVaporApp(App as any).mount('#app')
4 changes: 4 additions & 0 deletions benchmark/client/vdom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
Loading

0 comments on commit 25f8502

Please sign in to comment.