Home / File/ server-stress.js — astro Source File

server-stress.js — astro Source File

Architecture documentation for server-stress.js, a javascript file in the astro codebase. 8 imports, 0 dependents.

Entity Profile

Dependency Diagram

graph LR
  84e8dcec_8779_ed84_459a_2c92f21c0f63["server-stress.js"]
  4265c711_d908_961d_b7f8_d10af2c1c59b["_util.js"]
  84e8dcec_8779_ed84_459a_2c92f21c0f63 --> 4265c711_d908_961d_b7f8_d10af2c1c59b
  5d6d1861_a18d_b246_cd94_08889ab7e74c["promises"]
  84e8dcec_8779_ed84_459a_2c92f21c0f63 --> 5d6d1861_a18d_b246_cd94_08889ab7e74c
  d9a92db9_c95e_9165_13ac_24b3d859d946["node:url"]
  84e8dcec_8779_ed84_459a_2c92f21c0f63 --> d9a92db9_c95e_9165_13ac_24b3d859d946
  1b85ebc2_98b4_cd3d_a050_29c28aadffed["autocannon"]
  84e8dcec_8779_ed84_459a_2c92f21c0f63 --> 1b85ebc2_98b4_cd3d_a050_29c28aadffed
  50f71548_38c8_8ade_dfca_b84f78362dc4["markdown-table"]
  84e8dcec_8779_ed84_459a_2c92f21c0f63 --> 50f71548_38c8_8ade_dfca_b84f78362dc4
  d1b5b5e6_0e04_a09d_7faa_6b868fd077da["port-authority"]
  84e8dcec_8779_ed84_459a_2c92f21c0f63 --> d1b5b5e6_0e04_a09d_7faa_6b868fd077da
  54fcd246_4434_15f3_dc42_1162facf1a09["pretty-bytes"]
  84e8dcec_8779_ed84_459a_2c92f21c0f63 --> 54fcd246_4434_15f3_dc42_1162facf1a09
  015e2115_00b7_8619_a3f3_dc6eceb4c058["tinyexec"]
  84e8dcec_8779_ed84_459a_2c92f21c0f63 --> 015e2115_00b7_8619_a3f3_dc6eceb4c058
  style 84e8dcec_8779_ed84_459a_2c92f21c0f63 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

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;

export const defaultProject = 'server-stress-default';

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

	console.log('Building...');
	await exec(astroBin, ['build'], {
		nodeOptions: {
			cwd: root,
			stdio: 'inherit',
		},
		throwOnError: true,
	});

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

	console.log('Waiting for server ready...');
	await waitUntilBusy(port, { timeout: 5000 });

	console.log('Running benchmark...');
	const result = await benchmarkCannon();

	console.log('Killing server...');
	if (!previewProcess.kill('SIGTERM')) {
		console.warn('Failed to kill server process id:', previewProcess.pid);
	}

	console.log('Writing results to', fileURLToPath(outputFile));
	await fs.writeFile(outputFile, JSON.stringify(result, null, 2));

	console.log('Result preview:');
	console.log('='.repeat(10));
	console.log(`#### Server stress\n\n`);
	console.log(printResult(result));
	console.log('='.repeat(10));

	console.log('Done!');
}

/**
 * @returns {Promise<import('autocannon').Result>}
 */
export async function benchmarkCannon() {
	return new Promise((resolve, reject) => {
		const instance = autocannon(
			{
				url: `http://localhost:${port}`,
				connections: 100,
				duration: 30,
				pipelining: 10,
			},
			(err, result) => {
				if (err) {
					reject(err);
				} else {
					// @ts-expect-error untyped but documented
					instance.stop();
					resolve(result);
				}
			},
		);
		autocannon.track(instance, { renderResultsTable: false });
	});
}

/**
 * @param {import('autocannon').Result} output
 */
function printResult(output) {
	const { latency: l, requests: r, throughput: t } = output;

	const latencyTable = markdownTable(
		[
			['', 'Avg', 'Stdev', 'Max'],
			['Latency', `${l.average} ms`, `${l.stddev} ms`, `${l.max} ms`],
		],
		{
			align: ['l', 'r', 'r', 'r'],
		},
	);

	const reqAndBytesTable = markdownTable(
		[
			['', 'Avg', 'Stdev', 'Min', 'Total in 30s'],
			['Req/Sec', r.average, r.stddev, r.min, `${(r.total / 1000).toFixed(1)}k requests`],
			['Bytes/Sec', pb(t.average), pb(t.stddev), pb(t.min), `${pb(t.total)} read`],
		],
		{
			align: ['l', 'r', 'r', 'r', 'r'],
		},
	);

	return `${latencyTable}\n\n${reqAndBytesTable}`;
}

Subdomains

Dependencies

  • _util.js
  • autocannon
  • markdown-table
  • node:url
  • port-authority
  • pretty-bytes
  • promises
  • tinyexec

Frequently Asked Questions

What does server-stress.js do?
server-stress.js is a source file in the astro codebase, written in javascript. It belongs to the PerformanceBenchmarking domain, MetricsCalculator subdomain.
What functions are defined in server-stress.js?
server-stress.js defines 3 function(s): benchmarkCannon, printResult, run.
What does server-stress.js depend on?
server-stress.js imports 8 module(s): _util.js, autocannon, markdown-table, node:url, port-authority, pretty-bytes, promises, tinyexec.
Where is server-stress.js in the architecture?
server-stress.js is located at benchmark/bench/server-stress.js (domain: PerformanceBenchmarking, subdomain: MetricsCalculator, directory: benchmark/bench).

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free