Skip to content

matchlen

CI coverage

MatchLen(a, b []byte) int — the length of the common prefix of two byte slices. It is the core primitive of every LZ-family compressor's match-finder (LZ4, zstd, LZFSE/LZVN, brotli, …) and the single most SIMD-amenable spot in LZ encoding. Repository →

API

n := matchlen.MatchLen(a, b) // a[:n] == b[:n], n maximal

The hot comparison loop is real SIMD on all six 64-bit Go targets, assembly generated by go-asmgen — on plain go build, no cgo, no GOEXPERIMENT:

arch ISA how
amd64 SSE2 + AVX2 (V)PCMPEQB+(V)PMOVMSKB, BSF; AVX2 (32-byte) auto-selected
arm64 NEON VEOR, first non-zero byte via RBIT+CLZ
loong64 LSX VXORV, lane→GPR via VMOVQ V.V[i], CTZV
riscv64 RVV VXOR+VMSNE, vfirst.m
ppc64le VSX LXVD2X+VCMPEQUB, mask→GPR via MFVSRD, CNTTZD
s390x vector facility (big-endian) VL+VFENEBS (find-element-not-equal), index via VLGVB

VSX is baseline on POWER8+ and the vector facility on z13+, so ppc64le and s390x need no runtime feature dispatch — the SIMD path is simply the arch's only path (build-tagged), like riscv64 and loong64. s390x is the one big-endian target: VL puts the lowest memory address in the high-order lane, so the first mismatching byte is the first VFENEBS element. lz4-style callers that need a remaining architecture use a portable 8-byte-word scalar fallback. The result is bit-identical everywhere — including big-endian s390x — checked vs a byte-by-byte reference and fuzzed. ppc64le, riscv64, loong64 and s390x are now natively measured on real silicon (see below).

Performance

16-byte SIMD strides vs a naive byte loop, ~4 KiB shared prefix (Apple Silicon, arm64 NEON): ~34.7 GB/s vs ~3.3 GB/s — ~10×.

The match-counter alone (native amd64, GitHub runner): SSE2 ~17.6 GB/s, AVX2 ~36.6 GB/s (~2.08×) — AVX2 is picked at runtime when available.

Measured on real silicon (GCC Compile Farm, Go 1.26.4, 2026-06-26)

  • ppc64le — real POWER9 (VSX): MatchLen runs at ~6.3× the scalar baseline (5320 vs 841 MB/s), superseding the earlier llvm-mca cycle-model estimate.
  • s390x — real IBM z15 (VXE2, native, 2026-07-03, -count=6): the vector-facility MatchLen (VL+VFENEBS, index via VLGVB) runs at ~9.2× the scalar baseline, superseding the earlier ~2.5× z14 cycle-model estimate.
  • riscv64 — real SpacemiT X60 (RVV 1.0): ~5.8× the scalar baseline (1236 vs 214 MB/s). The X60 is a low-power in-order core, so absolute MB/s are modest — the ratio is the signal; an out-of-order RVV core would do better.
  • loong64 — real Loongson 3A5000 (LSX): ~11.4× the scalar baseline — a strong, measured native win.

Coverage

100% of the Go code, gated on every architecture (native amd64 + arm64, riscv64 + loong64 + ppc64le + s390x under QEMU). Both amd64 dispatch branches (AVX2 and the SSE fallback) are exercised on the native amd64 runner by toggling the feature flag. The .s kernels are validated by differential tests against a byte-by-byte reference plus a fuzz target.

Regenerating

go get github.com/go-asmgen/asmgen@v0.5.0 && go generate ./... && go mod tidy

BSD-3-Clause.