deniz.in

Markets

Weather

Loading weather

· via Hacker News – Front Page (native)

noalloc enforces zero heap allocations in Go and ships fixed-capacity containers

The Consensus Labs has open-sourced noalloc, a Go toolkit that statically checks annotated functions and their full call trees for heap allocations, paired with fixed-capacity data structures for allocation-free code.

noalloc enforces zero heap allocations in Go and ships fixed-capacity containers

The Consensus Labs has released noalloc, an open-source toolkit for Go that turns "this function must not allocate" from a manual discipline into a checkable invariant. According to the project's README, which surfaced on the front page of Hacker News, the tool statically analyses the entire call tree of annotated functions and reports every line that would allocate on the heap.

How the checking works

Developers mark a function with a //noalloc:root comment and run the noalloc CLI inside the module. The tool walks everything that function calls and prints the offending lines. The README's example flags a map write inside a Counter.Add method and a string concatenation whose result escapes to the heap. The CLI exits with status 1 when it finds an allocation and 2 when it cannot run at all, which makes it easy to wire into continuous integration.

Real code needs escape hatches, so noalloc provides several directives. //noalloc:exempt, with a stated reason, exempts a line and everything that line calls. //noalloc:fixed on a type promises its methods never grow their slices, so the tool treats them as reused memory. //noalloc:append marks helpers that behave like append. Allocations are tolerated on error or panic paths that end the root's call, and during first-use setup. A -scratch flag marks a type's fields as memory kept between requests, and -source pulls an external import path prefix into the check as if it were part of your module — the README suggests running it over noalloc's own libraries so their directives take effect. Calls into other modules are allowed only when noalloc can establish the callee allocates nothing, worked out from its source or, for assembly and runtime code, from its compiled form. The tool requires Go 1.27 or later and installs with the standard go install command.

Fixed-capacity containers

The second half of the project is the bounded library: zero-allocating, fixed-size data structures where overflow is a visible state rather than a crash or a hidden allocation. Its four containers — Buf, Vec, Slice and Map — each have a maximum capacity, and a write that does not fit does nothing while marking the container as full, so code can check once at the end instead of after every write. A Buf can be attached to an io.Writer and flush as it fills. A Vec can borrow chunks from a pool through a Region and be read back non-contiguously. A Slice migrates to progressively larger pooled chunks the way append moves to a bigger array. A Map refuses new keys past its limit but keeps accepting updates to existing keys, and can grow into larger pools of slots. The README also lists a zero-allocating JSON encoder and decoder among the provided algorithms.

A budget model for requests

Underneath the containers sit Pool and Region. A Pool lends a fixed number of chunks; when they run out, callers can get nil, block until a channel closes, or take several chunks at once or none. The recommended pattern for dynamic input is to give each request a Region with a fixed memory budget when it starts, borrow from a shared pool as the input demands, and release everything when the request ends. The README is explicit that every site which can exhaust its budget needs a plan for when it does — suggestions include ending a page early and letting the client resume from a cursor, skipping an optimisation, evicting a memo entry, or refusing oversized input before parsing it.

Provenance and caveats

The README opens with an unusual disclaimer: the repository is entirely written by AI, guided by a human, and is used in production at The Consensus in both its web service and its code search engine. It also warns that the project is experimental and may change vastly. The design is coherent, but the API surface carries no stability promise.

Why it matters

Allocation-free hot paths matter in Go because every heap allocation is future garbage-collection work, and that cost lands precisely in latency-sensitive services. The hard part has never been writing allocation-free code once — it is keeping it that way as the codebase evolves, since a single innocent map write or escaping string reintroduces allocations silently. By resolving the whole call tree statically and failing with a non-zero exit code, noalloc turns a performance property into something CI can enforce, much as a compiler enforces types. The fixed-capacity containers address the follow-on problem: once allocation is forbidden, everyday Go idioms like append and map assignment stop working, and code needs substitutes with explicit overflow behaviour. Enforcement plus replacement primitives is what makes the release practical rather than aspirational. The stated AI authorship of a production-grade tool is, separately, a data point worth noting in its own right.

  • #golang
  • #static-analysis
  • #developer-tools
  • #performance
  • #open-source

Related posts