Open-source project
gperftools/gperftools avatar
gperftools/gperftools

gperftools: tcmalloc and the profilers that grew up beside it

Main gperftools repository

8,977 stars1,539 forksC++BSD-3-Clause

At a glance

What is it?
Google's performance tools collection, now maintained outside Google, with a new stack unwinder in 2.19 and a README that admits pprof outgrew it.
Who is it for?
gperftools is most useful when you have a C or C++ binary you cannot recompile, because LD_PRELOAD gets you heap profiling without a rebuild. For everything else in this article's territory, modern toolchains have better options: Go has its own pprof integration, and language-level profilers usually understand your program's structure better than a sampling profiler with symbol tables.
Can I use it commercially?
Yes. BSD-3-Clause 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 31 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 21, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two libraries, one malloc replacement and one profiler

gperftools is described as a collection of a high-performance multi-threaded malloc implementation, plus some pretty nifty performance analysis tools. Originally it was Google Performance Tools, and it is now maintained as its own project under the BSD License with a mailing list on Google Groups.

There are effectively two things in the box. The first is tcmalloc, which you link in place of malloc and new, either as -ltcmalloc or in a smaller form as -ltcmalloc_minimal. The second is a pair of profilers, and those are in -lprofiler rather than in the allocator library.

That split is the first thing to understand. The README is explicit that the cpu profiler, heap checker and heap profiler lie dormant, using no memory or CPU, until you turn them on. Which means there is no harm in linking -lprofiler into every application, and also -ltcmalloc if you are happy with the non-libc malloc library.

So the cost of adopting gperftools is a link flag, not a runtime tax. That is a rare and useful property for a performance tool, and it explains why tcmalloc outlived the surrounding project.

The repository is 8977 stars and 1539 forks with 109 open issues, BSD-3-Clause licensed, and the last push was 2026-09-05. The language is listed as C++, though the project has a long history of C with a C++ toolchain.

Heap profiling three steps, one of which needs no rebuild

The heap profiler quick start in the README is worth reading closely, because the third option changes what the tool is for.

The documented path is to link your executable with -ltcmalloc, run it with the HEAPPROFILE environment variable set, and then analyse the output with pprof:

bash
$ HEAPPROFILE=/tmp/heapprof <path/to/binary> [binary args]
$ pprof <path/to/binary> /tmp/heapprof.0045.heap
$ pprof --gv <path/to/binary> /tmp/heapprof.0045.heap

Note that the output file is numbered, which is why the example shows heapprof.0045.heap. The profiler writes a new dump at intervals rather than appending to one file, so a long run produces a sequence.

The third line of the quick start is the important one: you can also use LD_PRELOAD to heap-profile an executable that you did not compile. That turns gperftools from a build-time decision into a deployment-time one, and for a crash triage or a vendor binary it is the only realistic option.

Two limits are stated plainly. The heap profiler is available on all unix-based systems tested, but it is not currently available on Windows. And the analysis step is no longer part of this repository, which is the subject of the next section.

The related heap checker works the same way through HEAPCHECK, which takes a strictness type rather than a path, and it is a different tool from the profiler: it reports memory errors rather than allocation behaviour.

The CPU profiler, and the fork caveat in the README

The CPU profiler follows the same shape with different flags. You link with -lprofiler, set CPUPROFILE to a file, and analyse it with pprof, which the README describes as producing pg-like text output, or with the --gv flag for graphical output:

bash
$ CPUPROFILE=/tmp/prof.out <path/to/binary> [binary args]
$ pprof <path/to/binary> /tmp/prof.out
$ pprof --gv <path/to/binary> /tmp/prof.out

The environment variables matter as much as the flags. PROFILESELECTED set to 1 restricts profiling to regions wrapped in ProfilerEnable and ProfilerDisable calls, which is how you avoid drowning in samples from a program that spends its time in a library. CPUPROFILE_FREQUENCY sets how many interrupts per second the profiler samples, which trades overhead against resolution. MALLOCSTATS prints memory-use stats at program exit, and PERFTOOLS_VERBOSE raises the volume of messages malloc emits.

