Skip to content

Commit 378bd1b

Browse files
Optimize CommentMapper.visit_FunctionDef
The optimized code achieves a 10% speedup through several targeted micro-optimizations that reduce overhead in the tight loops: **Key optimizations:** 1. **Local variable caching for frequent lookups**: Storing `self.original_runtimes` and `self.optimized_runtimes` in local variables (`original_runtimes`, `optimized_runtimes`) eliminates repeated attribute lookups in the inner loops, which is expensive due to Python's method resolution. 2. **Eliminated unnecessary list allocations**: The original code created `nodes_to_check = [compound_line_node]` and extended it with `getattr(compound_line_node, "body", [])` on every iteration. The optimized version uses `hasattr()` to check for a body attribute first, then iterates directly over `compound_line_node.body` when present, avoiding list creation and extension. 3. **Reduced redundant attribute access**: Added `nbody = node.body` and `line_body = line_node.body` to cache commonly accessed attributes, reducing repeated lookups. 4. **Streamlined f-string usage**: Consistent use of f-strings (`f"{i}_{j}"` instead of `str(i) + "_" + str(j)`) provides marginal performance improvements for string concatenation. The optimizations are most effective for **large-scale test cases** - the annotated tests show the biggest improvements (13.4% faster) occur with functions containing many compound statements (50 for-loops with 10 statements each), where the eliminated allocations and attribute lookups compound significantly. Simple functions show minimal or slight performance regression due to the overhead of additional local variable assignments, but complex functions with nested loops see substantial gains.
1 parent 7e4ecb3 commit 378bd1b

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

codeflash/code_utils/edit_generated_tests.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,28 +61,39 @@ def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> ast.AsyncFunctio
6161

6262
def _process_function_def_common(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> None:
6363
self.context_stack.append(node.name)
64-
i = len(node.body) - 1
64+
nbody = node.body
65+
i = len(nbody) - 1
6566
test_qualified_name = ".".join(self.context_stack)
6667
key = test_qualified_name + "#" + str(self.abs_path)
68+
original_runtimes = self.original_runtimes
69+
optimized_runtimes = self.optimized_runtimes
70+
6771
while i >= 0:
68-
line_node = node.body[i]
72+
line_node = nbody[i]
6973
if isinstance(line_node, (ast.With, ast.For, ast.While, ast.If)):
70-
j = len(line_node.body) - 1
74+
line_body = line_node.body
75+
j = len(line_body) - 1
7176
while j >= 0:
72-
compound_line_node: ast.stmt = line_node.body[j]
73-
nodes_to_check = [compound_line_node]
74-
nodes_to_check.extend(getattr(compound_line_node, "body", []))
75-
for internal_node in nodes_to_check:
76-
if isinstance(internal_node, (ast.stmt, ast.Assign)):
77-
inv_id = str(i) + "_" + str(j)
78-
match_key = key + "#" + inv_id
79-
if match_key in self.original_runtimes and match_key in self.optimized_runtimes:
80-
self.results[internal_node.lineno] = self.get_comment(match_key)
77+
compound_line_node: ast.stmt = line_body[j]
78+
# Fast-path: most ast.stmt don't have a body
79+
if hasattr(compound_line_node, "body"):
80+
for internal_node in compound_line_node.body:
81+
if isinstance(internal_node, (ast.stmt, ast.Assign)):
82+
inv_id = f"{i}_{j}"
83+
match_key = f"{key}#{inv_id}"
84+
if match_key in original_runtimes and match_key in optimized_runtimes:
85+
self.results[internal_node.lineno] = self.get_comment(match_key)
86+
# Always check the compound_line_node itself
87+
if isinstance(compound_line_node, (ast.stmt, ast.Assign)):
88+
inv_id = f"{i}_{j}"
89+
match_key = f"{key}#{inv_id}"
90+
if match_key in original_runtimes and match_key in optimized_runtimes:
91+
self.results[compound_line_node.lineno] = self.get_comment(match_key)
8192
j -= 1
8293
else:
8394
inv_id = str(i)
84-
match_key = key + "#" + inv_id
85-
if match_key in self.original_runtimes and match_key in self.optimized_runtimes:
95+
match_key = f"{key}#{inv_id}"
96+
if match_key in original_runtimes and match_key in optimized_runtimes:
8697
self.results[line_node.lineno] = self.get_comment(match_key)
8798
i -= 1
8899
self.context_stack.pop()

0 commit comments

Comments
 (0)