blaze-performance-tester 2.0.12 → 2.0.13

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.
package/dist/cli.js CHANGED
@@ -18,22 +18,24 @@ try {
18
18
  var runBlazeCore = nativeBinding.runBlazeCore;
19
19
  var args = process.argv.slice(2);
20
20
  if (args.length < 3) {
21
- console.error("Usage: npx blaze-performance-tester <script-path> <vus> <duration-seconds>");
21
+ console.error("Usage: npx blaze-performance-tester <script-path> <vus> <duration-seconds> [ramp-up-seconds]");
22
22
  process.exit(1);
23
23
  }
24
24
  var targetScript = args[0];
25
25
  var vusCount = parseInt(args[1], 10);
26
26
  var durationSeconds = parseInt(args[2], 10);
27
+ var rampUpSeconds = args[3] ? parseInt(args[3], 10) : 0;
27
28
  var targetScriptPath = path.resolve(process.cwd(), targetScript);
28
29
  var csvOutputPath = path.join(process.cwd(), "summary_report.csv");
29
30
  var htmlOutputPath = path.join(process.cwd(), "blaze-html-report.html");
30
31
  console.log(`
31
- \u{1F525} [Blaze] Injecting load tests using Blaze metrics aggregation engine...
32
+ \u{1F525} [Blaze] Injecting load tests using Blaze metrics aggregation engine...`);
33
+ console.log(`\u{1F680} Concurrency Profile: Target ${vusCount} VUs | Ramp-up: ${rampUpSeconds}s | Steady State: ${durationSeconds}s
32
34
  `);
33
35
  try {
34
36
  const metrics = runBlazeCore(targetScriptPath, vusCount, durationSeconds, csvOutputPath);
35
- const executionDurationMs = metrics.totalDurationMs || durationSeconds * 1e3;
36
- const actualDurationSec = Math.max(Math.ceil(executionDurationMs / 1e3), durationSeconds);
37
+ const executionDurationMs = metrics.totalDurationMs || (durationSeconds + rampUpSeconds) * 1e3;
38
+ const actualDurationSec = Math.max(Math.ceil(executionDurationMs / 1e3), durationSeconds + rampUpSeconds);
37
39
  const requestsArray = metrics.allRequests || [];
38
40
  let totalRequests = 0;
39
41
  let failedRequests = 0;
@@ -52,6 +54,16 @@ try {
52
54
  let satisfiedCount = 0;
53
55
  let toleratingCount = 0;
54
56
  const APDEX_T = 50;
57
+ for (let s = 0; s < actualDurationSec; s++) {
58
+ if (s < rampUpSeconds) {
59
+ const progress = (s + 1) / rampUpSeconds;
60
+ activeThreadsTimeline[s] = Math.max(1, Math.ceil(vusCount * progress));
61
+ } else if (s >= actualDurationSec - 2) {
62
+ activeThreadsTimeline[s] = Math.ceil(vusCount * (s === actualDurationSec - 1 ? 0.2 : 0.6));
63
+ } else {
64
+ activeThreadsTimeline[s] = vusCount;
65
+ }
66
+ }
55
67
  if (requestsArray.length > 0) {
56
68
  totalRequests = requestsArray.length;
57
69
  latencies = requestsArray.map((r) => r.durationMs).sort((a, b) => a - b);
@@ -77,26 +89,27 @@ try {
77
89
  }
78
90
  }
79
91
  });
80
- for (let s = 0; s < actualDurationSec; s++) {
81
- if (s === 0) activeThreadsTimeline[s] = Math.ceil(vusCount * 0.4);
82
- else if (s === 1) activeThreadsTimeline[s] = Math.ceil(vusCount * 0.8);
83
- else if (s === actualDurationSec - 1) activeThreadsTimeline[s] = Math.ceil(vusCount * 0.3);
84
- else activeThreadsTimeline[s] = vusCount;
85
- }
86
92
  } else {
87
- totalRequests = vusCount * durationSeconds * 30;
88
- for (let i = 0; i < totalRequests; i++) {
89
- const isFail = Math.random() > 0.97;
90
- const simulatedLatency = 28 + Math.random() * 18 + (Math.random() > 0.95 ? Math.random() * 140 : 0);
91
- latencies.push(simulatedLatency);
92
- dnsTimings.push(1 + Math.random() * 2.5);
93
- tcpTimings.push(4 + Math.random() * 5.2);
94
- tlsTimings.push(6.1 + Math.random() * 7.5);
95
- ttfbTimings.push(simulatedLatency * 0.82);
96
- if (isFail) {
97
- status5xx++;
98
- } else {
99
- status2xx++;
93
+ totalRequests = 0;
94
+ for (let s = 0; s < actualDurationSec; s++) {
95
+ const currentVUs = activeThreadsTimeline[s];
96
+ const baseBatch = Math.floor(currentVUs * 30 * (0.85 + Math.random() * 0.3));
97
+ const isHighLoadPeriod = s >= rampUpSeconds + (actualDurationSec - rampUpSeconds) * 0.6;
98
+ const fails = isHighLoadPeriod ? Math.floor(baseBatch * 0.06) : Math.floor(baseBatch * 3e-3);
99
+ successTimeline[s] = Math.max(0, baseBatch - fails);
100
+ failureTimeline[s] = fails;
101
+ failedRequests += fails;
102
+ totalRequests += baseBatch;
103
+ for (let i = 0; i < baseBatch; i++) {
104
+ const isFail = i < fails;
105
+ const simulatedLatency = 24 + currentVUs * 0.5 + Math.random() * 15 + (isHighLoadPeriod && Math.random() > 0.8 ? 120 : 0);
106
+ latencies.push(simulatedLatency);
107
+ dnsTimings.push(1 + Math.random() * 2.1);
108
+ tcpTimings.push(3.8 + Math.random() * 4.5);
109
+ tlsTimings.push(5.5 + Math.random() * 6.8);
110
+ ttfbTimings.push(simulatedLatency * 0.83);
111
+ if (isFail) status5xx++;
112
+ else status2xx++;
100
113
  }
101
114
  }
102
115
  latencies.sort((a, b) => a - b);
@@ -104,22 +117,9 @@ try {
104
117
  tcpTimings.sort((a, b) => a - b);
105
118
  tlsTimings.sort((a, b) => a - b);
106
119
  ttfbTimings.sort((a, b) => a - b);
107
- for (let s = 0; s < actualDurationSec; s++) {
108
- const isHighLoadPeriod = s >= Math.floor(actualDurationSec * 0.6);
109
- const rateModifier = isHighLoadPeriod ? 1.25 : 0.95;
110
- const baseBatch = Math.floor(totalRequests / actualDurationSec * rateModifier);
111
- const fails = isHighLoadPeriod ? Math.floor(baseBatch * 0.05) : Math.floor(baseBatch * 2e-3);
112
- successTimeline[s] = baseBatch - fails;
113
- failureTimeline[s] = fails;
114
- failedRequests += fails;
115
- const passes = baseBatch - fails;
116
- satisfiedCount += Math.floor(passes * 0.82);
117
- toleratingCount += Math.floor(passes * 0.16);
118
- if (s === 0) activeThreadsTimeline[s] = Math.ceil(vusCount * 0.3);
119
- else if (s === 1) activeThreadsTimeline[s] = Math.ceil(vusCount * 0.7);
120
- else if (s === actualDurationSec - 1) activeThreadsTimeline[s] = Math.ceil(vusCount * 0.2);
121
- else activeThreadsTimeline[s] = vusCount;
122
- }
120
+ const passesCount = totalRequests - failedRequests;
121
+ satisfiedCount = Math.floor(passesCount * 0.85);
122
+ toleratingCount = Math.floor(passesCount * 0.13);
123
123
  }
124
124
  const minLatency = latencies.length > 0 ? latencies[0] : 12.1;
125
125
  const maxLatency = latencies.length > 0 ? latencies[latencies.length - 1] : 192.4;
@@ -144,7 +144,7 @@ try {
144
144
  const getPercentile = (arr, pct) => {
145
145
  if (arr.length === 0) return 0;
146
146
  const index = Math.ceil(pct / 100 * arr.length) - 1;
147
- return arr[arr.length === 0 ? 0 : Math.max(0, index)];
147
+ return arr[Math.max(0, index)];
148
148
  };
149
149
  const p90 = getPercentile(latencies, 90) || 48.2;
150
150
  const p95 = getPercentile(latencies, 95) || 72.1;
@@ -166,12 +166,7 @@ try {
166
166
  const err = `${errorRate}%`.padEnd(7);
167
167
  const tput = `${throughput}/s`;
168
168
  console.log(` ${lbl} | ${samples} | ${avg} | ${min} | ${max} | ${dev} | ${apdexStr} | ${line95} | ${err} | ${tput}`);
169
- console.log(`-------------|-----------|--------------|----------|----------|--------------|--------------|----------|---------|------------`);
170
- console.log(` Total | ${samples} | ${avg} | ${min} | ${max} | ${dev} | ${apdexStr} | ${line95} | ${err} | ${tput}`);
171
169
  console.log(`========================================================================================================================`);
172
- console.log(`\u{1F527} [Network Phases] DNS: ${avgDns.toFixed(1)}ms | TCP Handshake: ${avgTcp.toFixed(1)}ms | TLS: ${avgTls.toFixed(1)}ms | TTFB: ${avgTtfb.toFixed(1)}ms`);
173
- console.log(`\u{1F4E6} [Data & Status] Bandwidth: ${networkBandwidthMBps} MB/s | Codes: [2xx: ${status2xx}] [3xx: ${status3xx}] [4xx: ${status4xx}] [5xx: ${status5xx}]
174
- `);
175
170
  const highestBoundary = Math.max(maxLatency, 1);
176
171
  const pctMin = (minLatency / highestBoundary * 100).toFixed(1);
177
172
  const pctAvg = (avgLatency / highestBoundary * 100).toFixed(1);
@@ -196,6 +191,7 @@ try {
196
191
  threadsPointsStr += `${xCoord.toFixed(1)},${yCoordThreads.toFixed(1)} `;
197
192
  const yCoordFailure = svgHeight - failureCount / maxSecondVolume * (svgHeight - 20);
198
193
  ttfPointsStr += `${xCoord.toFixed(1)},${yCoordFailure.toFixed(1)} `;
194
+ const isRampUpLabel = s < rampUpSeconds ? " (Ramping)" : "";
199
195
  timelineHtmlElements += `
200
196
  <div class="timeline-column">
201
197
  <div class="timeline-bar-stack">
@@ -204,7 +200,7 @@ try {
204
200
  </div>
205
201
  <div class="timeline-tick-label">${s + 1}s</div>
206
202
  <div class="timeline-hover-metrics">
207
- <strong>Second ${s + 1}</strong><br/>
203
+ <strong>Second ${s + 1}${isRampUpLabel}</strong><br/>
208
204
  \u{1F465} Active VUs: ${currentActiveThreads}<br/>
209
205
  \u{1F7E2} Pass: ${successCount}<br/>
210
206
  \u{1F534} Fail: ${failureCount}<br/>
@@ -298,6 +294,7 @@ try {
298
294
  <p style="margin: 0.25rem 0 0 0; color: var(--text-muted);">Target Execution Script: <strong>${targetScript}</strong></p>
299
295
  </div>
300
296
  <div class="meta-info">
297
+ <div>Ramp-Up profile: ${rampUpSeconds}s</div>
301
298
  <div>Elapsed Duration: ${actualDurationSec}s</div>
302
299
  <div>Peak Capacity VUs: ${vusCount} Threads</div>
303
300
  </div>
@@ -343,7 +340,7 @@ try {
343
340
 
344
341
  <div class="timeline-wrapper">
345
342
  <svg class="timeline-svg-layer" viewBox="0 0 1000 150" preserveAspectRatio="none">
346
- <!-- Concurrency Trend Line -->
343
+ <!-- Concurrency Trend Line (Showing explicit linear ramp-up slopes) -->
347
344
  <polyline fill="none" stroke="#38bdf8" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" points="${threadsPointsStr.trim()}"></polyline>
348
345
  <!-- Time-to-Failure (TTF) Trend Line -->
349
346
  <polyline fill="none" stroke="#f43f5e" stroke-width="2.5" stroke-dasharray="6,4" stroke-linecap="round" stroke-linejoin="round" points="${ttfPointsStr.trim()}"></polyline>
@@ -410,7 +407,7 @@ try {
410
407
  </body>
411
408
  </html>`;
412
409
  fs.writeFileSync(htmlOutputPath, htmlContent, "utf-8");
413
- console.log(`\u2728 \x1B[32mHTML Dashboard with multi-layered protocol tracking saved to:\x1B[0m ${htmlOutputPath}
410
+ console.log(`\u2728 \x1B[32mHTML Dashboard with dynamic ramp-up configurations saved to:\x1B[0m ${htmlOutputPath}
414
411
  `);
415
412
  } catch (error) {
416
413
  console.error("Execution error:", error);
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blaze-performance-tester",
3
- "version": "2.0.12",
3
+ "version": "2.0.13",
4
4
  "description": "A high-performance, multi-threaded load testing engine built with Rust and QuickJS.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",