gprof2dot reads eleven profiler formats and tells you which ones it will never get faster
Converts profiling output to a dot graph.
At a glance
- What is it?
- A single-file Python converter from profiler output to Graphviz, with a comparison mode that is the most interesting part, and a status section that says plainly it is finished.
- Who is it for?
- The honest framing for gprof2dot is that it is a finished tool rather than a project in progress, and the README says so in a Status section that other projects would be uncomfortable publishing. That does not make it less useful.
- Can I use it commercially?
- Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 62 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 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One script, eleven input formats
The scope is a converter and nothing more: it reads profiler output and writes a Graphviz dot graph. What makes it substantial is the length of the input list, since the same graph comes out of Linux perf, Valgrind's callgrind, Sysprof, Xperf, Intel VTune, Very Sleepy, Python's own profilers, Java's HPROF, prof and gprof, DTrace, and FlameGraph's stackcollapse output. Eleven formats in one tool means you can switch profilers without losing your ability to look at results.
The format is chosen with a single option rather than sniffed from the content:
-f FORMAT, --format=FORMAT
profile format: axe, callgrind, collapse, dtrace,
hprof, json, perf, prof, pstats, sleepy,
sysprof or xperf [default: prof]The list in that help text runs to twelve because json is in the option string alongside the eleven the README enumerates, which is a small reminder that the prose feature list and the parser table are maintained by different habits. The default is prof, the classic GNU output, which is the least surprising choice for a tool whose own name comes from gprof.
Installation has three routes and they are all one line each, which is unusual for a package that has been around since 2021. The PyPI route is `pip install gprof2dot`. There is also a standalone script you can fetch and run, and the git repository itself. The standalone script matters more than it looks: it means you can drop one file next to a build on a machine that has Python and Graphviz and nothing else.
Thresholds are what make a call graph readable
A call graph of a real program has thousands of nodes and most of them are noise. The two pruning options exist for that, and their defaults are conservative:
-n PERCENTAGE, --node-thres=PERCENTAGE
eliminate nodes below this threshold [default: 0.5]
-e PERCENTAGE, --edge-thres=PERCENTAGE
eliminate edges below this threshold [default: 0.1]A node below half a percent of time and an edge below a tenth are dropped. Raising those is the single most effective thing you can do to make a graph legible, and it is worth remembering that the numbers are percentages of total rather than absolute costs, so the same settings behave differently on a large and a small program.
There is a second, structural form of pruning. You can cut the graph down to the descendants of one function or the ancestors of one, and you can bound it by depth:
-z ROOT, --root=ROOT prune call graph to show only descendants of specified
root function
-l LEAF, --leaf=LEAF prune call graph to show only ancestors of specified
leaf function
--depth=DEPTH prune call graph to show only descendants or ancestors
until specified depthThe root and leaf options take selectors formatted as `<pkg>:<linenum>:<function>`, which is where `--list-functions` earns its place. That option lists the available functions for selection and accepts a selector argument using shell-style pattern matching, with a leading `%` dumping everything available. In practice you run it once to find the exact function name and then paste it into `-z`.
There is also `-p` to filter out entire module paths, which is the faster way to deal with a program whose time is spread across a runtime and a standard library you are not investigating.
Colour, labels and the recursion heuristic
Colour is doing real work rather than decoration, because the graph is meant to be read at a glance for hot spots. The colormap option offers five themes, bw, color, gray, pink and print, with color as the default. Nodes are coloured by total time by default, which is the sum of self time and descendants, and there is a flag to switch to self time instead when the question is which function is actually burning cycles rather than which one owns a slow subtree.
The `--skew` option reshapes the colourisation curve and is the answer to the common complaint that everything looks the same shade. Values below 1.0 give more variety to lower percentages, values above 1.0 give less, so a program where all the cost sits in one place wants skew raised and a long flat profile wants it lowered.
Labels are configurable too. `--node-label` can be given more than once and picks from self-time, self-time-percentage, total-time or total-time-percentage, with the last two as the defaults. `-w` wraps long function names, which matters as soon as C++ template names appear.
Two other behaviours are worth naming because they are easy to miss. `-s` strips function parameters, template parameters and const modifiers from demangled C++ names, which is what makes a C++ graph readable at all. And the tool applies a heuristic to propagate time inside mutually recursive functions, since without it recursion flattens the graph into a small cycle and loses the distribution of cost inside it.
`--show-samples` is the one to know about when reading the README's example output, because a graph without sample counts tells you the shape but not the evidence.
Comparing two profiles is the least obvious feature
The comparison mode takes two graph files with almost identical structure and reports the difference between them, which turns gprof2dot from a viewer into a measurement instrument. You answer a question that a single profile cannot: did the change work.
--compare Compare two graphs with almost identical structure. With this
option two files should be provided.
--compare-tolerance=TOLERANCE
Tolerance threshold for node difference
(default=0.001%).If the difference is below this value
the nodes are considered identical.
--compare-only-slower
Display comparison only for function which are slower
in second graph.
--compare-only-faster
Display comparison only for function which are faster
in second graph.
--compare-color-by-difference
Color nodes based on the value of the difference.The tolerance is the detail that decides whether the feature is useful. Two runs of the same binary differ by measurement noise, so a node whose difference is below 0.001% is treated as identical, and without that default every graph would be entirely red. Raising it is how you decide what counts as a real change.
The only-slower and only-faster flags are the ones you will actually use day to day. A comparison showing everything changed reads as noise; a comparison showing only what got slower is a work list. The default tolerance combined with either filter is what makes this mode practical rather than theoretical.
The stated assumption is almost identical structures, which is the real limitation. A comparison between a version where a function was inlined and one where it was not is not a performance comparison, and the tool will not tell you that is what happened.
The Status section is worth reading before you file an issue
The README has a section headed Status and it says the project fulfills the author's needs, that there is little or no time for maintenance, that requested features are unlikely to be implemented, and that issues and pull requests may be slow. That is the author stating the trade in plain language, and it changes how you should approach the repository.
It also explains the release cadence. The tags are 2022.07.29, 2024.06.06 and 2025.04.14, so roughly one release every year or two, and the last push was 2026-08-05. That is consistent with a project that gets attention when the author needs it rather than a schedule.
The content of those releases shows the pattern. 2025.04.14 removed the %3 tooltip from SVG output and added an option to specify the time format. 2024.06.06 is longer and more telling: it added support for simulated and embedded gprof output, made the GitHub Actions matrix cover the oldest and youngest Pythons still alive, stopped Codecov from failing on forks, and dropped the Python 2.7 leftovers, which is where the requirement of Python 3.8 or newer comes from. 2022.07.29 converted setup.py to setup.cfg.
Those are maintenance commits rather than feature work, and they came from different contributors, which is what happens in a project where the maintainer is candid about not having time. The build and coverage badges sit directly under the Status section, so the tests exist even though the maintenance does not, and codecov is wired into a build workflow on the main branch.
The licence is LGPL-3.0, which is worth a second look if you plan to read the source and reuse it, since that is a different set of obligations from MIT.
Requirements, packaging and what is actually in the tree
Two things have to be present: Python and Graphviz. The README states Python is known to work with version 3.8 or newer and will most likely not work with earlier releases, and Graphviz is tested against 2.26.3 but should work with other versions. Installation on Linux is the shortest path:
apt-get install python3 graphvizwith a yum equivalent for RedHat and Fedora, and Windows users pointed at the two installers. Graphviz is not optional because the output is dot source, so without the graphviz command to render it you have text.
The repository is smaller than you would expect from the feature list. The tree holds `gprof2dot.py`, `tests/`, `images/`, `sample.svg`, a `schema.json`, `MANIFEST.in`, both `setup.py` and `setup.cfg`, and a `pyproject.toml` that is four lines declaring setuptools as the build backend. `setup.py` itself has been reduced to a shebang, an import and a bare `setup()` call, which is the correct end state after the setup.cfg migration in 2022 and the kind of detail that says the packaging was tidied rather than accumulated.
What is absent is worth noting too. No plugin system, no web interface, no output formats beyond dot, no configuration file. If you want SVG or PNG, Graphviz does it from the dot file, and the README points at xdot.py for an interactive viewer when you want to click through a large graph rather than squint at a static image.
The project has 3,456 stars, 391 forks and 11 open issues. Given the maintenance posture, the issue count is more a measure of how few people file things than of how responsive the project is, and the topics list covers C++, graph, profiling and Python.
Editorial conclusion
The honest framing for gprof2dot is that it is a finished tool rather than a project in progress, and the README says so in a Status section that other projects would be uncomfortable publishing. That does not make it less useful. A single Python file with no runtime dependency beyond the standard library, Graphviz as the only external requirement, and eleven input formats is a rare amount of coverage for something you can read top to bottom in an afternoon. Use it the way the author expects, which is to install it, point it at whatever your profiler emitted, and tune the two thresholds until the graph is readable rather than trying to coax it into a workflow it was not built for. The comparison mode, with its tolerance and its slower-only and faster-only filters, is what you reach for when you are trying to answer whether a change helped. For anything interactive, xdot.py is the companion the README points at, and for anything you need changed, expect to wait.
Frequently asked questions
How do I install gprof2dot?
On Debian or Ubuntu, install Python and Graphviz with `apt-get install python3 graphviz`, then install the tool with `pip install gprof2dot`. There is also a standalone script you can download and run directly, which needs nothing but Python and Graphviz on the machine.
Which profilers can gprof2dot read?
Linux perf, Valgrind callgrind, Sysprof, Xperf, Intel VTune, Very Sleepy, Python's profilers, Java HPROF, prof and gprof, DTrace, and FlameGraph's stackcollapse. Pick one with the format option, whose default is prof. The README lists eleven while the option's own help text names twelve, since json is in the option string but not the prose.
How do I make the call graph smaller?
Raise the pruning thresholds. Nodes below 0.5% and edges below 0.1% are dropped by default, and both are adjustable. For structural reduction, use the root option to keep only descendants of a function, the leaf option to keep only ancestors, or the depth option to bound the graph either way.
Can gprof2dot compare two profiles?
Yes, and this is its most interesting capability. The compare option takes two graphs with almost identical structure and reports differences, with a tolerance so nodes differing by less than the threshold are treated as identical. The only-slower and only-faster flags narrow the output to regressions or improvements, which is what makes the mode usable in practice.
Is gprof2dot still maintained?
The author says plainly in the README that it fulfills their needs with little or no time for maintenance, that requested features are unlikely, and that issues and pull requests may be slow. Releases are irregular, 2022, 2024 and 2025 so far, and the work that does land tends to be maintenance contributed by other people.
What can I use to view the graphs interactively?
xdot.py, which the README recommends specifically for that purpose, since gprof2dot itself only emits dot source and relies on Graphviz to render it. The README's example output is an SVG, and the 2025 release removed a tooltip format from the SVG output while adding an option for the time format.
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/jrfonseca-gprof2dot)