123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579 |
- """Benchmark tests for apps with varying page 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
- from reflex.utils.prerequisites import get_web_dir
- web_pages = get_web_dir() / constants.Dirs.PAGES
- def render_multiple_pages(app, num: int):
- """Add multiple pages based on num.
- Args:
- app: The App object.
- num: number of pages to render.
- """
- from typing import Tuple
- from rxconfig import config # type: ignore
- import reflex as rx
- docs_url = "https://reflex.dev/docs/getting-started/introduction/"
- filename = f"{config.app_name}/{config.app_name}.py"
- college = [
- "Stanford University",
- "Arizona",
- "Arizona state",
- "Baylor",
- "Boston College",
- "Boston University",
- ]
- class State(rx.State):
- """The app state."""
- position: str
- college: str
- age: Tuple[int, int] = (18, 50)
- salary: Tuple[int, int] = (0, 25000000)
- comp1 = rx.center(
- rx.theme_panel(),
- rx.vstack(
- rx.heading("Welcome to Reflex!", size="9"),
- rx.text("Get started by editing ", rx.code(filename)),
- rx.button(
- "Check out our docs!",
- on_click=lambda: rx.redirect(docs_url),
- size="4",
- ),
- align="center",
- spacing="7",
- font_size="2em",
- ),
- height="100vh",
- )
- comp2 = rx.vstack(
- rx.hstack(
- rx.vstack(
- rx.select(
- ["C", "PF", "SF", "PG", "SG"],
- placeholder="Select a position. (All)",
- on_change=State.set_position, # type: ignore
- size="3",
- ),
- rx.select(
- college,
- placeholder="Select a college. (All)",
- on_change=State.set_college, # type: ignore
- size="3",
- ),
- ),
- rx.vstack(
- rx.vstack(
- rx.hstack(
- rx.badge("Min Age: ", State.age[0]),
- rx.divider(orientation="vertical"),
- rx.badge("Max Age: ", State.age[1]),
- ),
- rx.slider(
- default_value=[18, 50],
- min=18,
- max=50,
- on_value_commit=State.set_age, # type: ignore
- ),
- align_items="left",
- width="100%",
- ),
- rx.vstack(
- rx.hstack(
- rx.badge("Min Sal: ", State.salary[0] // 1000000, "M"),
- rx.divider(orientation="vertical"),
- rx.badge("Max Sal: ", State.salary[1] // 1000000, "M"),
- ),
- rx.slider(
- default_value=[0, 25000000],
- min=0,
- max=25000000,
- on_value_commit=State.set_salary, # type: ignore
- ),
- align_items="left",
- width="100%",
- ),
- ),
- spacing="4",
- ),
- width="100%",
- )
- for i in range(1, num + 1):
- if i % 2 == 1:
- app.add_page(comp1, route=f"page{i}")
- else:
- app.add_page(comp2, route=f"page{i}")
- def AppWithOnePage():
- """A reflex app with one page."""
- from rxconfig import config # type: ignore
- import reflex as rx
- docs_url = "https://reflex.dev/docs/getting-started/introduction/"
- filename = f"{config.app_name}/{config.app_name}.py"
- class State(rx.State):
- """The app state."""
- pass
- def index() -> rx.Component:
- return rx.center(
- rx.input(
- id="token", value=State.router.session.client_token, is_read_only=True
- ),
- rx.vstack(
- rx.heading("Welcome to Reflex!", size="9"),
- rx.text("Get started by editing ", rx.code(filename)),
- rx.button(
- "Check out our docs!",
- on_click=lambda: rx.redirect(docs_url),
- size="4",
- ),
- align="center",
- spacing="7",
- font_size="2em",
- ),
- height="100vh",
- )
- app = rx.App(state=rx.State)
- app.add_page(index)
- def AppWithTenPages():
- """A reflex app with 10 pages."""
- import reflex as rx
- app = rx.App(state=rx.State)
- render_multiple_pages(app, 10)
- def AppWithHundredPages():
- """A reflex app with 100 pages."""
- import reflex as rx
- app = rx.App(state=rx.State)
- render_multiple_pages(app, 100)
- def AppWithThousandPages():
- """A reflex app with Thousand pages."""
- import reflex as rx
- app = rx.App(state=rx.State)
- render_multiple_pages(app, 1000)
- def AppWithTenThousandPages():
- """A reflex app with ten thousand pages."""
- import reflex as rx
- app = rx.App(state=rx.State)
- render_multiple_pages(app, 10000)
- @pytest.fixture(scope="session")
- def app_with_one_page(
- tmp_path_factory,
- ) -> Generator[AppHarness, None, None]:
- """Create an app with 10000 pages at tmp_path via AppHarness.
- Args:
- tmp_path_factory: pytest tmp_path_factory fixture
- Yields:
- an AppHarness instance
- """
- root = tmp_path_factory.mktemp("app1")
- yield AppHarness.create(root=root, app_source=AppWithOnePage)
- @pytest.fixture(scope="session")
- def app_with_ten_pages(
- tmp_path_factory,
- ) -> Generator[AppHarness, None, None]:
- """Create an app with 10 pages at tmp_path via AppHarness.
- Args:
- tmp_path_factory: pytest tmp_path_factory fixture
- Yields:
- an AppHarness instance
- """
- root = tmp_path_factory.mktemp("app10")
- yield AppHarness.create(
- root=root,
- app_source=functools.partial(
- AppWithTenPages,
- render_comp=render_multiple_pages, # type: ignore
- ),
- )
- @pytest.fixture(scope="session")
- def app_with_hundred_pages(
- tmp_path_factory,
- ) -> Generator[AppHarness, None, None]:
- """Create an app with 100 pages at tmp_path via AppHarness.
- Args:
- tmp_path_factory: pytest tmp_path_factory fixture
- Yields:
- an AppHarness instance
- """
- root = tmp_path_factory.mktemp("app100")
- yield AppHarness.create(
- root=root,
- app_source=functools.partial(
- AppWithHundredPages,
- render_comp=render_multiple_pages, # type: ignore
- ),
- ) # type: ignore
- @pytest.fixture(scope="session")
- def app_with_thousand_pages(
- tmp_path_factory,
- ) -> Generator[AppHarness, None, None]:
- """Create an app with 1000 pages at tmp_path via AppHarness.
- Args:
- tmp_path_factory: pytest tmp_path_factory fixture
- Yields:
- an AppHarness instance
- """
- root = tmp_path_factory.mktemp("app1000")
- yield AppHarness.create(
- root=root,
- app_source=functools.partial(
- AppWithThousandPages,
- render_comp=render_multiple_pages, # type: ignore
- ),
- ) # type: ignore
- @pytest.fixture(scope="session")
- def app_with_ten_thousand_pages(
- tmp_path_factory,
- ) -> Generator[AppHarness, None, None]:
- """Create an app with 10000 pages at tmp_path via AppHarness.
- Args:
- tmp_path_factory: pytest tmp_path_factory fixture
- Yields:
- running AppHarness instance
- """
- root = tmp_path_factory.mktemp("app10000")
- yield AppHarness.create(
- root=root,
- app_source=functools.partial(
- AppWithTenThousandPages,
- render_comp=render_multiple_pages, # type: ignore
- ),
- ) # type: ignore
- @pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
- @pytest.mark.benchmark(
- group="Compile time of varying page numbers",
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_1_compile_time_cold(benchmark, app_with_one_page):
- """Test the compile time on a cold start for an app with 1 page.
- Args:
- benchmark: The benchmark fixture.
- app_with_one_page: The app harness.
- """
- def setup():
- with chdir(app_with_one_page.app_path):
- utils.empty_dir(web_pages, keep_files=["_app.js"])
- app_with_one_page._initialize_app()
- build.setup_frontend(app_with_one_page.app_path)
- def benchmark_fn():
- with chdir(app_with_one_page.app_path):
- app_with_one_page.app_instance._compile()
- benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
- app_with_one_page._reload_state_module()
- @pytest.mark.benchmark(
- group="Compile time of varying page numbers",
- min_rounds=5,
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_1_compile_time_warm(benchmark, app_with_one_page):
- """Test the compile time on a warm start for an app with 1 page.
- Args:
- benchmark: The benchmark fixture.
- app_with_one_page: The app harness.
- """
- with chdir(app_with_one_page.app_path):
- app_with_one_page._initialize_app()
- build.setup_frontend(app_with_one_page.app_path)
- def benchmark_fn():
- with chdir(app_with_one_page.app_path):
- app_with_one_page.app_instance._compile()
- benchmark(benchmark_fn)
- app_with_one_page._reload_state_module()
- @pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
- @pytest.mark.benchmark(
- group="Compile time of varying page numbers",
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_10_compile_time_cold(benchmark, app_with_ten_pages):
- """Test the compile time on a cold start for an app with 10 page.
- Args:
- benchmark: The benchmark fixture.
- app_with_ten_pages: The app harness.
- """
- def setup():
- with chdir(app_with_ten_pages.app_path):
- utils.empty_dir(web_pages, keep_files=["_app.js"])
- app_with_ten_pages._initialize_app()
- build.setup_frontend(app_with_ten_pages.app_path)
- def benchmark_fn():
- with chdir(app_with_ten_pages.app_path):
- app_with_ten_pages.app_instance._compile()
- benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
- app_with_ten_pages._reload_state_module()
- @pytest.mark.benchmark(
- group="Compile time of varying page numbers",
- min_rounds=5,
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_10_compile_time_warm(benchmark, app_with_ten_pages):
- """Test the compile time on a warm start for an app with 10 page.
- Args:
- benchmark: The benchmark fixture.
- app_with_ten_pages: The app harness.
- """
- with chdir(app_with_ten_pages.app_path):
- app_with_ten_pages._initialize_app()
- build.setup_frontend(app_with_ten_pages.app_path)
- def benchmark_fn():
- with chdir(app_with_ten_pages.app_path):
- app_with_ten_pages.app_instance._compile()
- benchmark(benchmark_fn)
- app_with_ten_pages._reload_state_module()
- @pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
- @pytest.mark.benchmark(
- group="Compile time of varying page numbers",
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_100_compile_time_cold(benchmark, app_with_hundred_pages):
- """Test the compile time on a cold start for an app with 100 page.
- Args:
- benchmark: The benchmark fixture.
- app_with_hundred_pages: The app harness.
- """
- def setup():
- with chdir(app_with_hundred_pages.app_path):
- utils.empty_dir(web_pages, keep_files=["_app.js"])
- app_with_hundred_pages._initialize_app()
- build.setup_frontend(app_with_hundred_pages.app_path)
- def benchmark_fn():
- with chdir(app_with_hundred_pages.app_path):
- app_with_hundred_pages.app_instance._compile()
- benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
- app_with_hundred_pages._reload_state_module()
- @pytest.mark.benchmark(
- group="Compile time of varying page numbers",
- min_rounds=5,
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_100_compile_time_warm(benchmark, app_with_hundred_pages):
- """Test the compile time on a warm start for an app with 100 page.
- Args:
- benchmark: The benchmark fixture.
- app_with_hundred_pages: The app harness.
- """
- with chdir(app_with_hundred_pages.app_path):
- app_with_hundred_pages._initialize_app()
- build.setup_frontend(app_with_hundred_pages.app_path)
- def benchmark_fn():
- with chdir(app_with_hundred_pages.app_path):
- app_with_hundred_pages.app_instance._compile()
- benchmark(benchmark_fn)
- app_with_hundred_pages._reload_state_module()
- @pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON)
- @pytest.mark.benchmark(
- group="Compile time of varying page numbers",
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_1000_compile_time_cold(benchmark, app_with_thousand_pages):
- """Test the compile time on a cold start for an app with 1000 page.
- Args:
- benchmark: The benchmark fixture.
- app_with_thousand_pages: The app harness.
- """
- def setup():
- with chdir(app_with_thousand_pages.app_path):
- utils.empty_dir(web_pages, keep_files=["_app.js"])
- app_with_thousand_pages._initialize_app()
- build.setup_frontend(app_with_thousand_pages.app_path)
- def benchmark_fn():
- with chdir(app_with_thousand_pages.app_path):
- app_with_thousand_pages.app_instance._compile()
- benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
- app_with_thousand_pages._reload_state_module()
- @pytest.mark.benchmark(
- group="Compile time of varying page numbers",
- min_rounds=5,
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_1000_compile_time_warm(benchmark, app_with_thousand_pages):
- """Test the compile time on a warm start for an app with 1000 page.
- Args:
- benchmark: The benchmark fixture.
- app_with_thousand_pages: The app harness.
- """
- with chdir(app_with_thousand_pages.app_path):
- app_with_thousand_pages._initialize_app()
- build.setup_frontend(app_with_thousand_pages.app_path)
- def benchmark_fn():
- with chdir(app_with_thousand_pages.app_path):
- app_with_thousand_pages.app_instance._compile()
- benchmark(benchmark_fn)
- app_with_thousand_pages._reload_state_module()
- @pytest.mark.skip
- @pytest.mark.benchmark(
- group="Compile time of varying page numbers",
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_10000_compile_time_cold(benchmark, app_with_ten_thousand_pages):
- """Test the compile time on a cold start for an app with 10000 page.
- Args:
- benchmark: The benchmark fixture.
- app_with_ten_thousand_pages: The app harness.
- """
- def setup():
- with chdir(app_with_ten_thousand_pages.app_path):
- utils.empty_dir(web_pages, keep_files=["_app.js"])
- app_with_ten_thousand_pages._initialize_app()
- build.setup_frontend(app_with_ten_thousand_pages.app_path)
- def benchmark_fn():
- with chdir(app_with_ten_thousand_pages.app_path):
- app_with_ten_thousand_pages.app_instance._compile()
- benchmark.pedantic(benchmark_fn, setup=setup, rounds=5)
- app_with_ten_thousand_pages._reload_state_module()
- @pytest.mark.skip
- @pytest.mark.benchmark(
- group="Compile time of varying page numbers",
- min_rounds=5,
- timer=time.perf_counter,
- disable_gc=True,
- warmup=False,
- )
- def test_app_10000_compile_time_warm(benchmark, app_with_ten_thousand_pages):
- """Test the compile time on a warm start for an app with 10000 page.
- Args:
- benchmark: The benchmark fixture.
- app_with_ten_thousand_pages: The app harness.
- """
- def benchmark_fn():
- with chdir(app_with_ten_thousand_pages.app_path):
- app_with_ten_thousand_pages.app_instance._compile()
- benchmark(benchmark_fn)
- app_with_ten_thousand_pages._reload_state_module()
|