From 7b4893e8bd9b5325d7c5435fd216b89384e32b02 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 11 Jul 2026 02:24:13 +0000 Subject: [PATCH 1/2] Bypass f-string tag round-trip for var operation operands Interpolating a var into an f-string hashes it, permanently registers it in the module-global _global_vars dict (which never evicts - a memory leak, worst under dev hot-reload), and emits a tag that the return expression's __post_init__ regex-decodes back out. For operands of a @var_operation this round-trip is pure overhead (~30-40% of op construction): the operation merges operand VarData directly from _args. var_operation now suppresses tagging on its operands (ref-counted, so nested operations on the same var can't clear an outer suppression early) while the body runs. Vars created inside the body still tag normally, so their VarData keeps flowing through the return expression. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Jy8uHH11KircGa2MbTrR8g --- .../reflex-base/src/reflex_base/vars/base.py | 33 ++++++++- tests/units/vars/test_base.py | 69 ++++++++++++++++++- 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/packages/reflex-base/src/reflex_base/vars/base.py b/packages/reflex-base/src/reflex_base/vars/base.py index f7212bef821..2f57c2e4d06 100644 --- a/packages/reflex-base/src/reflex_base/vars/base.py +++ b/packages/reflex-base/src/reflex_base/vars/base.py @@ -840,6 +840,13 @@ def __format__(self, format_spec: str) -> str: Returns: The formatted var. """ + # Operands of a running ``var_operation`` body interpolate as their + # raw JS expression: their VarData flows through the operation's + # ``_args``, so the tag round-trip (and its permanent ``_global_vars`` + # entry) is pure overhead there. See ``var_operation``. + if self.__dict__.get("_format_without_tagging"): + return self._js_expr + hashed_var = hash(self) _global_vars[hashed_var] = self @@ -1856,10 +1863,34 @@ def wrapper(*args: P.args, **kwargs: P.kwargs) -> Var[T]: for key, value in kwargs.items() } + operands = [*args_vars.values(), *kwargs_vars.values()] + # Suppress f-string tagging for the operands while the body runs: + # their VarData reaches the operation through ``_args`` below, so the + # tag round-trip (hash + permanent ``_global_vars`` entry + regex + # decode of the return expression) is pure overhead. The suppression + # is ref-counted so a nested operation on the same var cannot clear + # an outer suppression early; vars created inside the body still tag + # normally and keep contributing VarData via the return expression. + for operand in operands: + operand_dict = operand.__dict__ + operand_dict["_format_without_tagging"] = ( + operand_dict.get("_format_without_tagging", 0) + 1 + ) + try: + return_var = func(*args_vars.values(), **kwargs_vars) # pyright: ignore [reportCallIssue] + finally: + for operand in operands: + operand_dict = operand.__dict__ + remaining = operand_dict["_format_without_tagging"] - 1 + if remaining: + operand_dict["_format_without_tagging"] = remaining + else: + del operand_dict["_format_without_tagging"] + return CustomVarOperation.create( name=func.__name__, args=tuple(list(args_vars.items()) + list(kwargs_vars.items())), - return_var=func(*args_vars.values(), **kwargs_vars), # pyright: ignore [reportCallIssue, reportReturnType] + return_var=return_var, # pyright: ignore [reportArgumentType] ).guess_type() return wrapper diff --git a/tests/units/vars/test_base.py b/tests/units/vars/test_base.py index a8075357fa7..a39274ee283 100644 --- a/tests/units/vars/test_base.py +++ b/tests/units/vars/test_base.py @@ -1,7 +1,16 @@ from collections.abc import Mapping, Sequence import pytest -from reflex_base.vars.base import computed_var, figure_out_type +from reflex_base.utils.imports import ImportVar +from reflex_base.vars.base import ( + Var, + VarData, + _global_vars, + computed_var, + figure_out_type, + var_operation, + var_operation_return, +) from reflex.state import State @@ -42,6 +51,64 @@ def test_figure_out_type(value, expected): assert figure_out_type(value) == expected +def test_var_operation_does_not_register_global_vars() -> None: + """Internal var operations bypass the f-string tag round-trip. + + Regression: each operand interpolation hashed the var and permanently + registered it in the module-global ``_global_vars`` (a memory leak, + worst under hot-reload), then the return expression regex-decoded the + tag back out. Operand VarData already flows through + ``CustomVarOperation._args``. + """ + lhs = Var( + _js_expr="tag_bypass_lhs", + _var_data=VarData(imports={"op-lib": [ImportVar(tag="thing")]}), + ).to(int) + + before = len(_global_vars) + result = lhs + 1 + assert len(_global_vars) == before + + # The suppression flag does not persist on the operand after the op. + assert "_format_without_tagging" not in lhs.__dict__ + + # Operand VarData still reaches the merged operation VarData via _args. + var_data = result._get_all_var_data() + assert var_data is not None + assert dict(var_data.imports)["op-lib"] == (ImportVar(tag="thing"),) + assert str(result) == "(tag_bypass_lhs + 1)" + + # Formatting outside an operation still registers (and tags) as before. + formatted = f"{lhs}" + assert len(_global_vars) == before + 1 + assert formatted != str(lhs) + + +def test_var_operation_body_created_vars_keep_var_data() -> None: + """Vars created inside an operation body still contribute their VarData. + + Only the operands bypass tagging; a var constructed inside the body is + not carried by ``_args``, so it must keep flowing through the tagged + return expression. + """ + from reflex_base.vars.number import NumberVar + + @var_operation + def op_with_derived(value: NumberVar): + derived = Var( + _js_expr="derivedHelper", + _var_data=VarData(imports={"derived-lib": [ImportVar(tag="helper")]}), + ) + return var_operation_return(f"({value} + {derived})", var_type=int) + + result = op_with_derived(Var(_js_expr="a").to(int)) + + var_data = result._get_all_var_data() + assert var_data is not None + assert dict(var_data.imports)["derived-lib"] == (ImportVar(tag="helper"),) + assert str(result) == "(a + derivedHelper)" + + def test_computed_var_replace() -> None: class StateTest(State): @computed_var(cache=True) From c3f3c227a62eb782f87982b2ac9b3e1d91e3f6e0 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 11 Jul 2026 02:24:49 +0000 Subject: [PATCH 2/2] Add news fragment for var operation tag bypass Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Jy8uHH11KircGa2MbTrR8g --- packages/reflex-base/news/6747.performance.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 packages/reflex-base/news/6747.performance.md diff --git a/packages/reflex-base/news/6747.performance.md b/packages/reflex-base/news/6747.performance.md new file mode 100644 index 00000000000..f74ea9384d8 --- /dev/null +++ b/packages/reflex-base/news/6747.performance.md @@ -0,0 +1 @@ +`@var_operation` operands no longer pay the f-string tag round-trip (hash + permanent `_global_vars` registration + regex decode), cutting ~30-40% of var-operation construction cost and stopping internal operations from growing the never-evicting `_global_vars` dict.