Skip to content

Commit

Permalink
ImmutableVar perf optimizations (#3814)
Browse files Browse the repository at this point in the history
* Use lru_cache on expensive typing-related functions

* Skip instantiation of VarData unless data was actually merged

* Revert "integration: bump listening timeout to 1800 seconds"

This reverts commit a94eedf.

* Revert "integration: bump listening timeout to 1200 seconds"

This reverts commit 86563b6.
  • Loading branch information
masenf authored Aug 28, 2024
1 parent 3fa9f1f commit 8f396fc
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 20 deletions.
3 changes: 2 additions & 1 deletion reflex/ivars/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@
overload,
)

from typing_extensions import ParamSpec, get_origin, get_type_hints, override
from typing_extensions import ParamSpec, get_type_hints, override

from reflex import constants
from reflex.base import Base
from reflex.constants.colors import Color
from reflex.utils import console, imports, serializers, types
from reflex.utils.exceptions import VarDependencyError, VarTypeError, VarValueError
from reflex.utils.format import format_state_name
from reflex.utils.types import get_origin
from reflex.vars import (
ComputedVar,
ImmutableVarData,
Expand Down
4 changes: 1 addition & 3 deletions reflex/ivars/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@
overload,
)

from typing_extensions import get_origin

from reflex.utils import types
from reflex.utils.exceptions import VarAttributeError
from reflex.utils.types import GenericType, get_attribute_access_type
from reflex.utils.types import GenericType, get_attribute_access_type, get_origin
from reflex.vars import ImmutableVarData, Var, VarData

from .base import (
Expand Down
4 changes: 1 addition & 3 deletions reflex/ivars/sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@
overload,
)

from typing_extensions import get_origin

from reflex import constants
from reflex.constants.base import REFLEX_VAR_OPENING_TAG
from reflex.utils.types import GenericType
from reflex.utils.types import GenericType, get_origin
from reflex.vars import (
ImmutableVarData,
Var,
Expand Down
23 changes: 21 additions & 2 deletions reflex/utils/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import inspect
import sys
import types
from functools import cached_property, wraps
from functools import cached_property, lru_cache, wraps
from typing import (
Any,
Callable,
Expand All @@ -21,9 +21,11 @@
Union,
_GenericAlias, # type: ignore
get_args,
get_origin,
get_type_hints,
)
from typing import (
get_origin as get_origin_og,
)

import sqlalchemy

Expand Down Expand Up @@ -133,6 +135,20 @@ def __bool__(self) -> bool:
return False


@lru_cache()
def get_origin(tp):
"""Get the origin of a class.
Args:
tp: The class to get the origin of.
Returns:
The origin of the class.
"""
return get_origin_og(tp)


@lru_cache()
def is_generic_alias(cls: GenericType) -> bool:
"""Check whether the class is a generic alias.
Expand All @@ -157,6 +173,7 @@ def is_none(cls: GenericType) -> bool:
return cls is type(None) or cls is None


@lru_cache()
def is_union(cls: GenericType) -> bool:
"""Check if a class is a Union.
Expand All @@ -169,6 +186,7 @@ def is_union(cls: GenericType) -> bool:
return get_origin(cls) in UnionTypes


@lru_cache()
def is_literal(cls: GenericType) -> bool:
"""Check if a class is a Literal.
Expand Down Expand Up @@ -314,6 +332,7 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
return None # Attribute is not accessible.


@lru_cache()
def get_base_class(cls: GenericType) -> Type:
"""Get the base class of a class.
Expand Down
17 changes: 7 additions & 10 deletions reflex/vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
_GenericAlias, # type: ignore
cast,
get_args,
get_origin,
get_type_hints,
)

Expand All @@ -51,7 +50,7 @@
ParsedImportDict,
parse_imports,
)
from reflex.utils.types import override
from reflex.utils.types import get_origin, override

if TYPE_CHECKING:
from reflex.state import BaseState
Expand Down Expand Up @@ -182,15 +181,14 @@ def merge(cls, *others: ImmutableVarData | VarData | None) -> VarData | None:
var_data.interpolations if isinstance(var_data, VarData) else []
)

return (
cls(
if state or _imports or hooks or interpolations:
return cls(
state=state,
imports=_imports,
hooks=hooks,
interpolations=interpolations,
)
or None
)
return None

def __bool__(self) -> bool:
"""Check if the var data is non-empty.
Expand Down Expand Up @@ -302,14 +300,13 @@ def merge(
else {k: None for k in var_data.hooks}
)

return (
ImmutableVarData(
if state or _imports or hooks:
return ImmutableVarData(
state=state,
imports=_imports,
hooks=hooks,
)
or None
)
return None

def __bool__(self) -> bool:
"""Check if the var data is non-empty.
Expand Down
2 changes: 1 addition & 1 deletion scripts/integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ if [ -f /proc/$pid/winpid ]; then
echo "Windows detected, passing winpid $pid to port waiter"
fi

python scripts/wait_for_listening_port.py $check_ports --timeout=1800 --server-pid "$pid"
python scripts/wait_for_listening_port.py $check_ports --timeout=900 --server-pid "$pid"

0 comments on commit 8f396fc

Please sign in to comment.