Friday, October 2, 2026
HomeGolangMonoslices: Generate specialised slice operations for a 2-10× speedup - Releases

Monoslices: Generate specialised slice operations for a 2-10× speedup – Releases


The usual library’s slices bundle consists of a lot of operations that take perform arguments to manage their conduct: SortFunc, EqualFunc, and many others. These operations are versatile, however they management their conduct utilizing perform parameters, which may inhibit compiler optimizations, they usually can do lots of copying, internally and to cross slice parts to these features by worth. In consequence, they will go away a lot of efficiency on the desk.

To resolve this, I wrote monoslices: a instrument that generates specialised (“monomorphic”) variations of the slices.*Func operations.

monoslices is just not a library. It generates code that will get checked into your mission and provides no module dependencies. The generator itself is meant to be put in as a instrument dependency in your mission, which helps with versioning and toolchain consistency:

go get -tool github.com/zolstein/monoslices

Then, it’s invoked with:

go instrument monoslices

from the CLI, or by way of go generate.

As an alternative of writing:

slices.SortFunc(data, compareRecords)

you declare compareRecords because the comparator for a generated set of operations:

func compareRecords(a, b Report) int { … }

//monoslices:generate identify=Information cmp=compareRecords

and monoslices generates features like:

func RecordsSort(s []Report)
func RecordsBinarySearch(s []Report, goal Report) (int, bool)
func RecordsMin(s []Report) Report

These generated features are primarily based on the usual library implementations, however name compareRecords instantly. In consequence, the compiler has rather more room to optimize.

It additionally helps specialization features that obtain tips to parts as a substitute of copies, utilizing the byref possibility:

func compareRecords(a, b *Report) int { … }

//monoslices:generate identify=Information cmp=compareRecords byref=true

How a lot this issues relies upon closely on the operation and ingredient sort. Some circumstances already get optimized effectively and there’s mainly no distinction. However for a lot of operations, the distinction is substantial, and byref advantages even reasonably sized values:

Operation 16 B worth 64 B by-ref 256 B by-ref
Equal 1.6-2.0× speedup 3.3-5.9× speedup 3.4-10× speedup
BinarySearch 1.7-1.9× speedup 1.8-2.3× speedup 2.9-3.8× speedup
Kind 1.7-2.1× speedup 3.3-4.0× speedup 4.2-5.3× speedup

A part of the explanation I wrote this was to discover the efficiency impression of specialization in Go. Specialization is a crucial a part of how languages like Rust and C++ generate environment friendly generic code. Generic Go code can’t focus on all the identical methods, and I needed to see how a lot distinction express specialization would make for some frequent Go operations.

It seems that, no less than for a few of them, the distinction is fairly giant. I hope to see higher help for this type of optimization in Go over time, whether or not that’s by language adjustments, compiler enhancements, or higher codegen tooling and a tradition that encourages writing code turbines like this.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments