Skip to content

Commit 6452343

Browse files
committed
test: add stress test scripts for large file handling
- stress-test.js: Tests ValueExtractor performance with 10K/50K/100K lines - generate-test-file.js: Generates test log files for browser testing
1 parent 118782a commit 6452343

2 files changed

Lines changed: 181 additions & 0 deletions

File tree

scripts/generate-test-file.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Generate test log file for browser testing
3+
* Run with: node scripts/generate-test-file.js [lines]
4+
* Example: node scripts/generate-test-file.js 100000
5+
*/
6+
7+
import fs from 'fs';
8+
import path from 'path';
9+
import { fileURLToPath } from 'url';
10+
11+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
12+
13+
const numLines = parseInt(process.argv[2]) || 100000;
14+
15+
console.log(`\n📝 Generating test file with ${numLines.toLocaleString()} lines...`);
16+
17+
const lines = [];
18+
for (let i = 0; i < numLines; i++) {
19+
const step = i;
20+
const loss = Math.random() * 2 + Math.exp(-i / 10000);
21+
const gradNorm = Math.random() * 0.5 + 0.1;
22+
lines.push(`step: ${step} | loss: ${loss.toFixed(6)} | grad_norm: ${gradNorm.toFixed(6)}`);
23+
}
24+
25+
const content = lines.join('\n');
26+
const outputPath = path.join(__dirname, `test-${numLines}.log`);
27+
28+
fs.writeFileSync(outputPath, content);
29+
30+
const stats = fs.statSync(outputPath);
31+
const sizeMB = (stats.size / 1024 / 1024).toFixed(2);
32+
33+
console.log(`✓ Created: ${outputPath}`);
34+
console.log(`✓ Size: ${sizeMB} MB`);
35+
console.log(`\n📌 Drag this file into the Log Analyzer to test!`);

