Image for post
Image for post
slice it how you want

Bad Go: slices of pointers

This post is also here, where the code is better formatted!

This is the first of what may be a series of blog posts on uses of Go that I’ve found frustrating. They’re mostly minor things that could just be better without being more complicated. I’m going to try to not only explain why they are bad but also demonstrate it.

First up is slices of pointers. Things like []*MyStruct. Unless you need to express that certain indices in the slice are nil, then this is just wasteful and []MyStructis better in almost all circumstances.

Let’s start with some benchmarks. Here’s the struct we’re going to use.

First we’ll benchmark building a slice of 100 entries, each of which is a pointer to a MyStruct. We’ll fill in the fields in the struct just for laughs.

Next we’ll do the same, but use a []MyStruct.

We run the benchmarks with go test -bench . -count 10 > run1.txt, then analyse the results with benchstat run1.txt. Here are the results.

The no-pointer version allocates less memory, performs fewer allocations and is over an order of magnitude faster.

Why is it faster? Well, the pointer version allocates a new piece of memory for each entry in the slice, whereas the non-pointer version simply fills in the A & B ints in the slice entry itself. Allocating memory takes time — somewhere around 25ns per allocation — and hence the pointer version must take ~2500ns to allocate 100 entries.

Are there any downsides? Not really.

But I want to change entries in the slice!

You can still do this with a non-pointer slice. You can obtain a pointer to an entry in the slice and change it.

But I really need a slice of pointers to pass to this library

OK, sometimes you’re forced to use a slice of pointers because that’s what a library needs. If you can’t change the library then perhaps you just do need to build a slice of pointers. You might still be better off using a slice of non-pointers to do this! First build up the slice of non-pointers, then build a slice of pointers from that. You’ll likely end up with fewer allocations overall.

We can benchmark this too.

This time we don’t have to make a fresh allocation for each slice entry in the []*MyStruct - we just use pointers to the entries in []MyStruct. The amount of memory allocated it about the same, but it’s done in many fewer allocations.

But my function returns a *MyStruct

Does it have to? Could you change it to return a MyStruct instead?

But … it’s complicated!?

Remember this is just a suggestion. If your case is complicated perhaps you can write a benchmark to see whether changing things will make a worthwhile improvement. I’m just saying that perhaps []MyStruct should be the normal case, and you should use slices of pointers only where they are necessary.

I’m kind of hoping and kind of dreading that no-one out in the world uses slices of pointers, and therefore this post has fallen completely flat. I hesitate to say let me know on twitter…

Written by

software, fraud, bicycles — Fighting bad people at ravelin.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store