FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

#!/usr/bin/env python3 """Measure incremental list work with deterministic bounds and JSON output. Run ``python scripts/benchmark-rendering.py --rows 100000 --edits 20``. The headless renderer measures Python preparation, reconciliation, and wire work, not device frame rate. Native phase timings come from PN_PROFILE traces. """ from __future__ import annotations import argparse import json import platform import statistics import time from dataclasses import dataclass from typing import Any import pythonnative as pn from pythonnative.bridge import codec from pythonnative.profiling import Profiler from pythonnative.testing import render @dataclass(frozen=True) class Item: """Immutable application record with stable identity.""" key: str title: str def row(item: Item, index: int) -> pn.Element: """Keep the renderer stable so only actual data changes invalidate rows.""" return pn.Text(f"{index}: {item.title}") def benchmark(size: int, edits: int, incremental: bool) -> dict[str, Any]: """Report work for one-item edits after the initial snapshot is committed.""" initial = [Item(str(i), str(i)) for i in range(size)] data = pn.ListData(initial, key=lambda item: item.key) if incremental else initial result = render(pn.FlatList(data=data, render_item=row, item_height=44), viewport=None) durations, sizes = [], [] with Profiler() as profile: for edit in range(edits): started = time.perf_counter_ns() replacement = Item("0", f"edit {edit}") if isinstance(data, pn.ListData): data.update("0", replacement) result.settle() else: data = [replacement, *data[1:]] result.rerender(pn.FlatList(data=data, render_item=row, item_height=44)) durations.append((time.perf_counter_ns() - started) / 1e6) packet = result.get_by_type("VirtualList").props["dataset"] sizes.append(len(codec.dumps(packet).encode())) mounted = result.backend.live_view_count() report = { "source": "ListData" if incremental else "Sequence", "rows": size, "edits": edits, "median_ms": statistics.median(durations), "max_ms": max(durations), "max_dataset_bytes": max(sizes), "mounted_views": mounted, **profile.summary(), } result.unmount() assert result.backend.live_view_count() == 0 if incremental: assert profile.counters["list.snapshot_rows"] == 0 assert profile.counters["list.incremental_changes"] == edits assert profile.counters["list.rows_validated"] == edits assert max(sizes) < 128 and mounted < 128 return report def main() -> None: """Compare the intentional sequence adapter with a keyed incremental source.""" parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--rows", type=int, default=100_000) parser.add_argument("--edits", type=int, default=20) args = parser.parse_args() if args.rows < 1 or args.edits < 1: parser.error("rows and edits must be positive") print( json.dumps( { "environment": { "python": platform.python_version(), "system": platform.platform(), "renderer": "headless; timings include profiling", }, "results": [benchmark(args.rows, args.edits, mode) for mode in (False, True)], }, indent=2, ) ) if __name__ == "__main__": main()

Back | FazBrowse Home | New Git URL