Skip to content

Commit

Permalink
Merge branch 'main' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy committed Nov 6, 2024
2 parents c280655 + e10b03e commit 7db86cf
Show file tree
Hide file tree
Showing 62 changed files with 1,232 additions and 659 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/continuous_benchmark.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Continuous benchmark

on:
workflow_dispatch:
pull_request:
branches:
- main
push:
branches:
- main

env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
FORCE_COLOR: true
CODSPEED_TOKEN: ${{ secrets.CODSPEED_TOKEN }}
CODSPEED: true

jobs:
codspeed:
if: ${{ github.repository_owner == 'withastro' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Setup PNPM
uses: pnpm/action-setup@v3

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
cache: "pnpm"

- name: Install dependencies
run: pnpm install

- name: Build
run: pnpm run build

- name: Run the benchmarks
uses: CodSpeedHQ/action@fa1dcde8d58f2ab0b407a6a24d6cc5a8c1444a8c # v3.1.0
timeout-minutes: 30
with:
run: pnpm benchmark codspeed

2 changes: 1 addition & 1 deletion benchmark/bench/_util.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const astroBin = path.resolve(astroPkgPath, '../astro.js');
export function calculateStat(numbers) {
const avg = numbers.reduce((a, b) => a + b, 0) / numbers.length;
const stdev = Math.sqrt(
numbers.map((x) => Math.pow(x - avg, 2)).reduce((a, b) => a + b, 0) / numbers.length
numbers.map((x) => Math.pow(x - avg, 2)).reduce((a, b) => a + b, 0) / numbers.length,
);
const max = Math.max(...numbers);
return { avg, stdev, max };
Expand Down
11 changes: 5 additions & 6 deletions benchmark/bench/cli-startup.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { fileURLToPath } from 'node:url';
import { exec } from 'tinyexec';
import { markdownTable } from 'markdown-table';
import { exec } from 'tinyexec';
import { astroBin, calculateStat } from './_util.js';

/** Default project to run for this benchmark if not specified */
export const defaultProject = 'render-default';

/**
* @param {URL} projectDir
* @param {URL} outputFile
*/
export async function run(projectDir, outputFile) {
export async function run(projectDir) {
const root = fileURLToPath(projectDir);

console.log('Benchmarking `astro --help`...');
Expand All @@ -28,7 +27,7 @@ export async function run(projectDir, outputFile) {
printResult({
'astro --help': helpStat,
'astro info': infoStat,
})
}),
);
console.log('='.repeat(10));
}
Expand All @@ -45,7 +44,7 @@ async function benchmarkCommand(command, args, root) {

for (let i = 0; i < 10; i++) {
const start = performance.now();
await exec(command, args, { nodeOptions: { cwd: root } });
await exec(command, args, { nodeOptions: { cwd: root }, throwOnError: true });
durations.push(performance.now() - start);
}

Expand All @@ -69,6 +68,6 @@ function printResult(result) {
],
{
align: ['l', 'r', 'r', 'r'],
}
},
);
}
50 changes: 50 additions & 0 deletions benchmark/bench/codspeed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import path from 'node:path';
import { withCodSpeed } from '@codspeed/tinybench-plugin';
import { Bench } from 'tinybench';
import { exec } from 'tinyexec';
import { renderPages } from '../make-project/render-default.js';
import { astroBin } from './_util.js';

export async function run({ memory: _memory, render, stress: _stress }) {
const options = {
iterations: 10,
};
const bench = process.env.CODSPEED ? withCodSpeed(new Bench(options)) : new Bench(options);
let app;
bench.add(
'Rendering',
async () => {
console.info('Start task.');
const result = {};
for (const fileName of renderPages) {
const pathname = '/' + fileName.slice(0, -path.extname(fileName).length);
const request = new Request(new URL(pathname, 'http://exmpale.com'));
const response = await app.render(request);
const html = await response.text();
if (!result[pathname]) result[pathname] = [];
result[pathname].push(html);
}
console.info('Finish task.');
return result;
},
{
async beforeAll() {
// build for rendering
await exec(astroBin, ['build'], {
nodeOptions: {
cwd: render.root,
stdio: 'inherit',
},
});

const entry = new URL('./dist/server/entry.mjs', `file://${render.root}`);
const { manifest, createApp } = await import(entry);
app = createApp(manifest);
app.manifest = manifest;
},
},
);

await bench.run();
console.table(bench.table());
}
7 changes: 4 additions & 3 deletions benchmark/bench/memory.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { exec } from 'tinyexec';
import { markdownTable } from 'markdown-table';
import fs from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { markdownTable } from 'markdown-table';
import { exec } from 'tinyexec';
import { astroBin } from './_util.js';

/** @typedef {Record<string, import('../../packages/astro/src/core/config/timer').Stat>} AstroTimerStat */
Expand All @@ -26,6 +26,7 @@ export async function run(projectDir, outputFile) {
ASTRO_TIMER_PATH: outputFilePath,
},
},
throwOnError: true,
});

console.log('Raw results written to', outputFilePath);
Expand Down Expand Up @@ -55,6 +56,6 @@ function printResult(output) {
],
{
align: ['l', 'r', 'r', 'r'],
}
},
);
}
14 changes: 8 additions & 6 deletions benchmark/bench/render.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { exec } from 'tinyexec';
import { markdownTable } from 'markdown-table';
import fs from 'node:fs/promises';
import http from 'node:http';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { markdownTable } from 'markdown-table';
import { waitUntilBusy } from 'port-authority';
import { calculateStat, astroBin } from './_util.js';
import { exec } from 'tinyexec';
import { renderPages } from '../make-project/render-default.js';
import { astroBin, calculateStat } from './_util.js';

