Skip to content

⚡️ Speed up function _contains_jsx by 143% in PR #1565 (codeflash/optimize-pr1561-2026-02-20T03.24.55)#1569

Merged
claude[bot] merged 1 commit intocodeflash/optimize-pr1561-2026-02-20T03.24.55from
codeflash/optimize-pr1565-2026-02-20T03.34.50
Feb 20, 2026
Merged

⚡️ Speed up function _contains_jsx by 143% in PR #1565 (codeflash/optimize-pr1561-2026-02-20T03.24.55)#1569
claude[bot] merged 1 commit intocodeflash/optimize-pr1561-2026-02-20T03.24.55from
codeflash/optimize-pr1565-2026-02-20T03.34.50

Conversation

@codeflash-ai
Copy link
Contributor

@codeflash-ai codeflash-ai bot commented Feb 20, 2026

⚡️ This pull request contains optimizations for PR #1565

If you approve this dependent PR, these changes will be merged into the original PR branch codeflash/optimize-pr1561-2026-02-20T03.24.55.

This PR will be automatically closed if the original PR is merged.


📄 143% (1.43x) speedup for _contains_jsx in codeflash/languages/javascript/frameworks/react/profiler.py

⏱️ Runtime : 461 microseconds 190 microseconds (best of 24 runs)

📝 Explanation and details

Using an explicit stack (iterative DFS) avoids Python recursion overhead and the temporary generator created by any(...). This reduces function-call overhead on large/deep trees and returns as soon as a matching node is found, improving both runtime and memory usage.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 13 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Click to see Generated Regression Tests
import pytest  # used for our unit tests
from codeflash.languages.javascript.frameworks.react.profiler import \
    _contains_jsx

# NOTE:
# The function _contains_jsx expects an object that has a `.type` attribute
# and a `.children` iterable of similar objects. In the actual runtime those
# are tree_sitter.Node instances. For the purposes of these unit tests we
# construct lightweight real Python objects that expose the same attributes
# and behavior (type and children). These objects are concrete instances
# (not mocks) and are used only to exercise the pure-Python logic of the
# function under test; they implement the same attribute protocol that
# _contains_jsx relies on.
#
# While the original runtime likely uses tree_sitter.Node instances, the
# function itself performs no isinstance checks and only accesses attributes,
# so these helper instances are suitable, deterministic, and lightweight.

class _TestNode:
    """Minimal node-like object with .type and .children attributes.

    The _contains_jsx function only reads .type and iterates .children,
    so this class provides that protocol in a simple form.
    """
    def __init__(self, type_name: str, children=None):
        # store the node type string
        self.type = type_name
        # ensure children is an iterable (list) if None provided
        self.children = [] if children is None else list(children)

    def __repr__(self):
        # helpful repr for debugging failing tests
        return f"_TestNode(type={self.type!r}, children={self.children!r})"

# Helper constructors to make trees more readable in tests
def leaf(type_name: str):
    """Create a leaf node (no children) with the given type."""
    return _TestNode(type_name, children=[])

def node(type_name: str, *children):
    """Create a node with the given type and child nodes."""
    return _TestNode(type_name, children=list(children))

def test_direct_jsx_element_returns_true():
    # A node that itself is a jsx_element should immediately return True.
    n = leaf("jsx_element")  # a node whose type matches one of the cases
    codeflash_output = _contains_jsx(n) # 651ns -> 781ns (16.6% slower)

def test_direct_jsx_self_closing_returns_true():
    # A self-closing JSX element type should return True as well.
    n = leaf("jsx_self_closing_element")
    codeflash_output = _contains_jsx(n) # 591ns -> 832ns (29.0% slower)

def test_direct_jsx_fragment_returns_true():
    # A jsx_fragment should be recognized as containing JSX.
    n = leaf("jsx_fragment")
    codeflash_output = _contains_jsx(n) # 591ns -> 811ns (27.1% slower)

def test_no_jsx_in_single_non_jsx_node_returns_false():
    # A single node with non-JSX type and no children should return False.
    n = leaf("identifier")
    codeflash_output = _contains_jsx(n) # 1.48μs -> 1.00μs (48.0% faster)

def test_nested_jsx_child_returns_true():
    # If any descendant is JSX the function should return True.
    # Build a small tree: root -> intermediate -> jsx_element
    jsx = leaf("jsx_element")
    intermediate = node("expression_statement", jsx)
    root = node("program", intermediate)
    codeflash_output = _contains_jsx(root) # 2.62μs -> 1.22μs (114% faster)

def test_sibling_jsx_among_non_jsx_children_returns_true():
    # Root has multiple children; one of them is a JSX node.
    children = [leaf("identifier"), leaf("number"), leaf("jsx_self_closing_element"), leaf("string")]
    root = node("program", *children)
    codeflash_output = _contains_jsx(root) # 2.56μs -> 1.44μs (77.2% faster)