Then there is the caveat, and it is the kind of warning that only appears in a README that has been maintained by the same people for fifteen years. CPU profiling does not work after fork unless you immediately do an exec-style call afterwards. And if you do fork and the child calls exit, it may corrupt the profile data, with _exit given as the workaround.

That last point matters for anything that forks worker processes, which on Linux is a common shape for a service. If your program forks, do not expect the CPU profile to be readable.

The CPU profiler is also not available on Windows. For the full variable list, the README sends you to docs/cpuprofile.adoc and docs/heapprofile.adoc.

pprof was removed from this repository on purpose

This is the paragraph in the README that tells you something about how the project is run, and it is unusual enough to be worth quoting in structure rather than in full.

gperftools was the original home for the pprof program. The original pprof was a Perl script, and the README observes that there are not that many Perl experts nowadays. The script was rewritten in Go around 2016, and that version became more featureful. So the original pprof has been removed in favour of the Go version, which lives in its own repository, and Go's own profiling facilities are based on that same version.

That chain of events is the whole story of this repository's relationship with tooling. gperftools produced something genuinely good, that good thing outgrew it, and the leftover project released the original to avoid two competing profilers.

So the correct workflow today is gperftools for capture and google/pprof for analysis, and the README points there rather than shipping a second implementation. If you are following an old tutorial that pipes gperftools output into a local pprof script, that script is the deprecated one.

The README also notes a wiki page on stack trace capturing methods and their issues, and separately points at the TCMALLOC_STACKTRACE_METHOD and TCMALLOC_STACKTRACE_METHOD_VERBOSE variables documented in the INSTALL file. That choice of stack trace method turns out to be the subject of the newest release.

There is one other stack of documentation at the repository root worth knowing about. docs/ holds the two asciidoc pages named above, INSTALL covers configure flags for advanced users plus the per-platform notes, and README_windows.txt covers the Windows port, which the README describes as basic functionality only.

Why 2.19 replaced the stack unwinder

The gperftools-2.18.90 release, published 2026-09-05, is the 2.19 release candidate, and its headline change is the integration of aw-backtrace, a new stack trace capturing engine developed in a separate gperftools repository.

The goals listed for aw-backtrace are three, and they are worth quoting because they frame the whole change. It is built to never crash, to give perfect backtraces whenever possible with heuristics covering cases that lack unwind information, and to be fast enough to make frame-pointer-based unwinding a thing of the past.

That third goal is the one a performance engineer cares about. Frame pointers cost a register and a memory write on every call, so production builds that omit them get cheap calls and poor stack traces. The usual workarounds are libunwind or the libgcc unwinder, and the release notes describe both as costly or fragile.

When aw-backtrace is built it becomes the default stack trace implementation, so CPU profiles, heap and allocation sampling and the other tools get accurate backtraces even in -fomit-frame-pointer builds.

The constraints are explicit and worth noting before you plan an upgrade. It is Linux-only. It requires a reasonably recent glibc for _dl_find_object support, which rules out RHEL 9, though RHEL 10 should be fine. Only amd64 and arm64 are supported. And it is built as C++20 while the rest of gperftools is C++17, which means the toolchain has to be able to compile it.

The previous release, gperftools-2.18.1 from 2026-03-06, was one fix for a compilation failure on PPC. The release before that, gperftools-2.18 from 2026-01-25, is more substantive: a correctness fix for C23 sized deallocation where free_sized could crash the process on reallocated objects, with the old realloc shrinking and growth heuristics removed as a result, plus significantly improved Bazel support for Windows including MinGW and MSVC, an experimental tcmalloc_minimal_nopatch Bazel target, a fix for 256k logical pages on 32-bit targets, and several Valgrind integration fixes.

Four build systems in one repository

The tree at the root shows a project that has to be built four different ways, which is normal for a C library with this many downstream consumers.

