I’ve been searching for a way to remove an element from a slice in go an I basically came across two methods,
1: s = append(s[:i], s[i+1:]...)
2: s[i], s = s[len(s)-1], s[:len(s)-1]
where version 2 was deemed faster.
I did some benchmarking and the results I don’t quite understand:
1: BenchmarkSliceOrder-12 1000000000 0.0001861 ns/op
2: BenchmarkSliceNoOrder-12 1000000000 0.0001618 ns/op
Which would indicate that it makes no real difference.
Important to note here is that the index of the element to be removed was chosen randomly over the complete length of the slice (i := rand.Intn(limit)
). I also found that there are specific indices where it does make a difference but factor 2 at max.
Since I thought the Version 1 involves much more copying when the index is small I did two more tests:
i = 2, limit 100000
:
BenchmarkSliceOrder-12 1000000000 0.008157 ns/op
BenchmarkSliceNoOrder-12 1000000000 0.01165 ns/op
i = limit - 2, limit 100000
:
BenchmarkSliceOrder-12 1000000000 0.01550 ns/op
BenchmarkSliceNoOrder-12 1000000000 0.01599 ns/op
So what’s the deal with slices in go? should we not bother about optimization or what?
My code for reference:
var limit int = 100000
func BenchmarkSliceOrder(b *testing.B) {
s := make([]string, limit)
for i := 0; i < limit; i++ {
s[i] = fmt.Sprintf("string%d", i)
}
//i := rand.Intn(limit)
i := limit / 2
s = append(s[:i], s[i+1:]...)
}
func BenchmarkSliceNoOrder(b *testing.B) {
s := make([]string, limit)
for i := 0; i < limit; i++ {
s[i] = fmt.Sprintf("string%d", i)
}
//i := rand.Intn(limit)
i := limit / 2
s[i] = s[len(s)-1]
s = s[:len(s)-1]
}
atoms.h is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.