VizTracer: A Python Tracer That Writes Perfetto-Compatible Traces
A debugging and profiling tool that can trace and visualize python code execution
At a glance
- What is it?
- VizTracer records function entry and exit events from an unmodified Python program and renders them in a Perfetto timeline. It is the right tool when you need to see when code ran, not just how long it took.
- Who is it for?
- Adopt VizTracer if you need to see when functions actually ran, across threads, processes and async tasks, and you can afford a JSON trace on disk. Do not adopt it if you need per-line timing on a production service or you cannot install a compiled extension.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap VizTracer fills between cProfile and a debugger
cProfile answers how much total time a function consumed. It does not answer when that function ran relative to everything else, which is the question that matters when a request handler blocks on a lock, a background thread stalls the event loop, or a subprocess starts later than expected. A debugger answers the ordering question, but you have to step through execution to get there, and stepping changes what you observe.
VizTracer records entry and exit events on a shared timeline instead. The README describes it as a low-overhead logging, debugging and profiling tool that can trace and visualize Python code execution. The audience is anyone debugging concurrency or ordering problems in Python: threaded servers, multiprocessing pipelines, async code, and PyTorch training loops where GPU events and host calls need to be read together. The repository topics list debugging, flamegraph, logging, profiling, python3, tracer and visualization, which matches that positioning.
How the trace is produced and where the timeline comes from
There are two halves. The tracer hooks function entry and exit and writes events to a JSON file, conventionally result.json. The viewer reads that file and renders it in a browser using Perfetto as the front-end. The README states that the front-end UI is powered by Perfetto and that AWSD keys zoom and navigate the timeline.
The tracing core is not pure Python. The repository's setup.py declares an extension module named viztracer.snaptrace built from C sources under src/viztracer/modules/, including snaptrace.c, eventnode.c and quicktime.c. That is where the claimed low overhead comes from, and it also means the package ships platform-specific binaries. The same setup.py shows attach_process payloads selected by platform: DLLs and an inject_dll executable on Windows, a dylib on macOS, and .so files for i686 and x86_64 on Linux. The runtime dependency list in pyproject.toml is short, just objprint, with orjson as an optional extra under the full extra. The README's claim of no package dependency refers to the traced program, not to VizTracer's own install.
Event data can be filtered before it is written. The README links documentation pages for min duration, max stack depth, include files, exclude files, ignore C function and sparse log. Extra log modes capture variables, function arguments, return values, garbage collector activity, audit events and raised exceptions without editing the traced source.
Installing VizTracer and reading a first trace
The README gives pip as the preferred install path. Python 3.10 or newer is required according to pyproject.toml, and classifiers cover 3.10 through 3.14 plus free-threaded builds.
pip install viztracerRun an existing script under the tracer by putting viztracer where python3 would go. Arguments are passed through to the script, and a result.json file appears in the working directory.
viztracer my_script.py arg1 arg2Open the trace with vizviewer. The README states that vizviewer hosts an HTTP server on http://localhost:9001 and opens a browser at that address.
vizviewer result.jsonFor very large traces the README suggests an external trace processor, and there are flags for headless and one-shot use. If you would rather trace a section of code directly, the inline API is three calls.
from viztracer import VizTracer
tracer = VizTracer()
tracer.start()
# Something happens here
tracer.stop()
tracer.save()The README also documents a context manager form with an optional output_file argument, module execution via viztracer -m your_module, console scripts such as viztracer flask run, Jupyter cell magics loaded with %load_ext viztracer, and PyTorch tracing through --log_torch. What you should see after the first run is a browser tab with a timeline of nested function bars; if the page is empty, check that result.json was written in the directory you launched vizviewer from.
Where the trace-everything approach breaks down
The output format is the main constraint. A trace of a long-running program is a JSON file that grows with every recorded event, and the README's own pitch that the front-end can render GB-level traces acknowledges that files reach that size. On a service that runs for hours, tracing everything is not viable without filters, and the filters change what you see. Min duration filtering hides short calls, which is exactly what you may be hunting for.
The second constraint is the compiled extension. A pure-Python fallback is not described in the README, and setup.py builds snaptrace from C sources. On a platform without a matching wheel, installation depends on a working compiler toolchain, which rules out some locked-down or minimal container images. The attach_process binaries are also platform-specific, so any workflow that attaches to an already-running interpreter is limited to the platforms listed in setup.py.
Threading has a version boundary. The README states that Python 3.12 and later support Python-level multi-thread tracing without code modification, and that earlier versions need something else, a sentence the truncated README does not finish. If you are on 3.10 or 3.11 and rely on threads, treat that as unverified until you read the multi-thread section of the documentation. Finally, VizTracer is not a sampling profiler. It records events, so it tells you about call structure and ordering, not about CPU cache behaviour or instruction-level hotspots inside a single long function.
VizTracer against py-spy and cProfile
cProfile is in the standard library and gives you cumulative and total time per function with no install step. It has no timeline view, so two functions that each take 200ms look identical whether they run in parallel or one after the other. VizTracer's timeline makes that distinction visible, at the cost of writing a trace file and opening a browser.
py-spy takes the sampling approach: it reads the stack of a running process from outside, which means you can profile a process you did not start and did not modify. VizTracer's README also lists an attach_process directory with platform binaries, so attaching is a supported direction, but the primary documented workflow is launching the program under the tracer. The practical difference is measurement style: sampling gives statistical estimates with low overhead and no per-call bookkeeping, while VizTracer records every included call and therefore gives exact ordering and exact call counts. If you need to know that a specific function was entered 4,312 times before a deadlock, sampling will not tell you that and VizTracer will.
Maintenance, packaging and licence
The repository is not archived and the last push was on 2026-09-21, one day before this writing, so the project is being worked on now. Recent releases are 1.1.1 (2025-11-10), 1.1.0 (2025-10-27) and 1.0.4 (2025-05-09), which suggests release cadence in the months rather than weeks. The project is classified Production/Stable in pyproject.toml.
Upgrade cost is mostly the extension build. Because snaptrace is compiled and attach_process ships per-platform binaries, a version bump can require a new wheel for your interpreter and architecture. Pinning the version in a requirements file and testing the trace path on one machine before rolling it out avoids surprises. The runtime dependency surface is small, objprint plus optional orjson, so there is little transitive churn.
The licence is Apache-2.0, declared in both pyproject.toml and the LICENSE file at the repository root. There is also a NOTICE.txt, which is the file Apache-2.0 expects redistributors to carry. If you vendor VizTracer into a product, the licence permits that, but you should read the NOTICE and LICENSE files yourself rather than rely on this summary; nothing here is legal advice.
Editorial conclusion
Adopt VizTracer if you need to see when functions actually ran, across threads, processes and async tasks, and you can afford a JSON trace on disk. Do not adopt it if you need per-line timing on a production service or you cannot install a compiled extension. Before committing, verify that a wheel exists for your Python version and platform, that vizviewer opens your trace at localhost:9001, and that the trace file size stays within what your disk and browser can handle.
Frequently asked questions
How do I use VizTracer to profile a Python function?
Run the script under the tracer with viztracer my_script.py, or wrap the section you care about with a VizTracer instance using start(), stop() and save(). The README also shows a context manager form that takes an optional output_file argument.
What is VizTracer in Python?
It is a logging, debugging and profiling tool that traces Python code execution and visualizes it on a timeline. The viewer is built on Perfetto and runs as a local HTTP server on http://localhost:9001.
Does VizTracer support multiprocessing and threads?
The README lists threading, multiprocessing, subprocess, async and PyTorch among the supported targets. For Python 3.12 and later it states that Python-level multi-thread tracing works without code modification; earlier versions are described separately and the README excerpt does not spell out the requirement.
How do I view a VizTracer result file?
Use vizviewer result.json, which serves the trace on http://localhost:9001 and opens a browser. The README also documents vizviewer --server_only, vizviewer --once, and vizviewer --use_external_processor for very large trace files.
How do I keep VizTracer from tracing library code?
The README points to trace filter options including include files, exclude files, min duration, max stack depth, ignore C function and sparse log. These are documented on the filter page of the readthedocs site rather than in the README itself.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gaogaotiantian-viztracer)