There is configure.ac with autogen.sh and m4/, which is the autotools path and the traditional one. There is CMakeLists.txt with a cmake/ directory, used by the distribution packages and by the Windows port. There is a Bazel path, with BUILD.bazel, MODULE.bazel, .bazelrc and .bazelignore, and the 2.18 release notes spend most of their content on improving it. There is also gperftools.sln and a vsprojects/ directory for Visual Studio.

The fact that Bazel work dominated the 2.18 release tells you where the new consumers are. The distribution packages use autotools or CMake and are not where new work happens; downstream projects vendoring gperftools into a Bazel build are.

Other things at the root are diagnostic of a long-lived project. ChangeLog.old is named that way because there is a NEWS file for recent history and the older changelog was moved aside. AUTHORS is present. There is a .clang-format file, a .clangd file for editor configuration, and a gen_compile_commands.rb script that suggests some developers work in Ruby tooling for build database generation.

The source layout is src/, with benchmark/ for the benchmark harness, generic-config/ for the configure templates, vendor/ for vendored third-party code, and docs/ for the asciidoc manual.

Portability is documented honestly. The README says perftools was developed and tested on x86, aarch64 and riscv Linux systems, and works in its full generality only on those. Much of tcmalloc has been ported to FreeBSD, Solaris x86 and Mac OS X on aarch64, with x86 and ppc not tested recently, and the basic functionality of tcmalloc_minimal has been ported to Windows.

Editorial conclusion

gperftools is most useful when you have a C or C++ binary you cannot recompile, because LD_PRELOAD gets you heap profiling without a rebuild. For everything else in this article's territory, modern toolchains have better options: Go has its own pprof integration, and language-level profilers usually understand your program's structure better than a sampling profiler with symbol tables. What gperftools still does well is the allocator. The tcmalloc replacement for malloc and new is a battle-tested reason to link it on a large C++ service, and the 2.19rc integration of aw-backtrace is a genuine engineering advance for stripped and frame-pointer-omitted binaries. The current release is gperftools-2.18.90, the 2.19 release candidate, published 2026-09-05.

Frequently asked questions

How do I profile heap usage with gperftools?

Link your executable with -ltcmalloc, run it with the HEAPPROFILE environment variable set to a path prefix, and analyse the numbered output files with pprof. If you cannot recompile the binary, LD_PRELOAD lets you heap-profile it anyway. The profiler is available on unix-based systems but not on Windows.

How do I collect a CPU profile?

Link with -lprofiler, set CPUPROFILE to an output file, and run the program. Set PROFILESELECTED=1 to restrict sampling to regions wrapped in ProfilerEnable and ProfilerDisable, and use CPUPROFILE_FREQUENCY to trade overhead against resolution. Note the README's warning that CPU profiling does not work after fork unless the child immediately execs, and that a child calling exit may corrupt the profile data.

What happened to pprof in gperftools?

The original pprof was a Perl script that lived here. It was rewritten in Go around 2016, that Go version became more featureful, and the Perl script has been removed in favour of the Go one at github.com/google/pprof. Go's own profiling facilities are based on that same Go version, so the analysis step is not part of gperftools any more.

What is aw-backtrace and why does it matter?

aw-backtrace is a new stack trace capturing engine integrated into gperftools 2.19, designed to never crash, give correct backtraces where possible including cases without unwind information, and run fast enough to retire frame-pointer-based unwinding. When built it becomes the default, so profiles get accurate backtraces even in -fomit-frame-pointer builds. It is Linux-only, needs a recent glibc for _dl_find_object, and supports amd64 and arm64.

Does linking gperftools cost anything at runtime?

Not unless you turn it on. The README states the cpu profiler, heap checker and heap profiler stay dormant using no memory or CPU until enabled through environment variables such as CPUPROFILE, HEAPPROFILE and HEAPCHECK. That is why it says there is no harm in linking -lprofiler into every application, and -ltcmalloc if you accept the non-libc allocator.

Official sources

  1. gperftools/gperftools on GitHub
  2. Issues
  3. License: BSD-3-Clause
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/gperftools-gperftools.svg)](https://hysenlabs.com/projects/gperftools-gperftools)