Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ jobs:
'codeflash/telemetry/' 'codeflash/tracing/' 'codeflash/verification/' \
'tests/' 'pyproject.toml' 'uv.lock'

# JS E2E tests: JS language support + shared pipeline + packages
# JS E2E tests: JS language support + shared pipeline + packages + test fixtures
check_paths e2e_js \
'codeflash/languages/javascript/' 'codeflash/languages/base.py' \
'codeflash/languages/registry.py' 'codeflash/optimization/' \
'codeflash/verification/' 'packages/' \
'tests/scripts/end_to_end_test_js*'
'code_to_optimize/js/' 'tests/scripts/end_to_end_test_js*'

# Java E2E tests: Java language support + shared pipeline + runtime
check_paths e2e_java \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('DataProcessor', () => {

test('handles larger arrays with duplicates', () => {
const data: number[] = [];
for (let i = 0; i < 100; i++) {
for (let i = 0; i < 10000; i++) {
data.push(i % 20);
}
const processor = new DataProcessor(data);
Expand Down
2 changes: 1 addition & 1 deletion codeflash-benchmark/codeflash_benchmark/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# These version placeholders will be replaced by uv-dynamic-versioning during build.
__version__ = "0.20.5.post177.dev0+da536db8"
__version__ = "0.20.5.post151.dev0+95b62113"
5 changes: 5 additions & 0 deletions codeflash/languages/javascript/function_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ def line_profiler_step(
try:
line_profiler_output_path = get_run_tmp_file(Path("line_profiler_output.json"))

# Pre-create with valid empty JSON so the file is never 0 bytes
# even if the JS profiler save() is interrupted (e.g. SIGKILL on timeout)
line_profiler_output_path.parent.mkdir(parents=True, exist_ok=True)
line_profiler_output_path.write_text("{}", encoding="utf-8")

success = self.language_support.instrument_source_for_line_profiler(
func_info=self.function_to_optimize, line_profiler_output_file=line_profiler_output_path
)
Expand Down
27 changes: 15 additions & 12 deletions codeflash/languages/javascript/line_profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ def _generate_profiler_init(self) -> str:
# Serialize line contents map for embedding in JavaScript
line_contents_json = json.dumps(getattr(self, "line_contents", {}))

return f"""
return f"""// @ts-nocheck
// Codeflash line profiler initialization
// @ts-nocheck
const __codeflash_fs__ = require('fs');
const __codeflash_path__ = require('path');
const {self.profiler_var} = {{
stats: {{}},
lineContents: {line_contents_json},
Expand Down Expand Up @@ -123,19 +124,18 @@ def _generate_profiler_init(self) -> str:
this.lastLineTime = now;

this.totalHits++;
// Save every 100 hits to ensure we capture results even with --forceExit
if (this.totalHits % 100 === 0) {{
// Save periodically to capture results even with --forceExit.
// Use 10000 (not 100) to avoid excessive I/O on hot loops.
if (this.totalHits % 10000 === 0) {{
this.save();
}}
}},

save: function() {{
const fs = require('fs');
const pathModule = require('path');
const outputDir = pathModule.dirname('{self.output_file.as_posix()}');
const outputDir = __codeflash_path__.dirname('{self.output_file.as_posix()}');
try {{
if (!fs.existsSync(outputDir)) {{
fs.mkdirSync(outputDir, {{ recursive: true }});
if (!__codeflash_fs__.existsSync(outputDir)) {{
__codeflash_fs__.mkdirSync(outputDir, {{ recursive: true }});
}}
// Merge line contents into stats before saving
const statsWithContent = {{}};
Expand All @@ -145,7 +145,7 @@ def _generate_profiler_init(self) -> str:
content: this.lineContents[key] || ''
}};
}}
fs.writeFileSync(
__codeflash_fs__.writeFileSync(
'{self.output_file.as_posix()}',
JSON.stringify(statsWithContent, null, 2)
);
Expand Down Expand Up @@ -298,8 +298,11 @@ def parse_results(profile_file: Path) -> dict:
return {"timings": {}, "unit": 1e-9, "functions": {}}

try:
with profile_file.open("r") as f:
data = json.load(f)
content = profile_file.read_text(encoding="utf-8").strip()
if not content:
logger.warning("Line profiler output file is empty: %s", profile_file)
return {"timings": {}, "unit": 1e-9, "functions": {}}
data = json.loads(content)

# Group by file and function
timings = {}
Expand Down
18 changes: 11 additions & 7 deletions codeflash/languages/javascript/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -2497,13 +2497,17 @@ def instrument_source_for_line_profiler(
def parse_line_profile_results(self, line_profiler_output_file: Path) -> dict:
from codeflash.languages.javascript.line_profiler import JavaScriptLineProfiler

if line_profiler_output_file.exists():
parsed_results = JavaScriptLineProfiler.parse_results(line_profiler_output_file)
if parsed_results.get("timings"):
# Format output string for display
str_out = self._format_js_line_profile_output(parsed_results)
return {"timings": parsed_results.get("timings", {}), "unit": 1e-9, "str_out": str_out}
logger.warning("No line profiler output file found at %s", line_profiler_output_file)
if not line_profiler_output_file.exists():
logger.warning("Line profiler output file not found: %s", line_profiler_output_file)
return {"timings": {}, "unit": 0, "str_out": ""}

parsed_results = JavaScriptLineProfiler.parse_results(line_profiler_output_file)
if parsed_results.get("timings"):
# Format output string for display
str_out = self._format_js_line_profile_output(parsed_results)
return {"timings": parsed_results.get("timings", {}), "unit": 1e-9, "str_out": str_out}

logger.warning("Line profiler output file empty or contained no timing data: %s", line_profiler_output_file)
return {"timings": {}, "unit": 0, "str_out": ""}

def _format_js_line_profile_output(self, parsed_results: dict) -> str:
Expand Down
2 changes: 1 addition & 1 deletion codeflash/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# These version placeholders will be replaced by uv-dynamic-versioning during build.
__version__ = "0.20.5.post177.dev0+da536db8"
__version__ = "0.20.5.post151.dev0+95b62113"
Loading