Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.bat text eol=crlf
*.sh text eol=lf
*.command text eol=lf
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: CI

on:
push:
branches: [main]
pull_request:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
- name: Lint
run: |
uvx ruff check evolve_charts tests tools evolve-charts.py
uvx ruff format --check evolve_charts tests tools evolve-charts.py
# Test against exactly the libraries the download installs (evolve-charts.py.lock).
- name: Install
run: |
uv venv --python 3.12
uv export --script evolve-charts.py --no-hashes > requirements.txt
uv pip install -r requirements.txt pytest
- name: Test
run: uv run --no-project pytest -q
32 changes: 32 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Release Evolve Charts

# Push a tag like v1.0.0 to publish a release. Its download is always at
# https://github.com/Traverse-Research/evolve-scripts/releases/latest/download/Evolve-Charts.zip
on:
push:
tags: ["v*"]

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
- name: Test
run: |
uv venv --python 3.12
uv export --script evolve-charts.py --no-hashes > requirements.txt
uv pip install -r requirements.txt pytest
uv run --no-project pytest -q
- name: Package
run: python3 tools/package.py "${GITHUB_REF_NAME#v}"
- name: Publish
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "$GITHUB_REF_NAME" dist/Evolve-Charts.zip \
--title "Evolve Charts ${GITHUB_REF_NAME#v}" \
--notes "Download **Evolve-Charts.zip**, extract it, and double-click *Start Evolve Charts*. See *HOW TO START.txt* inside the zip."
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
__pycache__/
.venv/
.pytest_cache/
exports/*
!exports/README.txt
dist/
VERSION
requirements.txt
52 changes: 52 additions & 0 deletions .streamlit/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Evolve Charts settings. `evolve-charts.py` starts Streamlit from this folder so it picks them up.

[server]
# Keep everything on this computer: only reachable from this machine.
address = "localhost"
# Evolve exports with deep analysis are several hundred megabytes.
maxUploadSize = 2048
# Serves `static/`: the Spartan font and the Evolve logo.
enableStaticServing = true

[browser]
gatherUsageStats = false

[client]
toolbarMode = "minimal"

# Evolve's look, from `evolve/crates/evolve/src/ui/styling.rs`.
[theme]
base = "dark"
# RED_MEDIUM: Evolve's primary (orange) buttons
primaryColor = "#FD663A"
# GREEN_DARKER: the background panel
backgroundColor = "#0D3618"
# GREEN_DARK: panels and widgets
secondaryBackgroundColor = "#0F3F1D"
# Evolve's text colour on green
textColor = "#EFEEF0"
# GREEN_MEDIUM
borderColor = "#3E703C"
dataframeBorderColor = "#3E703C"
dataframeHeaderBackgroundColor = "#0F3F1D"
linkColor = "#FD663A"
greenColor = "#94C191"
redColor = "#CC3232"
orangeColor = "#FD663A"
yellowColor = "#F8DD49"
blueColor = "#619CD9"
# BUTTON_ROUNDING
baseRadius = "4px"
font = "Spartan, sans-serif"
headingFont = "Spartan, sans-serif"
headingFontWeights = 700

[[theme.fontFaces]]
family = "Spartan"
url = "app/static/Spartan-Regular.ttf"
weight = 400

[[theme.fontFaces]]
family = "Spartan"
url = "app/static/Spartan-Bold.ttf"
weight = 700
145 changes: 107 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,115 @@
<div align="center">

# 📜 Evolve scripts
# 📊 Evolve Charts

**Evolutionary benchmarking software**
**Turn Evolve deep analysis exports into publication-ready charts**

[![Banner](./docs/images/banner.png)](https://traverseresearch.nl)

</div>

## 👷‍♀️ Requirements

Please ensure the following dependencies are installed before running scripts from this repository:

- Python 3.7
- ADB (Android Debug Bridge)


## 📊 Comparing deep analysis output

Using the `compare_deep_analysis.py` script located in the `scripts` directory, you can compare the results of two separate deep analysis output files in multiple ways. For the analysis methods, the scripts will first do an attempt to average over all loop iterations of the output. If you ran Evolve with `--looping 5`, each frame in the output will use the mean from each frame from each of the Evolve benchmark iterations.

## Additional Requirements
In addition to the requirements listed in [Requirements](#👷‍♀️-requirements), this script also requires the use of several python packages. These can be installed as follows:

```sh
python -m pip install -r requirements.txt
```

## Usage
```sh
usage: Evolve Deep Analysis Comparison [-h] [--pass_mean_comparison PASS_MEAN_COMPARISON] [--pass_stdev_comparison PASS_STDEV_COMPARISON] deep_analysis_file deep_analysis_file
```

### Parameters:

- `deep_analysis_file` - The path(s) to the input files to compare, produced by Evolve's deep analysis.
- `--pass_mean_comparison [filename]` - The csv file to which to output a comparison of the mean execution times of the render passes with the highest difference in mean execution times between the two. Example: `--pass_mean_comparison mean_difference.csv`.
- `--pass_stdev_comparison [filename]` - The csv file to which to output a comparison of the standard deviation over execution times of the render passes with the highest difference in standard deviation over the execution time, between the two. Example: `--pass_stdev_comparison stdev_difference.csv`.

At least one of `--pass_mean_comparison` or `--pass_stdev_comparison` arguments is required, as the script doesn't output any information by default.

### Example usage
```sh
python compare_deep_analysis.py --pass_mean_comparison mean_comparison.csv --pass_stdev_comparison stdev_comparison.csv deep_analysis_gpu_1.json deep_analysis_gpu_2.json
```
Evolve Charts compares Evolve benchmark results: scores, GPU time per workload category and per pass,
and GPU sensors, across GPUs and settings. You don't need to know Python or git. It opens as a page in
your web browser, and **everything stays on your computer**. Nothing is uploaded.

## ⬇️ Download

**[Download Evolve Charts (Evolve-Charts.zip)](https://github.com/Traverse-Research/evolve-scripts/releases/latest/download/Evolve-Charts.zip)**

1. **Extract the zip.** Right-click it and choose **Extract All…** (Windows) or double-click it (macOS),
for example to your Desktop. Don't start the tool from inside the zip.
2. **Start the tool** from the extracted *Evolve Charts* folder:
- **Windows:** double-click **Start Evolve Charts**. If Windows warns about the file, click
**More info › Run anyway**.
- **macOS:** right-click **Start Evolve Charts.command** and choose **Open** (the first time only;
after that a double-click works).
- **Linux:** run `./start-evolve-charts.sh` in a terminal.

The first start installs [uv](https://docs.astral.sh/uv/), a small helper that downloads Python and
the libraries the tool uses (about 150 MB). This needs an internet connection, takes a few minutes and
only happens once. Keep the window that opens running while you use the tool; close it when you're
done.
3. **Export your results from Evolve.** After a benchmark run, click **Export** on the score screen. Do
this on every GPU or setting you want to compare, using the same benchmark on each. Scores and
per-frame data are always included; deep analysis (per-pass timings) needs an Evolve Professional
licence.
4. **Add your results.** Your browser opens Evolve Charts. Drag the export files onto *Add Evolve
exports*, or put them in the `exports` folder so they load automatically every time.
5. **Name your results** on their cards (for example "RTX 4070 Ti" or "Gen 1"). These names appear in
every chart.

To update, download the zip again and replace the old folder (keep your `exports` folder if you use it).

## 🗺️ What's in the tool

The tool reads every Evolve export: the **Export** zip from the score screen, and the files Evolve's
command line writes (`evolve_results.csv`, `scores.csv`, the per-frame CSV and `deep_analysis.json`).
It has a page per question, in the bar at the top:

| Page | What it shows | Needs |
|---|---|---|
| **Results** | Load and name exports; GPU, driver, OS, Evolve version and what each file contains | |
| **Scores** | Evolve's scores side by side, with the workload category each one scores, and the differences | scores |
| **GPU time** | Where the GPU spends its time each frame, per workload category; then one workload category over the run and the passes it's made of | per-frame data; the passes need deep analysis |
| **Passes** | Every render pass in one searchable table; tick passes to plot them over the run | deep analysis |
| **GPU sensors** | Clocks, power, temperature and more during the run, to spot throttling | per-frame data |
| **Export** | CSV files for Excel, Google Sheets, Datawrapper and Flourish | |

On every page except Results, a bar at the top shows the loaded results and lets you pick the one to
**compare against**.

**How Evolve measures a GPU.** Evolve times **passes**: single blocks of GPU work. A **workload
category** is GPU work that logically belongs together, and what Evolve scores. All ray tracing work,
such as the *shadow-raytrace-inline* pass, is the *Raytracing* workload: the *Ray Tracing* score. There is
one score per workload category and no total score.

**Downloading a chart:** hover over it and click the 📷 camera icon in its top-right corner. Use
**Charts** at the top right to choose PNG or SVG and whether charts get a source line with the GPUs,
drivers and Evolve version. **Help** explains how the numbers are made.

## 📏 How to read the numbers

- **GPU time per frame** is how long the GPU spent on that work, averaged over every frame of the
run. The first second is skipped because it includes one-off setup work. Lines over time are
smoothed over one second.
- Passes Evolve doesn't assign to a workload category (such as drawing the user interface) are left
out; the *GPU time* page says how much that is.
- Workload categories add up to the GPU work shown. That can differ a little from the time between frames,
because a GPU can idle between passes or run passes at the same time.
- **Whiskers** on bar charts show the range covering 90% of frames (5th to 95th percentile).
- Only compare results from the **same Evolve version and benchmark settings**. The tool warns you
when the Evolve versions or graphics APIs differ.

## ❓ Troubleshooting

- **A result is missing from *Passes***: its export has no deep analysis, which
needs an Evolve Professional licence. Its card shows ✗ Deep analysis; scores and workload
categories still work.
- **The browser doesn't open**: open <http://localhost:8501> yourself while the black window is open.
- **Anything else**: send a screenshot of the black window to Traverse Research.

## 🛠️ For developers

- Run without the launcher: `uv run evolve-charts.py`. Dependencies are declared inline
([PEP 723](https://peps.python.org/pep-0723/)), so no virtual environment is needed.
- Code lives in `evolve_charts/`:
- `loader.py` reads export zips into tidy tables.
- `categories.py` describes Evolve's workload categories and which pass belongs to which.
- `stats.py` computes the summaries.
- `charts.py` builds the Plotly figures.
- `ui.py` is the Streamlit page.
- The look follows Evolve's `crates/evolve/src/ui/styling.rs`: theme colours and the Spartan font are set in
`.streamlit/config.toml`, and the fonts, logo and icon live in `static/`. Chart colours are in `charts.py`.
- Which pass belongs to which workload category comes from Evolve's Rust source. After pass names
change in Evolve, regenerate the list with `python tools/sync_categories.py` (it reads
`../evolve/crates/evolve-frame-bucketing/src/lib.rs` by default).
- Dependencies are locked in `evolve-charts.py.lock`; refresh it with `uv lock --script evolve-charts.py --upgrade`.
- Tests: `uv export --script evolve-charts.py --no-hashes > requirements.txt`, then
`uv venv && uv pip install -r requirements.txt pytest && uv run --no-project pytest`. CI runs the same.
- Releases: push a tag like `v1.0.0`. The release workflow tests, runs `tools/package.py` and attaches
`Evolve-Charts.zip` to a GitHub release; the download link above always points to the newest one.

## 📱 Other scripts

- `scripts/run_on_android.py` starts Evolve on an Android device with command-line arguments. See
[docs/Android.md](docs/Android.md).
36 changes: 36 additions & 0 deletions Start Evolve Charts.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@echo off
rem Double-click this file to start Evolve Charts. A page opens in your browser.
cd /d "%~dp0"
set "PATH=%USERPROFILE%\.local\bin;%PATH%"

if not exist "evolve-charts.py" (
echo Evolve Charts can't start from inside the zip file.
echo Right-click the zip, choose "Extract All...", then open the extracted folder
echo and double-click "Start Evolve Charts" there.
echo.
pause
exit /b 1
)

where uv >nul 2>nul
if errorlevel 1 (
echo Evolve Charts needs "uv" to download Python and the libraries it uses.
echo It will now be installed for your user account from https://astral.sh/uv
echo.
powershell -NoProfile -ExecutionPolicy ByPass -Command "irm https://astral.sh/uv/install.ps1 | iex"
if errorlevel 1 goto failed
)

echo Starting Evolve Charts. The first start downloads Python and the libraries it uses
echo (about 150 MB) and can take a few minutes; later starts are quick.
echo Keep this window open while you use the tool; close it to stop.
echo.
uv run evolve-charts.py
if errorlevel 1 goto failed
exit /b 0

:failed
echo.
echo Something went wrong. Please send a screenshot of this window to Traverse Research.
pause
exit /b 1
8 changes: 8 additions & 0 deletions Start Evolve Charts.command
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh
# Double-click this file on macOS to start Evolve Charts. A page opens in your browser.
cd "$(dirname "$0")"
if ! sh ./start-evolve-charts.sh; then
echo
echo "Something went wrong. Please send a screenshot of this window to Traverse Research."
read -r _
fi
36 changes: 36 additions & 0 deletions evolve-charts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "streamlit>=1.65",
# "plotly>=6",
# "pandas>=2.2",
# ]
# ///
"""Evolve Charts: turn Evolve deep analysis exports into charts.

Start it by double-clicking `Start Evolve Charts.bat` (Windows) or `start-evolve-charts.sh`
(macOS/Linux), or run `uv run evolve-charts.py`. A page opens in your browser; nothing leaves
your computer.
"""

import os
import sys
from pathlib import Path

from streamlit.runtime.scriptrunner import get_script_run_ctx

HERE = Path(__file__).resolve().parent

# Under `streamlit run` this file is executed inside a script run; started directly, it relaunches itself that way.
if get_script_run_ctx(suppress_warning=True) is not None:
sys.path.insert(0, str(HERE))
from evolve_charts.ui import main

main()
else:
from streamlit.web import cli

# Streamlit reads `.streamlit/config.toml` (theme, privacy and upload settings) from the working directory.
os.chdir(HERE)
sys.argv = ["streamlit", "run", str(HERE / "evolve-charts.py"), *sys.argv[1:]]
sys.exit(cli.main())
Loading
Loading