forked from reflex-dev/reflex
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
simple pytest benchmark for measuring event <=> state update round tr…
…ip time (reflex-dev#2489)
- Loading branch information
Showing
2 changed files
with
108 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
"""Test large state.""" | ||
import time | ||
|
||
import jinja2 | ||
import pytest | ||
from selenium.webdriver.common.by import By | ||
|
||
from reflex.testing import AppHarness, WebDriver | ||
|
||
LARGE_STATE_APP_TEMPLATE = """ | ||
import reflex as rx | ||
class State(rx.State): | ||
var0: int = 0 | ||
{% for i in range(1, var_count) %} | ||
var{{ i }}: str = "{{ i }}" * 10000 | ||
{% endfor %} | ||
def increment_var0(self): | ||
self.var0 += 1 | ||
def index() -> rx.Component: | ||
return rx.box(rx.button(State.var0, on_click=State.increment_var0, id="button")) | ||
app = rx.App() | ||
app.add_page(index) | ||
""" | ||
|
||
|
||
def get_driver(large_state) -> WebDriver: | ||
"""Get an instance of the browser open to the large_state app. | ||
Args: | ||
large_state: harness for LargeState app | ||
Returns: | ||
WebDriver instance. | ||
""" | ||
assert large_state.app_instance is not None, "app is not running" | ||
return large_state.frontend() | ||
|
||
|
||
@pytest.mark.parametrize("var_count", [1, 10, 100, 1000, 10000]) | ||
def test_large_state(var_count: int, tmp_path_factory, benchmark): | ||
"""Measure how long it takes for button click => state update to round trip. | ||
Args: | ||
var_count: number of variables to store in the state | ||
tmp_path_factory: pytest fixture | ||
benchmark: pytest fixture | ||
Raises: | ||
TimeoutError: if the state doesn't update within 30 seconds | ||
""" | ||
template = jinja2.Template(LARGE_STATE_APP_TEMPLATE) | ||
large_state_rendered = template.render(var_count=var_count) | ||
|
||
with AppHarness.create( | ||
root=tmp_path_factory.mktemp(f"large_state"), | ||
app_source=large_state_rendered, | ||
app_name="large_state", | ||
) as large_state: | ||
driver = get_driver(large_state) | ||
try: | ||
assert large_state.app_instance is not None | ||
button = driver.find_element(By.ID, "button") | ||
|
||
t = time.time() | ||
while button.text != "0": | ||
time.sleep(0.1) | ||
if time.time() - t > 30.0: | ||
raise TimeoutError("Timeout waiting for initial state") | ||
|
||
times_clicked = 0 | ||
|
||
def round_trip(clicks: int, timeout: float): | ||
t = time.time() | ||
for _ in range(clicks): | ||
button.click() | ||
nonlocal times_clicked | ||
times_clicked += clicks | ||
while button.text != str(times_clicked): | ||
time.sleep(0.005) | ||
if time.time() - t > timeout: | ||
raise TimeoutError("Timeout waiting for state update") | ||
|
||
benchmark(round_trip, clicks=10, timeout=30.0) | ||
finally: | ||
driver.quit() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters