Files

107 lines
3.5 KiB
Markdown

# Django LiveView vs Phoenix LiveView: a real benchmark
A reproducible, Docker-based benchmark comparing **django-liveview** (WebSocket + Django Channels + Stimulus) against **Phoenix LiveView** (WebSocket + BEAM + LiveView diffs).
Both apps implement an identical alert dashboard: add, delete, and search alerts in real time. The benchmark is fully automated with Playwright headless Chromium.
---
## Stack versions
| Component | Django LiveView | Phoenix LiveView |
| --- | --- | --- |
| Language | Python 3.12 | Elixir 1.17.3 / OTP 27 |
| Framework | Django 6.0.5 | Phoenix 1.7 |
| LiveView lib | django-liveview 2.2.0 | phoenix_live_view 1.0 |
| WS layer | Channels 4.3.2 + channels-redis 4.3.0 | Built-in (BEAM) |
| HTTP server | Uvicorn 0.47.0 | Bandit 1.5 |
| Database | PostgreSQL 16 | PostgreSQL 16 |
| Cache/broker | Redis 7 | — |
---
## How each framework works
| | Django LiveView | Phoenix LiveView |
| --- | --- | --- |
| Transport | WebSocket (Django Channels) | WebSocket (BEAM) |
| Updates | Explicit HTML snippets per selector | Automatic template diffs |
| State | Stateless (DB per action) | In-memory assigns + DB for mutations |
| JS | liveview.js (Stimulus + WS client) | phoenix_live_view.js |
| Server | Uvicorn (ASGI) | Bandit (HTTP/WS) |
---
## Scenarios
### Common (10 iterations, 2 warmup)
| # | Scenario | What it measures |
| --- | --- | --- |
| 1 | **Add alert** | Click → new row appears (append) |
| 2 | **Delete alert** | Click → row disappears |
| 3 | **Search / filter** | Input → filtered list rendered |
### Edge cases (5 iterations, 1 warmup)
| # | Scenario | What it measures |
| --- | --- | --- |
| 4 | **Add to large list** | Add one alert with 500 already loaded |
| 5 | **Rapid fire** | 5 consecutive clicks (50 ms apart) → all 5 rows appear |
| 6 | **Empty search** | Search for non-existent term → empty state |
---
## Results
Full results, charts, and analysis are available in the article:
[Django LiveView vs Phoenix LiveView: a real benchmark](https://en.andros.dev/blog/80134668/django-liveview-vs-phoenix-liveview-a-real-benchmark/)
---
## How to run
### 1. Start the apps
```bash
docker compose up --build -d django phoenix
```
Wait until both are healthy (check `docker compose ps`).
### 2. Run the benchmark
```bash
docker compose --profile bench run --rm benchmark
```
Results land in `./results/` as:
- `results_<timestamp>.csv` — raw per-iteration data
- `report_<timestamp>.md` — summary tables (replace the placeholders above)
### 3. Manual exploration
| App | URL |
| --- | --- |
| Django LiveView | http://localhost:8001 |
| Phoenix LiveView | http://localhost:8002 |
---
## Benchmark methodology
- **Timing**: wall-clock `time.perf_counter()` from DOM action to DOM mutation detected by Playwright.
- **WS payload**: Playwright `framesent` / `framereceived` events summed per interaction.
- **Warmup**: first N iterations discarded (default 2 for common, 1 for edge cases).
- **DB state**: cleared via HTTP `/bench/clear/` before each scenario; pre-populated via `/bench/populate/?count=N` where needed.
- **WS ready**: benchmark waits for `#ws-status` to read `"connected"` before starting.
- **Browser**: headless Chromium via Playwright.
---
## Related work
- [django-interactive-frameworks-benchmark](https://github.com/tanrax/django-interactive-frameworks-benchmark) — previous benchmark comparing multiple Django interactive frameworks.
- [django-liveview](https://github.com/tanrax/django-liveview) — the Django LiveView package used here.