Library / SDK
segmentio/asm avatar
segmentio/asm

segmentio/asm: SIMD and branchless algorithms for Go

Go library providing algorithms optimized to leverage the characteristics of modern CPUs

929 stars39 forksGoMIT-0

At a glance

What is it?
segmentio/asm collects CPU-specific implementations of hot path algorithms for Go, generated with AVO and shipped alongside generic Go fallbacks, grouped into packages for ascii, base64, byte swapping, quicksort, slice pairs and sorted sets. It buys raw throughput at the price of uneven architecture coverage and assembly you did not write yourself.
Who is it for?
segmentio/asm fits Go teams whose profiles point at a small number of hot loops, such as ASCII comparison, base64 encoding or fixed-size sorting, and who can measure the difference on their own hardware. It does not fit teams that need one implementation across many architectures, since coverage differs per package and qsort has only an amd64 path, nor teams that would rather keep their critical path in portable Go.
Can I use it commercially?
Yes. MIT-0 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 135 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

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

From daily snapshots

Star history

  • segmentio/asm929 ★ · +0
Star history
Repository2026-10-212026-11-07
segmentio/asm929929

0 Stars in the last 17 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Aimed at hot loops in large distributed services

The stated motivation is worth repeating because it explains the whole shape of the library. The README argues that cloud computing makes it easy to run distributed systems across dozens or hundreds of CPUs, and that because projects run on so many cores, program performance and efficiency matter more than before. From there comes the technical claim: modern CPUs are complex machines whose performance can vary by orders of magnitude depending on how they are used, with branch prediction, instruction reordering, pipelining and caching all acting as input variables that decide achievable throughput. Compilers keep improving, the README concedes, and often apply micro-optimizations that would be counter-productive for a human developer to own, but there are limits to what a compiler can do. The audience is therefore not a general Go user but a performance engineer with a profile in hand and a hot path worth rewriting. The functions in this library have been used in high throughput production environments at Segment, which is the project's own claim about where they came from.

Eight packages, each with a narrow job

The library is split into logical groups of functions that share properties, and the README documents the set as a table. `ascii` holds functions designed to work on ASCII inputs, `base64` provides standard library compatible base64 encodings, and `bswap` handles byte swapping on arrays of fixed-size items. `cpu` is described as the definition of the ABI used to detect CPU features, which is the piece that lets the rest of the library ask what the current processor can do. `mem` operates on byte arrays, `qsort` holds quick-sort implementations for arrays of fixed-size items, `slices` performs computations on pairs of slices, and `sortedset` works on sorted arrays of fixed-size items. That design brief matters more than any individual function: the README says users will find functions often designed to work on arrays of values, which is where SIMD and branchless algorithms shine. Taking SIMD seriously often means rethinking how a program represents and manipulates data, which is beyond what a compiler will do for you, and the package boundaries reflect that bias.

Every assembly function has a Go fallback

The mechanism that makes the library usable in real services is the fallback. When no assembly version of a function is available for the target platform, the package provides a generic implementation in Go, and the compiler picks it up automatically. That single design decision removes the usual objection to assembly libraries, which is that they only build on one architecture and your build fails everywhere else. Here the code always compiles, and the fast path is used where it exists. The corollary is that performance is per architecture and per package, which is the trap for newcomers. The README advises searching for a `.s` file matching your architecture to be sure you are actually using the assembler optimized library instructions, because a package that looks SIMD aware may silently be running portable Go on the machine you deploy to.

AVO generation and the separate build module

The assembly is not hand written. It is generated with AVO, a Go assembly generator, and orchestrated by a Makefile that lets maintainers rebuild the assembly source when the AVO files change. The repository holds two Go modules: the main module `github.com/segmentio/asm` at the root, and a second module in the `build` subdirectory. The stated purpose of the split is to isolate build dependencies from programs that import the main module, so AVO never becomes a dependency of your application and the dependency management overhead for users stays minimal, while maintainers are free to change the build package. The two modules are versioned independently, and the README is explicit that breaking changes may appear in the build package more often because it is intended to be ground for more experimental constructs, while the main package aims for stable APIs. The root `go.mod` declares `go 1.18` and requires `golang.org/x/sys`.

purego gives you the slow path on purpose