scripts/stress-test.js

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/**
2+
* Stress test for large file handling
3+
* Run with: node scripts/stress-test.js
4+
*/
5+
6+
import { ValueExtractor } from '../src/utils/ValueExtractor.js';
7+
8+
// Generate a large test log file
9+
function generateTestLog(numLines) {
10+
console.log(`\n📝 Generating ${numLines.toLocaleString()} lines of test data...`);
11+
const startTime = Date.now();
12+
13+
const lines = [];
14+
for (let i = 0; i < numLines; i++) {
15+
const step = i;
16+
const loss = Math.random() * 2 + Math.exp(-i / 10000); // Decreasing loss with noise
17+
const gradNorm = Math.random() * 0.5 + 0.1;
18+
lines.push(`step: ${step} | loss: ${loss.toFixed(6)} | grad_norm: ${gradNorm.toFixed(6)}`);
19+
}
20+
21+
const content = lines.join('\n');
22+
const elapsed = Date.now() - startTime;
23+
const sizeBytes = Buffer.byteLength(content, 'utf8');
24+
const sizeMB = (sizeBytes / 1024 / 1024).toFixed(2);
25+
26+
console.log(` ✓ Generated in ${elapsed}ms`);
27+
console.log(` ✓ Size: ${sizeMB} MB (${sizeBytes.toLocaleString()} bytes)`);
28+
29+
return { content, sizeBytes };
30+
}
31+
32+
// Test ValueExtractor performance
33+
function testValueExtractor(content) {
34+
console.log('\n🔍 Testing ValueExtractor...');
35+
36+
// Test 1: String input (old way - splits every time)
37+
console.log('\n Test 1: extractByKeyword with string input');
38+
let start = Date.now();
39+
const result1 = ValueExtractor.extractByKeyword(content, 'loss:');
40+
let elapsed = Date.now() - start;
41+
console.log(` ✓ Found ${result1.length.toLocaleString()} matches in ${elapsed}ms`);
42+
43+
// Test 2: Pre-split lines (optimized way)
44+
console.log('\n Test 2: extractByKeyword with pre-split lines');
45+
start = Date.now();
46+
const lines = content.split('\n');
47+
const splitTime = Date.now() - start;
48+
console.log(` ✓ Split into ${lines.length.toLocaleString()} lines in ${splitTime}ms`);
49+
50+
start = Date.now();
51+
const result2 = ValueExtractor.extractByKeyword(lines, 'loss:');
52+
elapsed = Date.now() - start;
53+
console.log(` ✓ Found ${result2.length.toLocaleString()} matches in ${elapsed}ms`);
54+
55+
// Test 3: Multiple metrics with pre-split lines
56+
console.log('\n Test 3: Multiple metrics with pre-split lines (simulates worker)');
57+
start = Date.now();
58+
const lossResults = ValueExtractor.extractByKeyword(lines, 'loss:');
59+
const gradResults = ValueExtractor.extractByKeyword(lines, 'grad_norm:');
60+
elapsed = Date.now() - start;
61+
console.log(` ✓ Loss: ${lossResults.length.toLocaleString()} matches`);
62+
console.log(` ✓ Grad Norm: ${gradResults.length.toLocaleString()} matches`);
63+
console.log(` ✓ Total time: ${elapsed}ms`);
64+
65+
// Verify data integrity
66+
console.log('\n Verifying data integrity...');
67+
if (result1.length === result2.length) {
68+
console.log(` ✓ Match counts are equal: ${result1.length}`);
69+
} else {
70+
console.log(` ✗ ERROR: Match counts differ! ${result1.length} vs ${result2.length}`);
71+
}
72+
73+
return { lossResults, gradResults, lines };
74+
}
75+
76+
// Test memory usage
77+
function testMemoryUsage(label) {
78+
const used = process.memoryUsage();
79+
console.log(`\n📊 Memory Usage (${label}):`);
80+
console.log(` Heap Used: ${(used.heapUsed / 1024 / 1024).toFixed(2)} MB`);
81+
console.log(` Heap Total: ${(used.heapTotal / 1024 / 1024).toFixed(2)} MB`);
82+
console.log(` RSS: ${(used.rss / 1024 / 1024).toFixed(2)} MB`);
83+
return used;
84+
}
85+
86+
// Main test runner
87+
async function runStressTest() {
88+
console.log('═'.repeat(60));
89+
console.log('🚀 STRESS TEST FOR LARGE FILE HANDLING');
90+
console.log('═'.repeat(60));
91+
92+
const testCases = [
93+
{ lines: 10000, name: '10K lines' },
94+
{ lines: 50000, name: '50K lines' },
95+
{ lines: 100000, name: '100K lines' },
96+
];
97+
98+
testMemoryUsage('Initial');
99+
100+
for (const testCase of testCases) {
101+
console.log('\n' + '─'.repeat(60));
102+
console.log(`📋 TEST CASE: ${testCase.name}`);
103+
console.log('─'.repeat(60));
104+
105+
// Generate test data
106+
const { content, sizeBytes } = generateTestLog(testCase.lines);
107+
108+
// Check if this would be considered a "large file"
109+
const LARGE_FILE_THRESHOLD = 500 * 1024; // 500KB
110+
const isLargeFile = sizeBytes > LARGE_FILE_THRESHOLD;
111+
console.log(`\n Large file threshold: ${isLargeFile ? '⚠️ EXCEEDS' : '✓ Within'} (${(LARGE_FILE_THRESHOLD / 1024).toFixed(0)}KB)`);
112+
113+
// Test ValueExtractor
114+
const { lossResults, gradResults } = testValueExtractor(content);
115+
116+
// Memory after processing
117+
testMemoryUsage('After processing');
118+
119+
// Summary
120+
console.log('\n📈 Results Summary:');
121+
console.log(` Lines processed: ${testCase.lines.toLocaleString()}`);
122+
console.log(` Loss data points: ${lossResults.length.toLocaleString()}`);
123+
console.log(` Grad norm data points: ${gradResults.length.toLocaleString()}`);
124+
125+
// Verify first and last values
126+
if (lossResults.length > 0) {
127+
console.log(` First loss value: ${lossResults[0].value.toFixed(6)} (line ${lossResults[0].line})`);
128+
console.log(` Last loss value: ${lossResults[lossResults.length - 1].value.toFixed(6)} (line ${lossResults[lossResults.length - 1].line})`);
129+
}
130+
131+
// Force GC if available
132+
if (global.gc) {
133+
global.gc();
134+
console.log('\n 🧹 Garbage collection triggered');
135+
}
136+
}
137+
138+
console.log('\n' + '═'.repeat(60));
139+
console.log('✅ STRESS TEST COMPLETE');
140+
console.log('═'.repeat(60));
141+
142+
testMemoryUsage('Final');
143+
}
144+
145+
// Run the test
146+
runStressTest().catch(console.error);

0 commit comments

Comments
 (0)