123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- """Benchmark tests for apps with varying component numbers."""
- from __future__ import annotations
- import functools
- import time
- from typing import Generator
- import pytest
- from benchmarks import WINDOWS_SKIP_REASON
- from reflex import constants
- from reflex.compiler import utils
- from reflex.testing import AppHarness, chdir
- from reflex.utils import build
- def render_component(num: int):
- """Generate a number of components based on num.
- Args:
- num: number of components to produce.
- Returns:
- The rendered number of components.
- """
- import reflex as rx
- return [
- rx.fragment(
- rx.box(
- rx.accordion.root(
- rx.accordion.item(
- header="Full Ingredients", # type: ignore
- content="Yes. It's built with accessibility in mind.", # type: ignore
- font_size="3em",
- ),
- rx.accordion.item(
- header="Applications", # type: ignore
- content="Yes. It's unstyled by default, giving you freedom over the look and feel.", # type: ignore
- ),
- collapsible=True,
- variant="ghost",
- width="25rem",
- ),
- padding_top="20px",
- ),
- rx.box(
- rx.drawer.root(
- rx.drawer.trigger(
- rx.button("Open Drawer with snap points"), as_child=True
- ),
- rx.drawer.overlay(),
- rx.drawer.portal(
- rx.drawer.content(
- rx.flex(
- rx.drawer.title("Drawer Content"),
- rx.drawer.description("Drawer description"),
- rx.drawer.close(
- rx.button("Close Button"),
- as_child=True,
- ),
- direction="column",
- margin="5em",
- align_items="center",
- ),
- top="auto",
- height="100%",
- flex_direction="column",
- background_color="var(--green-3)",
- ),
- ),
- snap_points=["148px", "355px", 1],
- ),
- ),
- rx.box(
- rx.callout(
- "You will need admin privileges to install and access this application.",
- icon="info",
- size="3",
- ),
- ),
- rx.box(
- rx.table.root(
- rx.table.header(
- rx.table.row(
- rx.table.column_header_cell("Full name"),
- rx.table.column_header_cell("Email"),
- rx.table.column_header_cell("Group"),
- ),
- ),
- rx.table.body(
- rx.table.row(
- rx.table.row_header_cell("Danilo Sousa"),
- rx.table.cell("danilo@example.com"),
- rx.table.cell("Developer"),
- ),
- rx.table.row(
- rx.table.row_header_cell("Zahra Ambessa"),
- rx.table.cell("zahra@example.com"),
- rx.table.cell("Admin"),
- ),
- rx.table.row(
- rx.table.row_header_cell("Jasper Eriksson"),
- rx.table.cell("jasper@example.com"),
- rx.table.cell("Developer"),
- ),
- ),
- )
- ),
- )
- ] * num
- def AppWithTenComponentsOnePage():
- """A reflex app with roughly 10 components on one page."""
- import reflex as rx
- def index() -> rx.Component:
- return rx.center(rx.vstack(*render_component(1)))
- app = rx.App(state=rx.State)
- app.add_page(index)
- def AppWithHundredComponentOnePage():
- """A reflex app with roughly 100 components on one page."""
- import reflex as rx
- def index() -> rx.Component:
- return rx.center(rx.vstack(*render_component(100)))
- app = rx.App(state=rx.State)
- app.add_page(index)
- def AppWithThousandComponentsOnePage():
- """A reflex app with roughly 1000 components on one page."""
- import reflex as rx
- def index() -> rx.Component:
- return rx.center(rx.vstack(*render_component(1000)))
- app = rx.App(state=rx.State)
- app.add_page(index)
- @pytest.fixture(scope="session")
- def app_with_10_components(
- tmp_path_factory,
- ) -> Generator[AppHarness, None, None]:
- """Start Blank Template app at tmp_path via AppHarness.
- Args:
- tmp_path_factory: pytest tmp_path_factory fixture
- Yields:
- running AppHarness instance
- """
- root = tmp_path_factory.mktemp("app10components")
- yield AppHarness.create(
- root=root,
- app_source=functools.partial(
- AppWithTenComponentsOnePage,
- render_component=render_component, # type: ignore
- ),
- ) # type: ignore
- @pytest.fixture(scope="session")
- def app_with_100_components(
- tmp_path_factory,
- ) -> Generator[AppHarness, None, None]:
- """Start Blank Template app at tmp_path via AppHarness.
- Args:
- tmp_path_factory: pytest tmp_path_factory fixture
- Yields:
- running AppHarness instance
- """
- root = tmp_path_factory.mktemp("app100components")
- yield AppHarness.create(
- root=root,
- app_source=functools.partial(
- AppWithHundredComponentOnePage,
- render_component=render_component, # type: ignore
- ),
- ) # type: ignore
- @pytest.fixture(scope="session")
- def app_with_1000_components(
- tmp_path_factory,
- ) -> Generator[AppHarness, None, None]:
- """Create an app with 1000 components at tmp_path via AppHarness.
- Args:
- tmp_path_factory: pytest tmp_path_factory fixture
- Yields:
- an AppHarness instance
- """
- root = tmp_path_factory.mktemp("app1000components")
- yield AppHarness.create(
- root=root,
- app_source=functools.partial(
- AppWithThousandComponentsOnePage,
- render_component=render_component, # type: ignore
- ),
- ) # type: ignore
- @pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
- @pytest.mark.benchmark(
- group="Compile time of varying component numbers",
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_10_compile_time_cold(benchmark, app_with_10_components):
- """Test the compile time on a cold start for an app with roughly 10 components.
- Args:
- benchmark: The benchmark fixture.
- app_with_10_components: The app harness.
- """
- def setup():
- with chdir(app_with_10_components.app_path):
- utils.empty_dir(constants.Dirs.WEB_PAGES, keep_files=["_app.js"])
- app_with_10_components._initialize_app()
- build.setup_frontend(app_with_10_components.app_path)
- def benchmark_fn():
- with chdir(app_with_10_components.app_path):
- app_with_10_components.app_instance._compile()
- benchmark.pedantic(benchmark_fn, setup=setup, rounds=10)
- @pytest.mark.benchmark(
- group="Compile time of varying component numbers",
- min_rounds=5,
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_10_compile_time_warm(benchmark, app_with_10_components):
- """Test the compile time on a warm start for an app with roughly 10 components.
- Args:
- benchmark: The benchmark fixture.
- app_with_10_components: The app harness.
- """
- with chdir(app_with_10_components.app_path):
- app_with_10_components._initialize_app()
- build.setup_frontend(app_with_10_components.app_path)
- def benchmark_fn():
- with chdir(app_with_10_components.app_path):
- app_with_10_components.app_instance._compile()
- benchmark(benchmark_fn)
- @pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
- @pytest.mark.benchmark(
- group="Compile time of varying component numbers",
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_100_compile_time_cold(benchmark, app_with_100_components):
- """Test the compile time on a cold start for an app with roughly 100 components.
- Args:
- benchmark: The benchmark fixture.
- app_with_100_components: The app harness.
- """
- def setup():
- with chdir(app_with_100_components.app_path):
- utils.empty_dir(constants.Dirs.WEB_PAGES, keep_files=["_app.js"])
- app_with_100_components._initialize_app()
- build.setup_frontend(app_with_100_components.app_path)
- def benchmark_fn():
- with chdir(app_with_100_components.app_path):
- app_with_100_components.app_instance._compile()
- benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
- @pytest.mark.benchmark(
- group="Compile time of varying component numbers",
- min_rounds=5,
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_100_compile_time_warm(benchmark, app_with_100_components):
- """Test the compile time on a warm start for an app with roughly 100 components.
- Args:
- benchmark: The benchmark fixture.
- app_with_100_components: The app harness.
- """
- with chdir(app_with_100_components.app_path):
- app_with_100_components._initialize_app()
- build.setup_frontend(app_with_100_components.app_path)
- def benchmark_fn():
- with chdir(app_with_100_components.app_path):
- app_with_100_components.app_instance._compile()
- benchmark(benchmark_fn)
- @pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
- @pytest.mark.benchmark(
- group="Compile time of varying component numbers",
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_1000_compile_time_cold(benchmark, app_with_1000_components):
- """Test the compile time on a cold start for an app with roughly 1000 components.
- Args:
- benchmark: The benchmark fixture.
- app_with_1000_components: The app harness.
- """
- def setup():
- with chdir(app_with_1000_components.app_path):
- utils.empty_dir(constants.Dirs.WEB_PAGES, keep_files=["_app.js"])
- app_with_1000_components._initialize_app()
- build.setup_frontend(app_with_1000_components.app_path)
- def benchmark_fn():
- with chdir(app_with_1000_components.app_path):
- app_with_1000_components.app_instance._compile()
- benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
- @pytest.mark.benchmark(
- group="Compile time of varying component numbers",
- min_rounds=5,
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_1000_compile_time_warm(benchmark, app_with_1000_components):
- """Test the compile time on a warm start for an app with roughly 1000 components.
- Args:
- benchmark: The benchmark fixture.
- app_with_1000_components: The app harness.
- """
- with chdir(app_with_1000_components.app_path):
- app_with_1000_components._initialize_app()
- build.setup_frontend(app_with_1000_components.app_path)
- def benchmark_fn():
- with chdir(app_with_1000_components.app_path):
- app_with_1000_components.app_instance._compile()
- benchmark(benchmark_fn)
|