gilviz
gilviz is a small Python project that turns the GIL from a vague interview topic into something you can watch, measure, and explain.
It combines three things that are usually shown separately:
- a CPU-bound benchmark that highlights why the GIL limits threaded throughput,
- a browser dashboard that streams sampled thread activity in real time,
- export and comparison modes that produce data you can reuse in reports, blog posts, or portfolio writeups.
The project is intentionally simple in the workload it runs, but it is intentionally modern in the way it presents the result: FastAPI, WebSockets, a browser-based Gantt chart, and a free-threaded Python comparison path for CPython 3.13+.
Why this project matters
Most Python concurrency demos stop at “threads are slow for CPU work.” That is true, but not memorable. gilviz is designed to show the mechanism rather than just the conclusion.
That matters because it demonstrates a few things interviewers and reviewers care about:
- you can build a small tool around a concrete systems problem,
- you know how to connect a backend sampler to a live UI,
- you can measure behavior and export the data instead of hand-waving it,
- you know enough about modern Python to talk about free-threaded builds, not just the traditional GIL runtime.
What it shows
gilviz focuses on four visible outcomes:
gilviz compareruns the same prime-counting workload with threads and processes, then compares it to an asyncio I/O workload.gilviz liveopens a browser dashboard and streams sampled thread activity into a canvas-based timeline view.gilviz free-threadedchecks whether the interpreter exposes the CPython 3.13+ free-threaded switch and compares threaded performance against multiprocessing.gilviz exportwrites the collected samples to JSON or CSV for follow-up plotting with tools like matplotlib or pandas.
How it works
The internal flow is deliberately straightforward:
src/workloads.pydefines a pure-Python prime counter and a small I/O sleep workload.src/sampler.pysamplessys._current_frames()at a very fine interval and infers which thread is advancing between samples.src/sessions.pyruns the workload under aThreadPoolExecutorwhile the sampler is active and returns aSampleRunobject.src/browser.pyexposes a FastAPI app and a WebSocket endpoint that pushes sample batches to the browser.- The browser renders a live canvas chart and a small stats panel so you can see the activity instead of reading raw logs.
The important design choice is that the data is collected once and then reused in multiple views. The same samples can drive the browser UI, the export command, and the benchmark summary.
Benchmark snapshot
The numbers below are representative results from this workspace on Windows with Python 3.12. They are not meant to be universal performance claims, because CPU model, OS scheduling, and interpreter build all change the result.
| Command | What it measures | Result |
|---|---|---|
gilviz compare threading |
CPU-bound prime counting with threads | 1.07s |
gilviz compare multiprocessing |
Same CPU-bound workload with processes | 0.64s |
gilviz compare asyncio |
I/O-bound sleep workload | 1.02s |
| Inferred GIL handoffs | Thread switches observed during the sampled run | 7 |
If you want to update the table for a new machine, rerun gilviz compare and replace the values with the numbers you observe.
Related work
Tools like py-spy, VizTracer, and gil_load already cover important parts of Python performance visibility.
py-spyis a low-overhead sampler and profiler for live Python processes.VizTracerfocuses on detailed trace visualization and profiling output.gil_loadis aimed specifically at GIL contention and related measurements.
gilviz is intentionally different. It is not trying to out-profile those tools. Instead, it is a teaching and presentation project: simple workload, real-time browser visualization, inferred handoff counting, exportable sample data, and a free-threaded comparison path. That makes it better suited to demos, interviews, blog posts, and portfolio discussions.
Installation
Install it in editable mode during development:
uv pip install -e .
The project uses an editable package layout so the gilviz command is available after install.
Usage
Compare the concurrency models:
gilviz compare
Open the browser dashboard:
gilviz live
Inspect the current interpreter’s free-threaded status:
gilviz free-threaded
Export samples for later plotting or reporting:
gilviz export --output gilviz-samples.json --format json
gilviz export --output gilviz-samples.csv --format csv
Run without installing globally:
uv run gilviz compare
uv run gilviz live
Browser dashboard
gilviz live starts a FastAPI server and opens a browser page that receives sample batches over WebSocket.
The page shows:
- a live sample count,
- the inferred handoff count,
- the number of worker threads being tracked,
- the interpreter status label,
- a canvas-based timeline of which thread appears to be running over time.
If the dashboard shows zeroes, it usually means the browser connected before the run had emitted enough samples, or the runtime environment is missing the WebSocket dependency. Reinstalling with uv pip install -e . refreshes the environment and includes the required runtime packages.
Export format
gilviz export writes the sampled run to disk so you can post-process it with pandas, matplotlib, or your own reporting script.
- JSON keeps the full nested structure, including the per-sample thread state map.
- CSV expands the samples into rows that are easy to filter or chart in spreadsheet tools.
Free-threaded mode
CPython 3.13 introduced a free-threaded build option that can run without the GIL. gilviz free-threaded checks whether the interpreter exposes that capability and then compares threaded CPU-bound execution against the same process-based baseline.
That is valuable because it lets you demonstrate the difference between “threads are limited by the GIL” and “threads can scale when the runtime removes that lock.” Even if you are not on a free-threaded build locally, the command documents the concept and the code path.
Terminal recording GIF
The repository includes a VHS script so you can generate a terminal recording GIF for the project page or README.
Script:
To render it with VHS after installing the tool:
vhs demo.tape
If you prefer asciinema, record the same commands with asciinema and convert the result to a GIF using your preferred converter.
Fresh install check
This is the installation smoke test used during development:
uv venv --python 3.12 /tmp/test-env
source /tmp/test-env/bin/activate
uv pip install -e .
gilviz compare
On Windows, the equivalent is to create a temporary venv, install the package into that interpreter, and run gilviz compare from the generated console script.
Publishing
When you are ready to publish a release to PyPI, the intended flow is:
uv build
uv publish
The publish step requires valid PyPI credentials configured in your environment. I can prepare the package and verify the build, but I cannot complete the actual upload without your PyPI token or trusted publishing configuration.
Tests and linting
Run the deterministic checks locally with:
uv run pytest tests/test_workloads.py tests/test_sampler.py tests/test_exporting.py
uv run ruff check src/ tests/
uv run ruff format src/ tests/
Project layout
gilviz/
├── gilviz/ # Public import wrappers for the package name used by the CLI/tests
├── src/ # Implementation modules
├── tests/ # Deterministic tests
├── demo.tape # VHS terminal recording script
├── README.md
├── LICENSE
└── pyproject.toml
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gilviz-0.1.0.tar.gz.
File metadata
- Download URL: gilviz-0.1.0.tar.gz
- Upload date:
- Size: 16.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.9.10 {"installer":{"name":"uv","version":"0.9.10"},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b289fefe32251cf24b9c2176e42342ab3873488375cfb44b650a50042d53c7c4
|
|
| MD5 |
f670ae945d95cd4346e949b94f9451c0
|
|
| BLAKE2b-256 |
b73cf44f095377cf1bc3aa4369e7595edda094c7d00fd225bcf39f6272e68abb
|
File details
Details for the file gilviz-0.1.0-py3-none-any.whl.
File metadata
- Download URL: gilviz-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.9.10 {"installer":{"name":"uv","version":"0.9.10"},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a6706d33a5a4944d2ceb07cc0a70e209672b76325fc554c36007514fe12ebb8
|
|
| MD5 |
a4bc35403da827d5ac5545e20c755139
|
|
| BLAKE2b-256 |
98151aaf41498a3cab66c049e36ec8e606885d94a613b29ce4abf95e6752caee
|