Skip to content

Commit da51284

Browse files
committed
perf instrumentation as well
1 parent 30eb552 commit da51284

4 files changed

Lines changed: 684 additions & 3 deletions

File tree

code_to_optimize_js/codeflash-jest-helper.js

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,9 @@ function recordResult(funcName, args, returnValue, error, durationNs) {
225225
/**
226226
* Capture a function call with full behavior tracking.
227227
*
228-
* This is the main API for instrumenting function calls.
229-
* It captures inputs, outputs, errors, and timing for every call.
228+
* This is the main API for instrumenting function calls for BEHAVIOR verification.
229+
* It captures inputs (after call, to detect mutations), outputs, errors, and timing.
230+
* Results are written to SQLite for comparison between original and optimized code.
230231
*
231232
* @param {string} funcName - Name of the function being tested
232233
* @param {Function} fn - The function to call
@@ -251,6 +252,7 @@ function capture(funcName, fn, ...args) {
251252
(resolved) => {
252253
const endTime = performance.now();
253254
const durationNs = (endTime - startTime) * 1_000_000;
255+
// Note: args is captured AFTER the call to detect mutations
254256
recordResult(funcName, args, resolved, null, durationNs);
255257
return resolved;
256258
},
@@ -268,12 +270,83 @@ function capture(funcName, fn, ...args) {
268270

269271
const endTime = performance.now();
270272
const durationNs = (endTime - startTime) * 1_000_000;
273+
// Note: args is captured AFTER the call to detect mutations (same as Python)
271274
recordResult(funcName, args, returnValue, error, durationNs);
272275

273276
if (error) throw error;
274277
return returnValue;
275278
}
276279

280+
/**
281+
* Capture a function call for PERFORMANCE benchmarking only.
282+
*
283+
* This is a lightweight instrumentation that only measures timing.
284+
* It prints start/end tags to stdout (no SQLite writes, no serialization overhead).
285+
* Used when we've already verified behavior and just need accurate timing.
286+
*
287+
* Output format matches Python's codeflash_performance wrapper:
288+
* Start: !$######test_module:test_class.test_name:func_name:loop_index:invocation_id######$!
289+
* End: !######test_module:test_class.test_name:func_name:loop_index:invocation_id:duration_ns######!
290+
*
291+
* @param {string} funcName - Name of the function being tested
292+
* @param {Function} fn - The function to call
293+
* @param {...any} args - Arguments to pass to the function
294+
* @returns {any} - The function's return value
295+
* @throws {Error} - Re-throws any error from the function
296+
*/
297+
function capturePerf(funcName, fn, ...args) {
298+
const invocationId = `${lineId}_${invocationCounter}`;
299+
invocationCounter++;
300+
301+
// Get test context
302+
const testModulePath = TEST_MODULE || currentTestName || 'unknown';
303+
const testClassName = ''; // Jest doesn't use classes like Python
304+
305+
// Format: test_module:test_class.test_name:func_name:loop_index:invocation_id
306+
const testStdoutTag = `${testModulePath}:${testClassName}${currentTestName}:${funcName}:${LOOP_INDEX}:${invocationId}`;
307+
308+
// Print start tag
309+
console.log(`!$######${testStdoutTag}######$!`);
310+
311+
const startTime = performance.now();
312+
let returnValue;
313+
let error = null;
314+
315+
try {
316+
returnValue = fn(...args);
317+
318+
// Handle promises (async functions)
319+
if (returnValue instanceof Promise) {
320+
return returnValue.then(
321+
(resolved) => {
322+
const endTime = performance.now();
323+
const durationNs = Math.round((endTime - startTime) * 1_000_000);
324+
// Print end tag with timing
325+
console.log(`!######${testStdoutTag}:${durationNs}######!`);
326+
return resolved;
327+
},
328+
(err) => {
329+
const endTime = performance.now();
330+
const durationNs = Math.round((endTime - startTime) * 1_000_000);
331+
// Print end tag with timing even on error
332+
console.log(`!######${testStdoutTag}:${durationNs}######!`);
333+
throw err;
334+
}
335+
);
336+
}
337+
} catch (e) {
338+
error = e;
339+
}
340+
341+
const endTime = performance.now();
342+
const durationNs = Math.round((endTime - startTime) * 1_000_000);
343+
// Print end tag with timing
344+
console.log(`!######${testStdoutTag}:${durationNs}######!`);
345+
346+
if (error) throw error;
347+
return returnValue;
348+
}
349+
277350
/**
278351
* Capture multiple invocations for benchmarking.
279352
*
@@ -372,7 +445,8 @@ if (typeof afterAll !== 'undefined') {
372445

373446
// Export public API
374447
module.exports = {
375-
capture,
448+
capture, // Behavior verification (writes to SQLite)
449+
capturePerf, // Performance benchmarking (prints to stdout only)
376450
captureMultiple,
377451
writeResults,
378452
clearResults,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
try {
2+
const Database = require('better-sqlite3');
3+
console.log('better-sqlite3 loaded successfully');
4+
const db = new Database('/tmp/test_better_sqlite.db');
5+
db.exec('CREATE TABLE test (id INTEGER)');
6+
db.exec('INSERT INTO test VALUES (1)');
7+
const row = db.prepare('SELECT * FROM test').get();
8+
console.log('Row:', row);
9+
db.close();
10+
console.log('Database test passed');
11+
} catch (e) {
12+
console.error('Error:', e.message);
13+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const codeflash = require('./codeflash-jest-helper');
2+
const { reverseString } = require('./string_utils');
3+
4+
// Manually set test context
5+
process.env.CODEFLASH_OUTPUT_FILE = '/tmp/test_codeflash.sqlite';
6+
process.env.CODEFLASH_LOOP_INDEX = '1';
7+
process.env.CODEFLASH_TEST_MODULE = 'test_module';
8+
9+
// Mock beforeEach/afterAll for non-Jest environment
10+
global.expect = { getState: () => ({ currentTestName: 'manual_test' }) };
11+
12+
// Initialize database
13+
codeflash.initDatabase();
14+
codeflash.setTestName('manual_test');
15+
16+
// Capture a function call
17+
const result = codeflash.capture('reverseString', reverseString, 'hello');
18+
console.log('Result:', result);
19+
20+
// Write results
21+
codeflash.writeResults();
22+
console.log('Done');

0 commit comments

Comments
 (0)