const port = 4322;

Expand All @@ -25,6 +25,7 @@ export async function run(projectDir, outputFile) {
cwd: root,
stdio: 'inherit',
},
throwOnError: true,
});

console.log('Previewing...');
Expand All @@ -33,6 +34,7 @@ export async function run(projectDir, outputFile) {
cwd: root,
stdio: 'inherit',
},
throwOnError: true,
});

console.log('Waiting for server ready...');
Expand All @@ -58,14 +60,14 @@ export async function run(projectDir, outputFile) {
console.log('Done!');
}

async function benchmarkRenderTime() {
export async function benchmarkRenderTime(portToListen = port) {
/** @type {Record<string, number[]>} */
const result = {};
for (const fileName of renderPages) {
// Render each file 100 times and push to an array
for (let i = 0; i < 100; i++) {
const pathname = '/' + fileName.slice(0, -path.extname(fileName).length);
const renderTime = await fetchRenderTime(`http://localhost:${port}${pathname}`);
const renderTime = await fetchRenderTime(`http://localhost:${portToListen}${pathname}`);
if (!result[pathname]) result[pathname] = [];
result[pathname].push(renderTime);
}
Expand Down Expand Up @@ -95,7 +97,7 @@ function printResult(result) {
],
{
align: ['l', 'r', 'r', 'r'],
}
},
);
}

Expand Down
23 changes: 13 additions & 10 deletions benchmark/bench/server-stress.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import autocannon from 'autocannon';
import { exec } from 'tinyexec';
import { markdownTable } from 'markdown-table';
import fs from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import autocannon from 'autocannon';
import { markdownTable } from 'markdown-table';
import { waitUntilBusy } from 'port-authority';
import pb from 'pretty-bytes';
import { exec } from 'tinyexec';
import { astroBin } from './_util.js';

const port = 4321;
Expand All @@ -24,12 +24,15 @@ export async function run(projectDir, outputFile) {
cwd: root,
stdio: 'inherit',
},
throwOnError: true,
});

console.log('Previewing...');
const previewProcess = execaCommand(`${astroBin} preview --port ${port}`, {
cwd: root,
stdio: 'inherit',
const previewProcess = await exec(astroBin, ['preview', '--port', port], {
nodeOptions: {
cwd: root,
stdio: 'inherit',
},
});

console.log('Waiting for server ready...');
Expand Down Expand Up @@ -58,7 +61,7 @@ export async function run(projectDir, outputFile) {
/**
* @returns {Promise<import('autocannon').Result>}
*/
async function benchmarkCannon() {
export async function benchmarkCannon() {
return new Promise((resolve, reject) => {
const instance = autocannon(
{
Expand All @@ -75,7 +78,7 @@ async function benchmarkCannon() {
instance.stop();
resolve(result);
}
}
},
);
autocannon.track(instance, { renderResultsTable: false });
});
Expand All @@ -94,7 +97,7 @@ function printResult(output) {
],
{
align: ['l', 'r', 'r', 'r'],
}
},
);

const reqAndBytesTable = markdownTable(
Expand All @@ -105,7 +108,7 @@ function printResult(output) {
],
{
align: ['l', 'r', 'r', 'r', 'r'],
}
},
);

return `${latencyTable}\n\n${reqAndBytesTable}`;
Expand Down
33 changes: 24 additions & 9 deletions benchmark/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import mri from 'mri';
import fs from 'node:fs/promises';
import path from 'node:path';
import { pathToFileURL } from 'node:url';
import {fileURLToPath, pathToFileURL} from 'node:url';

const args = mri(process.argv.slice(2));

Expand All @@ -14,6 +14,7 @@ Command
memory Run build memory and speed test
render Run rendering speed test
server-stress Run server stress test
codspeed Run codspeed test
cli-startup Run CLI startup speed test
Options
Expand All @@ -29,6 +30,7 @@ const benchmarks = {
render: () => import('./bench/render.js'),
'server-stress': () => import('./bench/server-stress.js'),
'cli-startup': () => import('./bench/cli-startup.js'),
codspeed: () => import('./bench/codspeed.js')
};

if (commandName && !(commandName in benchmarks)) {
Expand All @@ -37,12 +39,26 @@ if (commandName && !(commandName in benchmarks)) {
}

if (commandName) {
// Run single benchmark
const bench = benchmarks[commandName];
const benchMod = await bench();
const projectDir = await makeProject(args.project || benchMod.defaultProject);
const outputFile = await getOutputFile(commandName);
await benchMod.run(projectDir, outputFile);
if (commandName === 'codspeed') {
const render = await makeProject('render-bench');
const rootRender = fileURLToPath(render);
const bench = benchmarks[commandName];
const benchMod = await bench();
const payload = {
render: {
root: rootRender,
output: await getOutputFile('render')
},
};
await benchMod.run(payload);
} else {
// Run single benchmark
const bench = benchmarks[commandName];
const benchMod = await bench();
const projectDir = await makeProject(args.project || benchMod.defaultProject);
const outputFile = await getOutputFile(commandName);
await benchMod.run(projectDir, outputFile);
}
} else {
// Run all benchmarks
for (const name in benchmarks) {
Expand All @@ -54,7 +70,7 @@ if (commandName) {
}
}

async function makeProject(name) {
export async function makeProject(name) {
console.log('Making project:', name);
const projectDir = new URL(`./projects/${name}/`, import.meta.url);

Expand All @@ -78,6 +94,5 @@ async function getOutputFile(benchmarkName) {

// Prepare output file directory
await fs.mkdir(new URL('./', file), { recursive: true });

return file;
}
Loading

0 comments on commit 7db86cf

Please sign in to comment.