Tuesday, October 6, 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 package deal contains plenty of operations that take operate arguments to regulate their habits: SortFunc, EqualFunc, and so forth. These operations are versatile, however they management their habits utilizing operate parameters, which may inhibit compiler optimizations, they usually can do plenty of copying, internally and to cross slice components to these features by worth. Because of this, they will depart 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 based mostly on the usual library implementations, however name compareRecords immediately. Because of this, the compiler has far more room to optimize.

It additionally helps specialization features that obtain tips that could components as an alternative 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 aspect sort. Some circumstances already get optimized properly 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 rationale I wrote this was to discover the efficiency influence 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 wished to see how a lot distinction specific specialization would make for some frequent Go operations.

It seems that, at the very least for a few of them, the distinction is fairly massive. I hope to see higher assist for this sort of optimization in Go over time, whether or not that’s by way of language modifications, compiler enhancements, or higher codegen tooling and a tradition that encourages writing code mills like this.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments