Skip to main content

gilviz

PyPI

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 compare runs the same prime-counting workload with threads and processes, then compares it to an asyncio I/O workload.
  • gilviz live opens a browser dashboard and streams sampled thread activity into a canvas-based timeline view.
  • gilviz free-threaded checks whether the interpreter exposes the CPython 3.13+ free-threaded switch and compares threaded performance against multiprocessing.
  • gilviz export writes 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:

  1. src/workloads.py defines a pure-Python prime counter and a small I/O sleep workload.
  2. src/sampler.py samples sys._current_frames() at a very fine interval and infers which thread is advancing between samples.
  3. src/sessions.py runs the workload under a ThreadPoolExecutor while the sampler is active and returns a SampleRun object.
  4. src/browser.py exposes a FastAPI app and a WebSocket endpoint that pushes sample batches to the browser.
  5. 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-spy is a low-overhead sampler and profiler for live Python processes.
  • VizTracer focuses on detailed trace visualization and profiling output.
  • gil_load is 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

gilviz-0.1.0.tar.gz (16.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gilviz-0.1.0-py3-none-any.whl (19.5 kB view details)

Uploaded Python 3

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

Hashes for gilviz-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b289fefe32251cf24b9c2176e42342ab3873488375cfb44b650a50042d53c7c4
MD5 f670ae945d95cd4346e949b94f9451c0
BLAKE2b-256 b73cf44f095377cf1bc3aa4369e7595edda094c7d00fd225bcf39f6272e68abb

See more details on using hashes here.

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

Hashes for gilviz-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6a6706d33a5a4944d2ceb07cc0a70e209672b76325fc554c36007514fe12ebb8
MD5 a4bc35403da827d5ac5545e20c755139
BLAKE2b-256 98151aaf41498a3cab66c049e36ec8e606885d94a613b29ce4abf95e6752caee

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.1

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page