Skip to content
Tech AI Wire

Debian Code Search drops its last cgo dependency

Michael Stapelberg replaced a 7-year-old C library with pure Go using the experimental SIMD package, and matched the C version's speed.

By Tech AI Wire Team

3 min read

XLinkedIn
A terminal running benchcmp to compare a scalar Go benchmark against a vectorised one, with the delta column showing the speed-up.

Debian Code Search now runs without any C code. Michael Stapelberg replaced a seven-year-old C compression library with a pure Go version built on Go's experimental SIMD package, and reports it matches the C original for speed. "I deleted the last cgo dependency in Debian Code Search," he wrote on his blog on September 6, 2026.

Debian Code Search is the service that lets anyone search 130 GiB of source code across every Debian package. It has been running since 2012.

What TurboPFor does and why C was there

The library in question is TurboPFor. It is an integer compression format, used inside an inverted index to store lists of document IDs compactly.

That job is unglamorous and performance-critical. A code search engine spends much of its time decoding those ID lists, so the decoder sets the speed of every query.

Go can call C, through a bridge called cgo. It works, but it costs. Every call crosses a boundary, cross-compiling gets harder, and the build now needs a C toolchain as well as a Go one. Stapelberg had carried that trade for seven years because the C version was faster.

What the Go rewrite achieved

The rewrite leans on simd/archsimd, an experimental package that arrived in Go 1.26. SIMD stands for single instruction, multiple data: one CPU instruction operating on a batch of values at once instead of one at a time.

Two figures from the post stand out. Positional popcount encoding, a bit-counting step in the format, ran about twice as fast with the SIMD path. Full blocks decoded roughly three times faster than the plain scalar Go version.

MeasureResult
Positional popcount encodingAbout 2x faster with SIMD
Full-block throughputAbout 3x faster than scalar Go
Against the original C libraryParity, encoder and decoder
cgo dependencies remainingZero

Parity is the important word. The Go version does not beat C. It draws with it, which is enough to make the C dependency not worth keeping.

The catch: it is still an experiment

This does not work out of the box. The package is gated behind a build flag. Stapelberg quotes the requirement directly. "Go 1.26 introduces a new experimental simd/archsimd package," he writes, "which can be enabled by setting the environment variable GOEXPERIMENT=simd at build time."

An experimental package can change shape between releases, and the API here is deliberately architecture-specific rather than portable. We covered Go 1.27 adding a portable simd package alongside the architecture-specific one, which is the direction this is heading, but neither is stable yet.

What this means for developers

The transferable result is that the cgo escape hatch is narrowing. Plenty of Go projects keep a C dependency for one hot loop, and accept a harder build in exchange. If SIMD in Go can reach parity with hand-written C on integer compression, that trade is worth re-examining in your own code.

Check what you are actually paying for cgo before you start. It is not only speed. It is cross-compilation, build toolchains in CI, static linking, and the debugging that follows a crash across the boundary. Stapelberg's win is a simpler build as much as a faster one.

Do not put GOEXPERIMENT=simd into a production build yet. Experimental means the package can move, and an architecture-specific API means your code is not portable by default. Prototype with it, measure your own numbers, and keep the C path until the API settles.

If you want the implementation rather than the summary, the Go port is published separately as goturbopfor. The service it feeds is open source under the Debian organisation. Reading a real SIMD kernel written in Go is currently a short list, and this is on it.

Sources

  1. Debian Code Search: Fast TurboPFor with Go SIMD - Michael Stapelberg
  2. Debian Code Search - Debian
  3. stapelberg/goturbopfor - GitHub

Related articles

A terminal showing a large C++ project compiling, with the CMake percentage counter partway through and object files scrolling past.
Coding

LLVM debates building ClangIR by default

An LLVM RFC proposes compiling ClangIR into Clang by default. Nobody would use it without a flag, but some estimates put build times at more than double.

The daily brief

Three to five stories a day, and what each one means for the people who build software. Free, no spam.