There is a build tag that lets you switch the whole library back to the portable implementations, which sounds pointless until you realise its purpose is measurement. Code in the build module can declare a constraint that instructs AVO to inject the `!purego` tag into the generated files:

go
func init() {
	ConstraintExpr("!purego")
}

With that tag in place the libraries compile without any assembly optimizations:

bash
go build -tags purego ...

The README describes this as mainly useful for comparing the impact of using the assembly optimized versions instead of the simpler Go-only implementations, and the Makefile encodes exactly that comparison in its `benchcmp` target, which runs the same benchmark twice, once with the `purego` tag and once without, writes both result sets to temporary files and hands them to `benchstat`. The Makefile also regenerates the `.s` and `.go` outputs from the AVO sources for each package. For a team evaluating this library, that target is the workflow: measure the portable path against the assembly path on your own hardware and your own data, rather than trusting published numbers.

Architecture coverage is not uniform

This is the limitation that decides whether the library fits your deployment. The README states plainly that some libraries have custom purpose code for both amd64 and arm64, while others, qsort is named as the example, have only amd64. So a service that must run on amd64 and arm64, which is the normal shape for a container-based fleet today, gets full acceleration in some packages and the portable fallback in others. The fallback keeps the code correct, but it also means the headline gains are conditional on the machine. The README also states that the Go code requires Go 1.17 or above, noting that those versions contain significant performance improvements compared to earlier ones, and that `asm` version v1.1.5 and earlier maintained compatibility with Go 1.16. In other words the version floor is a deliberate choice tied to compiler quality rather than an accident. The upgrade cost of adopting this library is therefore mostly cognitive: you are accepting two implementations of every function, and you need to know which one your binary actually contains.

MIT-0 licence, one release, and a slow-ish commit rhythm

The licence field on the repository says MIT-0, which is the MIT licence with the attribution requirement waived, and the `LICENSE` file sits at the root next to `CONTRIBUTING.md` and `CODE_OF_CONDUCT.md`. For a library intended to be dropped into other people's hot paths, that is the licence you would want, though whether the waiver applies to your distribution model is a question for your own legal review rather than something this article can answer. On maintenance, the picture is mixed and worth stating plainly. There is one tagged release, v1.2.0 from 2022-05-01, while the last push was on 2026-06-25. Recent commits without a new tag mean the tree is being worked on while the released version stays put, so pinning to v1.2.0 gives you the state of 2022, and tracking the default branch gives you work in progress. The root `go.mod` still declares `go 1.18`, and the repository carries `internal/`, `keyset/` and `utf8/` directories alongside the documented packages, so the public surface documented in the README is a curated subset of what is in the tree.

Editorial conclusion

segmentio/asm fits Go teams whose profiles point at a small number of hot loops, such as ASCII comparison, base64 encoding or fixed-size sorting, and who can measure the difference on their own hardware. It does not fit teams that need one implementation across many architectures, since coverage differs per package and qsort has only an amd64 path, nor teams that would rather keep their critical path in portable Go. Before adopting it, check that a `.s` file exists for the architecture you deploy on, benchmark the purego build against the assembly build with the Makefile benchcmp target on your own machine, and confirm the last push on 2026-06-25 is recent enough for the Go release you compile with.

Frequently asked questions

What does segmentio/asm do when the target CPU has no assembly implementation?

The package provides a generic implementation in Go for that function, and the compiler picks it up automatically. The README advises searching for a .s file matching your architecture to confirm you are using the assembler optimized path.

How do I compare the assembly version with the pure Go version?

Build with the purego tag to get the portable implementations, for example with go build -tags purego. The Makefile benchcmp target runs the benchmark suite both ways and compares the two result sets with benchstat.

Which architectures does segmentio/asm support?

Coverage differs by package. The README says some libraries have custom purpose code for both amd64 and arm64, while others, with qsort named as the example, have only amd64. The Go code requires Go 1.17 or above.

Official sources

  1. Issues
  2. License: MIT-0
  3. README
  4. Releases
  5. segmentio/asm on GitHub
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/segmentio-asm.svg)](https://hysenlabs.com/projects/segmentio-asm)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/segmentio-asm.svg)](https://hysenlabs.com/projects/segmentio-asm)

Was this useful?