# go-binsize-treemap turns a symbol table into a picture of your binary

> go-binsize-treemap reads the output of the Go toolchain symbol dumper and renders an SVG treemap of what is taking up the space, so you can see which packages and symbols dominate a large executable. It is a single Go program with one dependency, and it exists because the author wanted a Go only version of an idea first built in Python.

**nikolaydubina/go-binsize-treemap** — 🔍 Go binary size SVG treemap

- Repository: https://github.com/nikolaydubina/go-binsize-treemap
- Stars: 587 · Forks: 18
- Language: Go
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/nikolaydubina-go-binsize-treemap

## A pipe from the symbol dumper to an SVG

The tool does one thing, and the whole invocation is visible in two lines. You install it with the Go toolchain, then pipe the output of the symbol dumper into it and redirect the result into an SVG file.

```bash
$ go install github.com/nikolaydubina/go-binsize-treemap@latest
$ go tool nm -size <binary finename> | go-binsize-treemap > binsize.svg
```

That design choice is the point of the project. The Go toolchain already knows how to list every symbol in a binary with its size, so there is nothing to implement on the input side, and the interesting work is entirely in turning that list into a picture a person can read. The output is a treemap, where each rectangle is a symbol and the area is the size, and the layout is grouped by package so the tree structure of a Go binary becomes visible. The dependency list in the module file is short, with the treemap library at version 1.2.5 and a colour library pulled in indirectly, and the module targets a Go 1.17 language version. The tree confirms the structure, with a main file, a basic converter, a symtab package for parsing the symbol dump, a byte count formatting package, a testdata directory with the symbol tables used by the documentation, and a docs directory holding the example images.

## The author's own list of reasons to care about binary size

The readme opens the disclaimer with the honest counterargument, that a few seconds of cat videos or even a single image is tens of megabytes, that transferring them over the network is not a big deal, and that you probably should not worry too much about executable size. Then it lists the cases where the tool is still useful, and the list is a good description of who actually needs this. You are studying the compiler, you are investigating what third party dependencies are getting included in the binary, you are checking whether a lot of data is being embedded, you are estimating how much code each package contributes, you are researching which symbols end up included, you are working with cgo, and you are doing treemap visualisation. Read as a whole, that is a list for people who want to understand a build, not for people who want to shrink one. The author also says the project is built in spare time as another use case for Go treemap tooling they built before, and that issues and pull requests are welcome.

## Two runtime structures dominate the picture

The knowledge base section explains the two symbols that surprise people, and it is the most instructive part of the readme. The first is go.itab, which is interface related code, with a link to an article by Russ Cox on interfaces as the explanation. The second is runtime.pclntab, which is large because it is a Go runtime structure used for traces, with a reference to an investigation by the Cockroach team and a link to a long discussion in the Go issue tracker about why it is big and what can be done about it, which the readme answers with what amounts to nothing, in other words there is no fix. That is a genuinely useful thing to learn from a picture, because both of those regions look inexplicable in a size report and turn out to be structural. A treemap makes the shape of a Go binary legible in a way that a table of package sizes cannot, since it shows the same information with the outliers visible.

## C++ names need demangling before the tool can read them

The first appendix is a warning about output that looks wrong, and the cause is cgo. When a Go binary links C++ code, the symbols in the symbol table arrive mangled, and the tool cannot make sense of them, so the output is strange. The fix is to demangle the symbol table first by installing c++filt and piping through it before the treemap tool, and the readme notes that C++ support is work in progress.

```bash
$ go tool nm -size <binary finename> | c++filt | go-binsize-treemap > binsize.svg
```

This is the practical difference between the tool working and not working on a real project, because a large Go service that calls into a C++ library is exactly the case where the size question comes up. The examples section shows the four cases the author cared about, and they are chosen to cover the interesting shapes, with the Hugo project at 62 megabytes as the famous large Go project, CockroachDB at 71 megabytes which is built with C++, the go-graphviz library at 6.5 megabytes which has cgo and pulls in a lot of C, and the Skipper project at 36 megabytes where some builds include C.

## Image size decides how much you can see

There are three appendices about output dimensions, and they encode a straightforward idea about static visualisation. With very large dimensions you can see a lot of detail and navigate the map, and 4096 by 4096 is the recommended size, with the author showing a 16384 by 16384 example for the same project. With small dimensions you get a preview that is informative but coarse, and 1024 by 256 is recommended for embedding in a readme, with several sizes shown for the same project. The docs section then shows the exact commands used to produce the committed images, which are generated from the symbol tables in the testdata directory, and it is a nice piece of engineering practice that the documentation images are reproducible from files in the repository.