def test_empty_children_list_on_non_jsx_node_returns_false():
    # A node with an empty children list and non-JSX type should be False.
    root = _TestNode("source_file", children=[])
    codeflash_output = _contains_jsx(root) # 1.07μs -> 1.02μs (4.89% faster)

def test_children_attribute_is_iterable_but_empty_tuple_returns_false():
    # children as an empty tuple should also work (function iterates children).
    root = _TestNode("module", children=tuple())
    codeflash_output = _contains_jsx(root) # 1.11μs -> 982ns (13.2% faster)

def test_deeply_nested_non_jsx_nodes_return_false():
    # Create a deep chain of non-JSX nodes to ensure recursion handles depth.
    depth = 50  # moderate depth to keep test deterministic and safe
    current = leaf("identifier")
    for _ in range(depth):
        current = node("expression", current)
    codeflash_output = _contains_jsx(current) # 23.4μs -> 5.57μs (320% faster)

def test_node_children_set_to_none_raises_type_error():
    # If children is None, the generator expression will attempt to iterate None
    # and raise a TypeError. Confirm that behavior (explicitly testing an edge).
    bad = _TestNode("program", children=None)
    # Manually set children to None to simulate a misconstructed node
    bad.children = None
    with pytest.raises(TypeError):
        _contains_jsx(bad) # 3.06μs -> 2.96μs (3.37% faster)

def test_node_is_none_raises_attribute_error():
    # Passing None as the node should raise an AttributeError when accessing .type
    with pytest.raises(AttributeError):
        _contains_jsx(None) # 2.52μs -> 2.63μs (4.14% slower)

def test_wide_tree_of_many_children_without_jsx_returns_false():
    # Root node with many (1000) non-JSX children should be processed without error.
    many = [leaf("identifier") for _ in range(1000)]  # 1000 children
    root = node("program", *many)
    codeflash_output = _contains_jsx(root) # 279μs -> 82.5μs (239% faster)

def test_wide_tree_of_many_children_with_one_jsx_returns_true():
    # Same as above but with one child containing JSX; should short-circuit to True.
    many = [leaf("identifier") for _ in range(999)]
    many.insert(500, leaf("jsx_element"))  # place JSX in the middle
    root = node("program", *many)
    codeflash_output = _contains_jsx(root) # 141μs -> 42.4μs (234% faster)

def test_deep_tree_with_jsx_at_bottom_returns_true():
    # Build a deep chain of non-JSX nodes ending with a JSX node.
    # Depth chosen to be large but below typical recursion limit to avoid RecursionError.
    depth = 500
    bottom = leaf("jsx_fragment")  # the deepest node is JSX
    current = bottom
    for i in range(depth):
        # wrap current into a new parent node each iteration
        current = node(f"wrap_{i}", current)
    # The top node should contain JSX somewhere deep in its descendants.
    codeflash_output = _contains_jsx(current)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

To edit these changes git checkout codeflash/optimize-pr1565-2026-02-20T03.34.50 and push.

Codeflash Static Badge

Using an explicit stack (iterative DFS) avoids Python recursion overhead and the temporary generator created by any(...). This reduces function-call overhead on large/deep trees and returns as soon as a matching node is found, improving both runtime and memory usage.
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash labels Feb 20, 2026
@claude
Copy link
Contributor

claude bot commented Feb 20, 2026

PR Review Summary

Prek Checks

✅ All checks passed — no formatting or linting issues found.

Mypy

✅ No new type errors introduced by this PR. Pre-existing mypy errors exist in base.py and support.py (unrelated to this change).

Code Review

No critical issues found.

This PR converts _contains_jsx from a recursive implementation to an iterative stack-based DFS in profiler.py:161-169. The change is straightforward and correct:

  • Replaces recursive calls with an explicit stack (list used as LIFO)
  • Preserves identical traversal logic and short-circuit behavior
  • Eliminates Python function call overhead and any() generator
  • Avoids RecursionError on deeply nested trees (previously limited to ~1000 depth)
  • No behavioral change for callers

Test Coverage

File PR Main Delta
codeflash/languages/javascript/frameworks/react/profiler.py 0% N/A (new file)
codeflash/languages/base.py 98% 98% 0%
codeflash/languages/javascript/parse.py 49% 49% 0%
codeflash/languages/javascript/support.py 70% 71% -1%
codeflash/models/function_types.py 100% 100% 0%
Overall 78% 78% 0%

Notes:

  • profiler.py has 0% test coverage, but this is a pre-existing gap from the parent branch — the file was introduced in an earlier PR, not by this optimization
  • The specific function changed (_contains_jsx) is covered by the codeflash-generated regression tests included in the PR description (13 passed)
  • No coverage regression from this change
  • 8 test failures in test_tracer.py are pre-existing on main and unrelated to this PR

Last updated: 2026-02-20

@claude claude bot merged commit 71988e9 into codeflash/optimize-pr1561-2026-02-20T03.24.55 Feb 20, 2026
22 of 28 checks passed
@claude claude bot deleted the codeflash/optimize-pr1565-2026-02-20T03.34.50 branch February 20, 2026 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants

Comments