Skip to content

Commit 73e43e2

Browse files
codeflash optimization
1 parent b464c4d commit 73e43e2

File tree

1 file changed

+43
-21
lines changed

1 file changed

+43
-21
lines changed

codeflash/context/unused_definition_remover.py

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,46 +52,64 @@ def collect_top_level_definitions(
5252
node: cst.CSTNode, definitions: Optional[dict[str, UsageInfo]] = None
5353
) -> dict[str, UsageInfo]:
5454
"""Recursively collect all top-level variable, function, and class definitions."""
55+
# Locally bind types and helpers for faster lookup
56+
FunctionDef = cst.FunctionDef # noqa: N806
57+
ClassDef = cst.ClassDef # noqa: N806
58+
Assign = cst.Assign # noqa: N806
59+
AnnAssign = cst.AnnAssign # noqa: N806
60+
AugAssign = cst.AugAssign # noqa: N806
61+
IndentedBlock = cst.IndentedBlock # noqa: N806
62+
5563
if definitions is None:
5664
definitions = {}
5765

58-
# Handle top-level function definitions
59-
if isinstance(node, cst.FunctionDef):
66+
# Speed: Single isinstance+local var instead of several type calls
67+
node_type = type(node)
68+
# Fast path: function def
69+
if node_type is FunctionDef:
6070
name = node.name.value
6171
definitions[name] = UsageInfo(
6272
name=name,
6373
used_by_qualified_function=False, # Will be marked later if in qualified functions
6474
)
6575
return definitions
6676

67-
# Handle top-level class definitions
68-
if isinstance(node, cst.ClassDef):
77+
# Fast path: class def
78+
if node_type is ClassDef:
6979
name = node.name.value
7080
definitions[name] = UsageInfo(name=name)
7181

72-
# Also collect method definitions within the class
73-
if hasattr(node, "body") and isinstance(node.body, cst.IndentedBlock):
74-
for statement in node.body.body:
75-
if isinstance(statement, cst.FunctionDef):
76-
method_name = f"{name}.{statement.name.value}"
82+
# Collect class methods
83+
body = getattr(node, "body", None)
84+
if body is not None and type(body) is IndentedBlock:
85+
statements = body.body
86+
# Precompute f-string template for efficiency
87+
prefix = name + "."
88+
for statement in statements:
89+
if type(statement) is FunctionDef:
90+
method_name = prefix + statement.name.value
7791
definitions[method_name] = UsageInfo(name=method_name)
7892

7993
return definitions
8094

81-
# Handle top-level variable assignments
82-
if isinstance(node, cst.Assign):
83-
for target in node.targets:
95+
# Fast path: assignment
96+
if node_type is Assign:
97+
# Inline extract_names_from_targets for single-target speed
98+
targets = node.targets
99+
append_def = definitions.__setitem__
100+
for target in targets:
84101
names = extract_names_from_targets(target.target)
85102
for name in names:
86-
definitions[name] = UsageInfo(name=name)
103+
append_def(name, UsageInfo(name=name))
87104
return definitions
88105

89-
if isinstance(node, (cst.AnnAssign, cst.AugAssign)):
90-
if isinstance(node.target, cst.Name):
91-
name = node.target.value
106+
if node_type is AnnAssign or node_type is AugAssign:
107+
tgt = node.target
108+
if type(tgt) is cst.Name:
109+
name = tgt.value
92110
definitions[name] = UsageInfo(name=name)
93111
else:
94-
names = extract_names_from_targets(node.target)
112+
names = extract_names_from_targets(tgt)
95113
for name in names:
96114
definitions[name] = UsageInfo(name=name)
97115
return definitions
@@ -100,12 +118,15 @@ def collect_top_level_definitions(
100118
section_names = get_section_names(node)
101119

102120
if section_names:
121+
getattr_ = getattr
103122
for section in section_names:
104-
original_content = getattr(node, section, None)
123+
original_content = getattr_(node, section, None)
124+
# Instead of isinstance check for list/tuple, rely on duck-type via iter
105125
# If section contains a list of nodes
106126
if isinstance(original_content, (list, tuple)):
127+
defs = definitions # Move out for minor speed
107128
for child in original_content:
108-
collect_top_level_definitions(child, definitions)
129+
collect_top_level_definitions(child, defs)
109130
# If section contains a single node
110131
elif original_content is not None:
111132
collect_top_level_definitions(original_content, definitions)
@@ -302,14 +323,15 @@ def mark_used_definitions(self) -> None:
302323
# Avoid list comprehension for set intersection
303324
expanded_names = self.expanded_qualified_functions
304325
defs = self.definitions
305-
functions_to_mark = (
326+
# Use set intersection but only if defs.keys is a set (Python 3.12 dict_keys supports it efficiently)
327+
fnames = (
306328
expanded_names & defs.keys()
307329
if isinstance(expanded_names, set)
308330
else [name for name in expanded_names if name in defs]
309331
)
310332

311333
# For each specified function, mark it and all its dependencies as used
312-
for func_name in functions_to_mark:
334+
for func_name in fnames:
313335
defs[func_name].used_by_qualified_function = True
314336
for dep in defs[func_name].dependencies:
315337
self.mark_as_used_recursively(dep)

0 commit comments

Comments
 (0)