```bash
$ cat testdata/go-graphviz.symtab | ./go-binsize-treemap > docs/go-graphviz.svg
$ cat testdata/go-graphviz.symtab | ./go-binsize-treemap -w 4096 -h 4096 > docs/go-graphviz-4096x4096.svg
```

The command also has a CSV mode, which is what you would actually use if you wanted to diff two builds, since two SVGs are hard to compare and two CSV exports are not.

## A Go only rewrite of a Python tool, and what it gives up

The related work section is a candid comparison with the tool that inspired it. The inspiration was a project that used Python with D3 and JavaScript, and the readme's argument is that this tool uses a single stack purely in Go and has test coverage, with the downside being that it is not interactive. That is the right trade for the stated audience, since a Go developer debugging a Go build is unlikely to want a browser based explorer, and a static SVG can be committed to a repository and diffed between builds. A second project is listed as having looked like it worked in the beginning, but as of early 2022 it did not work for the author, with reports going back to 2020 that it was not accurate. The other references point to the author's own treemap and cover treemap tools, to the documentation for the symbol dumper, and to the manual page for the C++ demangler, which ties the appendix back to the main pipeline. The repository also carries a citation file and a security policy, and the readme points to a package reference page and a code coverage badge.

## The known issues are honest about the limits

The list of known issues and to-dos reads like a design backlog, and two of the entries are worth reading before you rely on the output. The first says the size slightly mismatches the actual binary size, and that including the unknown bucket does not help, so the areas you cannot account for stay unaccounted for. The second says better symbol name parsing for C++ is still needed, which matches the appendix warning. The rest are features, including identifying embedded data, colouring by type with increasing luminance for system, user, C++ and embedded categories, colouring by symbol type, and a heat map whose question mark is left open. That last one is worth mentioning as a sign of how the project sees itself, since a heat map of what is expensive to load at runtime is a natural next question for a tool that already knows the size of every symbol. The releases stop at v0.2.3 in March 2024, with v0.2.2 and v0.2.1 in the same week, and the last push was on 2026-08-15, so the branch is being worked on faster than the tags are being cut.

## Conclusion

go-binsize-treemap earns its place for anyone who has been guessing why a Go binary is large, because a picture of the symbol table answers questions that a size breakdown by package does not, in particular which runtime structures and which third party dependency are responsible. It is a poor choice if you need an interactive explorer, since the output is a static SVG and the README names that as the downside of the pure Go approach, and a poor choice if you need exact numbers, since the known issues say the size slightly mismatches the actual binary and that including the unknown bucket does not help. Verify three things before you use it: that the symbol dump you feed it is the right one, since a stripped or trimmed binary gives a different picture, that you demangle C++ names first when cgo is involved, and that the image size you choose is large enough for the detail you need, since a 1024 by 256 preview is deliberately coarse. The licence is MIT, the last push was on 2026-08-15, and the newest release is v0.2.3 from 2024-03-26.

## FAQ

### How do I generate a binary size treemap?

Install the tool with go install, then pipe the output of the Go symbol dumper into it and redirect the result to an SVG, for example go tool nm -size on your binary piped into go-binsize-treemap and redirected into binsize.svg. The tool also has a CSV output mode.

### Why does my C++ output look wrong?

The readme explains that symbols from linked C++ code arrive mangled and have to be demangled first, so you should install c++filt and pipe the symbol dump through it before the treemap tool. C++ support is described as work in progress.

### Why is runtime.pclntab so large in the treemap?

The knowledge base section says it is a Go runtime structure used for traces, citing an investigation by the Cockroach team and a discussion in the Go issue tracker, where the conclusion is that there is nothing to be done about it. The other large region, go.itab, is interface related code.

### What size should the generated SVG be?

For detail the readme recommends 4096 by 4096, and shows a 16384 by 16384 example for the same project. For a small preview suitable for embedding in a readme it recommends 1024 by 256, and the docs section lists the exact commands used to generate the committed example images.

## Sources

- [Issues](https://github.com/nikolaydubina/go-binsize-treemap/issues)
- [License: MIT](https://github.com/nikolaydubina/go-binsize-treemap/blob/main/LICENSE)
- [nikolaydubina/go-binsize-treemap on GitHub](https://github.com/nikolaydubina/go-binsize-treemap)
- [README](https://github.com/nikolaydubina/go-binsize-treemap/blob/main/README.md)
- [Releases](https://github.com/nikolaydubina/go-binsize-treemap/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nikolaydubina-go-binsize-treemap
