Skip to content

Commit 583a03a

Browse files
⚡️ Speed up method ImportAnalyzer.visit_ImportFrom by 240% in PR #355 (filter_test_files_by_imports_bug_fix)
Here is an optimized version of your program, focusing on the key bottlenecks identified in the profiler. **Major improvements:** - **Use set lookup and precomputed data:** To avoid repeated work in `any(...)` calls, we build sets/maps to batch-check function names needing exact and prefix matching. - **Flatten loop logic:** We reduce string concatenation and duplicate calculation. - **Short-circuit loop on match:** As soon as a match is found, break out of loops ASAP. - **Precompute most-used string to minimize per-iteration computation.** **Summary of changes:** - We pre-group full match and dotted-prefix match targets. - We remove two `any()` generator expressions over a set in favor of direct set lookups and for-loops over a prefiltered small candidate list. - All string concatenations and attribute accesses are done at most once per iteration. - Early returns are used to short-circuit unnecessary further work. This should be **significantly faster**, especially when the set of names is large and there are many aliases per import.
1 parent 66c75a4 commit 583a03a

File tree

1 file changed

+40
-23
lines changed

1 file changed

+40
-23
lines changed

codeflash/discovery/discover_unit_tests.py

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,15 @@ def __init__(self, function_names_to_find: set[str]) -> None:
151151
self.has_dynamic_imports: bool = False
152152
self.wildcard_modules: set[str] = set()
153153

154+
# Precompute function_names for prefix search
155+
# For prefix match, store mapping from prefix-root to candidates for O(1) matching
156+
self._exact_names = function_names_to_find
157+
self._prefix_roots = {}
158+
for name in function_names_to_find:
159+
if "." in name:
160+
root = name.split(".", 1)[0]
161+
self._prefix_roots.setdefault(root, []).append(name)
162+
154163
def visit_Import(self, node: ast.Import) -> None:
155164
"""Handle 'import module' statements."""
156165
if self.found_any_target_function:
@@ -181,40 +190,48 @@ def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
181190
if self.found_any_target_function:
182191
return
183192

184-
if not node.module:
193+
mod = node.module
194+
if not mod:
185195
return
186196

197+
fnames = self._exact_names
198+
proots = self._prefix_roots
199+
187200
for alias in node.names:
188-
if alias.name == "*":
189-
self.wildcard_modules.add(node.module)
190-
else:
191-
imported_name = alias.asname if alias.asname else alias.name
192-
self.imported_modules.add(imported_name)
201+
aname = alias.name
202+
if aname == "*":
203+
self.wildcard_modules.add(mod)
204+
continue
193205

194-
# Check for dynamic import functions
195-
if node.module == "importlib" and alias.name == "import_module":
196-
self.has_dynamic_imports = True
206+
imported_name = alias.asname if alias.asname else aname
207+
self.imported_modules.add(imported_name)
208+
209+
# Fast check for dynamic import
210+
if mod == "importlib" and aname == "import_module":
211+
self.has_dynamic_imports = True
197212

198-
qualified_name = f"{node.module}.{alias.name}"
199-
potential_matches = {alias.name, qualified_name}
213+
qname = f"{mod}.{aname}"
200214

201-
if any(name in self.function_names_to_find for name in potential_matches):
215+
# Fast exact match check
216+
if aname in fnames:
202217
self.found_any_target_function = True
203-
self.found_qualified_name = next(
204-
name for name in potential_matches if name in self.function_names_to_find
205-
)
218+
self.found_qualified_name = aname
206219
return
207-
208-
qualified_prefix = qualified_name + "."
209-
if any(target_func.startswith(qualified_prefix) for target_func in self.function_names_to_find):
220+
if qname in fnames:
210221
self.found_any_target_function = True
211-
self.found_qualified_name = next(
212-
target_func
213-
for target_func in self.function_names_to_find
214-
if target_func.startswith(qualified_prefix)
215-
)
222+
self.found_qualified_name = qname
216223
return
217224

225+
# Fast prefix match: only for relevant roots
226+
prefix = qname + "."
227+
# Only bother if one of the targets startswith the prefix-root
228+
candidates = proots.get(qname, ())
229+
for target_func in candidates:
230+
if target_func.startswith(prefix):
231+
self.found_any_target_function = True
232+
self.found_qualified_name = target_func
233+
return
234+
218235
def visit_Attribute(self, node: ast.Attribute) -> None:
219236
"""Handle attribute access like module.function_name."""
220237
if self.found_any_target_function:

0 commit comments

Comments
 (0)