vanilla-jet 1.3.2 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,201 @@
1
+ const fs = require('fs');
2
+ const http = require('http');
3
+ const os = require('os');
4
+ const path = require('path');
5
+ const { performance } = require('perf_hooks');
6
+
7
+ const Server = require('../framework/server.js');
8
+
9
+ const BENCH_PORT = Number(process.env.BENCH_PORT || 3199);
10
+ const BENCH_FILE_SIZE_KB = Number(process.env.BENCH_FILE_SIZE_KB || 512);
11
+ const BENCH_TOTAL_REQUESTS = Number(process.env.BENCH_TOTAL_REQUESTS || 2000);
12
+ const BENCH_COLD_ITERATIONS = Number(process.env.BENCH_COLD_ITERATIONS || 300);
13
+ const BENCH_PATH = '/public/scripts/vanilla.min.js';
14
+
15
+ function ensureDir(dirPath) {
16
+ fs.mkdirSync(dirPath, { recursive: true });
17
+ }
18
+
19
+ function createFixtureWorkspace(rootPath) {
20
+ ensureDir(path.join(rootPath, 'assets'));
21
+ ensureDir(path.join(rootPath, 'public', 'scripts'));
22
+
23
+ const bytes = BENCH_FILE_SIZE_KB * 1024;
24
+ const filePath = path.join(rootPath, BENCH_PATH);
25
+ const content = Buffer.alloc(bytes, 'a');
26
+ fs.writeFileSync(filePath, content);
27
+ }
28
+
29
+ function createServerOptions(port) {
30
+ return {
31
+ settings: {
32
+ profile: {
33
+ port: port,
34
+ https_server: false,
35
+ enable_precompressed_negotiation: true
36
+ },
37
+ shared: {},
38
+ security: {}
39
+ }
40
+ };
41
+ }
42
+
43
+ function percentile(values, percentileValue) {
44
+ if (!values.length) {
45
+ return 0;
46
+ }
47
+ const sorted = values.slice().sort((a, b) => a - b);
48
+ const index = Math.min(sorted.length - 1, Math.ceil((percentileValue / 100) * sorted.length) - 1);
49
+ return sorted[index];
50
+ }
51
+
52
+ function summarize(values, elapsedMs) {
53
+ const total = values.length;
54
+ const sum = values.reduce((acc, current) => acc + current, 0);
55
+ return {
56
+ count: total,
57
+ avgMs: total ? sum / total : 0,
58
+ p50Ms: percentile(values, 50),
59
+ p95Ms: percentile(values, 95),
60
+ p99Ms: percentile(values, 99),
61
+ maxMs: values.length ? Math.max(...values) : 0,
62
+ rps: elapsedMs > 0 ? (total * 1000) / elapsedMs : 0
63
+ };
64
+ }
65
+
66
+ function printSummary(title, summary) {
67
+ console.log(`\n${title}`);
68
+ console.log(` requests: ${summary.count}`);
69
+ console.log(` avg: ${summary.avgMs.toFixed(2)} ms`);
70
+ console.log(` p50: ${summary.p50Ms.toFixed(2)} ms`);
71
+ console.log(` p95: ${summary.p95Ms.toFixed(2)} ms`);
72
+ console.log(` p99: ${summary.p99Ms.toFixed(2)} ms`);
73
+ console.log(` max: ${summary.maxMs.toFixed(2)} ms`);
74
+ console.log(` rps: ${summary.rps.toFixed(2)}`);
75
+ }
76
+
77
+ function requestOnce(agent, port, headers) {
78
+ return new Promise((resolve, reject) => {
79
+ const start = performance.now();
80
+ const req = http.request({
81
+ hostname: '127.0.0.1',
82
+ port: port,
83
+ path: BENCH_PATH,
84
+ method: 'GET',
85
+ headers: headers || {},
86
+ agent: agent
87
+ }, (res) => {
88
+ res.on('data', () => {});
89
+ res.on('end', () => {
90
+ resolve({
91
+ statusCode: res.statusCode,
92
+ durationMs: performance.now() - start
93
+ });
94
+ });
95
+ });
96
+ req.on('error', reject);
97
+ req.end();
98
+ });
99
+ }
100
+
101
+ function waitForServerListening(instance) {
102
+ if (instance && instance.httpx && instance.httpx.listening) {
103
+ return Promise.resolve();
104
+ }
105
+ return new Promise((resolve) => {
106
+ instance.httpx.once('listening', resolve);
107
+ });
108
+ }
109
+
110
+ async function runWarmBenchmark(port) {
111
+ const agent = new http.Agent({
112
+ keepAlive: true,
113
+ maxSockets: 1
114
+ });
115
+ const latencies = [];
116
+ const startedAt = performance.now();
117
+ for (let index = 0; index < BENCH_TOTAL_REQUESTS; index += 1) {
118
+ const result = await requestOnce(agent, port, {
119
+ 'accept-encoding': 'br, gzip'
120
+ });
121
+ if (result.statusCode !== 200) {
122
+ throw new Error(`Unexpected status ${result.statusCode} in warm benchmark`);
123
+ }
124
+ latencies.push(result.durationMs);
125
+ }
126
+ agent.destroy();
127
+ return summarize(latencies, performance.now() - startedAt);
128
+ }
129
+
130
+ async function runColdBenchmark(server, port) {
131
+ const latencies = [];
132
+ const agent = new http.Agent({
133
+ keepAlive: true,
134
+ maxSockets: 1
135
+ });
136
+ const startedAt = performance.now();
137
+ for (let index = 0; index < BENCH_COLD_ITERATIONS; index += 1) {
138
+ server.router.staticMetadataCache.clear();
139
+ server.router.staticResolutionCache.clear();
140
+
141
+ const sample = await requestOnce(agent, port, {
142
+ 'accept-encoding': 'br, gzip'
143
+ });
144
+ if (sample.statusCode !== 200) {
145
+ throw new Error(`Unexpected status ${sample.statusCode} in cold benchmark`);
146
+ }
147
+ latencies.push(sample.durationMs);
148
+ }
149
+ agent.destroy();
150
+ return summarize(latencies, performance.now() - startedAt);
151
+ }
152
+
153
+ async function main() {
154
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'vanillajet-bench-'));
155
+ createFixtureWorkspace(tmpDir);
156
+ const previousCwd = process.cwd();
157
+ process.chdir(tmpDir);
158
+
159
+ const server = new Server(createServerOptions(BENCH_PORT), []);
160
+ await waitForServerListening(server);
161
+ try {
162
+ const warmup = await requestOnce(undefined, BENCH_PORT, {});
163
+ if (warmup.statusCode !== 200) {
164
+ throw new Error(`Warmup request failed with status ${warmup.statusCode}`);
165
+ }
166
+
167
+ const coldResult = await runColdBenchmark(server, BENCH_PORT);
168
+ printSummary('Cold cache benchmark', coldResult);
169
+
170
+ const warmResult = await runWarmBenchmark(BENCH_PORT);
171
+ printSummary('Warm cache benchmark', warmResult);
172
+
173
+ await new Promise((resolve) => {
174
+ server.httpx.close(() => {
175
+ resolve();
176
+ });
177
+ });
178
+ process.chdir(previousCwd);
179
+
180
+ const p95Improvement = coldResult.p95Ms > 0
181
+ ? ((coldResult.p95Ms - warmResult.p95Ms) / coldResult.p95Ms) * 100
182
+ : 0;
183
+ console.log(`\nWarm p95 improvement vs cold: ${p95Improvement.toFixed(2)}%`);
184
+ } catch (error) {
185
+ await new Promise((resolve) => {
186
+ server.httpx.close(() => {
187
+ resolve();
188
+ });
189
+ }).catch(() => {});
190
+ process.chdir(previousCwd);
191
+ throw error;
192
+ } finally {
193
+ fs.rmSync(tmpDir, { recursive: true, force: true });
194
+ }
195
+ }
196
+
197
+ main().catch((error) => {
198
+ console.error('\nStatic benchmark failed');
199
+ console.error(error);
200
+ process.exit(1);
201
+ });