Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

misc: fix benchmark script #44592

Merged
merged 2 commits into from
Jan 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 41 additions & 7 deletions bench/vercel/bench.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,24 @@ import console from 'console'
import chalk from 'chalk'

import PQueue from 'p-queue'
import { generateProjects, cleanupProjectFolders } from './project-utils.js'
import {
generateProjects,
cleanupProjectFolders,
TEST_PROJECT_NAME,
} from './project-utils.js'
import { printBenchmarkResults } from './chart.js'
import { genRetryableRequest } from './gen-request.js'

const program = new Command()

const queue = new PQueue({ concurrency: 25 })
const TTFB_OUTLIERS_THRESHOLD = 250
const queue = new PQueue({ concurrency: 50 })
const TTFB_OUTLIERS_THRESHOLD = 1500

let progress = 0

program.option('-p, --path <path>')
program.option('-s, --skip-build', 'Skip build step')
program.option('-f, --force-crash', 'Force function crash')

program.parse(process.argv)

Expand All @@ -23,8 +31,23 @@ if (options.path) {
console.log('Running benchmark for path: ', options.path)
}

if (options.skipBuild) {
console.log('Skipping build step')
}

if (options.forceCrash) {
console.log('Forcing function crash')
}

export const forceCrash = options.forceCrash

try {
const [originDeploymentURL, headDeploymentURL] = await generateProjects()
const [originDeploymentURL, headDeploymentURL] = options.skipBuild
? [
`https://${TEST_PROJECT_NAME}-origin.vercel.app`,
`https://${TEST_PROJECT_NAME}-head.vercel.app`,
]
: await generateProjects()

const originBenchmarkURL = `${originDeploymentURL}${options.path || ''}`
const headBenchmarkURL = `${headDeploymentURL}${options.path || ''}`
Expand Down Expand Up @@ -60,11 +83,22 @@ try {
}

async function runBenchmark(url) {
progress = 0
process.stdout.write(`Sending requests to ${url} ...\n`)
process.stdout.write(`Progress: ${++progress}/500`)
return (
await Promise.all(
Array.from({ length: 500 }).map(() =>
queue.add(() => genRetryableRequest(url))
)
Array.from({ length: 500 }).map(async () => {
const p = await queue.add(() => genRetryableRequest(url))
refreshProgress()
return p
})
)
).filter(Boolean)
}

function refreshProgress() {
process.stdout.clearLine()
process.stdout.cursorTo(0)
process.stdout.write(`Requests sent: ${++progress}/500`)
}
4 changes: 0 additions & 4 deletions bench/vercel/benchmark-app/app/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,3 @@ export default function Root({ children }) {
</html>
)
}

export const config = {
runtime: 'experimental-edge',
}
22 changes: 14 additions & 8 deletions bench/vercel/benchmark-app/app/rsc/page.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import * as React from 'react'
import { cookies } from 'next/headers'

// if (!('hot' in Math)) Math.hot = false
if (!('hot' in Math)) Math.hot = false

export default function page() {
// const previous = Math.hot
// Math.hot = true
// return <div>{previous ? 'HOT' : 'COLD'}</div>
return <div>hello</div>
}
// make the page dynamic
cookies()
const previous = Math.hot
Math.hot = true

// crash the server after responding
if (process.env.CRASH_FUNCTION) {
setTimeout(() => {
throw new Error('crash')
}, 500)
}

export const config = {
runtime: 'experimental-edge',
return <div>{previous ? 'HOT' : 'COLD'}</div>
}
11 changes: 7 additions & 4 deletions bench/vercel/benchmark-app/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ export async function getServerSideProps() {
const wasHot = Math.hot
Math.hot = true

// crash the server after responding
if (process.env.CRASH_FUNCTION) {
setTimeout(() => {
throw new Error('crash')
}, 700)
}

return {
props: {
hot: wasHot,
},
}
}

export const config = {
runtime: 'experimental-edge',
}
5 changes: 5 additions & 0 deletions bench/vercel/chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ export function printBenchmarkResults({ origin, head }, metricSelector) {
(results) => results.map(metricSelector).filter(Boolean)
)

if (processedHeadData.length === 0 || processedOriginData.length === 0) {
console.log('No data to compare, skipping')
return
}

const [originMetrics, headMetrics] = [
processedOriginData,
processedHeadData,
Expand Down
6 changes: 4 additions & 2 deletions bench/vercel/gen-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import timer from '@szmarczak/http-timer'
// a wrapper around genAsyncRequest that will retry the request 5 times if it fails
export async function genRetryableRequest(url) {
let retries = 0
while (retries < 5) {
while (retries < 10) {
try {
return await genAsyncRequest(url)
} catch (err) {}
retries++
await new Promise((r) => setTimeout(r, 1000))
}
throw new Error(`Failed to fetch ${url}, too many retries`)
}
Expand All @@ -25,6 +24,9 @@ async function genAsyncRequest(url) {
body += data
})
response.on('end', () => {
if (response.statusCode !== 200) {
reject(new Error(`Failed to fetch ${url}`))
}
resolve({
...response.timings.phases,
cold: !body.includes('HOT'),
Expand Down
4 changes: 2 additions & 2 deletions bench/vercel/generate-package-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ async function getCurrentRootReactPackagesVersions() {
await fs.readFile('../../package.json', 'utf8')
)
return {
react: packageJson.devDependencies['react-exp'],
'react-dom': packageJson.devDependencies['react-dom-exp'],
react: packageJson.devDependencies['react'],
'react-dom': packageJson.devDependencies['react-dom'],
}
}
4 changes: 3 additions & 1 deletion bench/vercel/project-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import path from 'path'
import url from 'url'
import { generatePackageJson } from './generate-package-json.js'
import { Listr } from 'listr2'
import { forceCrash } from './bench.js'

config()

const TEST_PROJECT_NAME = process.env.VERCEL_TEST_PROJECT_NAME
export const TEST_PROJECT_NAME = process.env.VERCEL_TEST_PROJECT_NAME
const ORIGIN_PROJECT_NAME = TEST_PROJECT_NAME + '-origin'
const HEAD_PROJECT_NAME = TEST_PROJECT_NAME + '-head'

Expand Down Expand Up @@ -197,6 +198,7 @@ export async function deployProject(projectName, appFolder) {
: []),
'--force',
...vercelFlags,
...(forceCrash ? ['--env', 'CRASH_FUNCTION=1'] : []),
],
{
cwd: appFolder,
Expand Down