inari111 blog

Webエンジニアの備忘録

Goでsliceを結合するときのパフォーマンスについて

sliceを結合するときに、どういう書き方をするのがパフォーマンスがいいのか気になって検証してみた。 検証したのは2パターン。

パターン1: slice同士を結合

func appendSlice(n int) []string {
    sliceA := make([]string, n)
    sliceB := make([]string, n)

    for i := 1; i <= n; i++ {
        sliceA = append(sliceA, "a")
        sliceB = append(sliceB, "b")
    }
    sliceA = append(sliceA, sliceB...)

    return sliceA
}

パターン2: forで回しながらappend

func appendSlice2(n int) []string {
    sliceA := make([]string, n)
    sliceB := make([]string, n)

    for _, s := range sliceB {
        sliceA = append(sliceA, s)
    }

    return sliceA
}

パフォーマンスを計測するためにベンチマークを書く。

package main

import "testing"

func BenchmarkAppendSlice(b *testing.B) {
    b.ResetTimer()
    appendSlice(b.N)
}

func BenchmarkAppendSlice2(b *testing.B) {
    b.ResetTimer()
    appendSlice2(b.N)
}

パターン1のベンチマーク

$ go test -count 10 -test.bench BenchmarkAppendSlice

BenchmarkAppendSlice-8       2000000           631 ns/op
BenchmarkAppendSlice-8       2000000           596 ns/op
BenchmarkAppendSlice-8       2000000           631 ns/op
BenchmarkAppendSlice-8       2000000           595 ns/op
BenchmarkAppendSlice-8       2000000           602 ns/op
BenchmarkAppendSlice-8       2000000           600 ns/op
BenchmarkAppendSlice-8       2000000           596 ns/op
BenchmarkAppendSlice-8       2000000           598 ns/op
BenchmarkAppendSlice-8       2000000           597 ns/op
BenchmarkAppendSlice-8       2000000           596 ns/op
PASS
ok      github.com/inari111/test    18.915s

パターン2のベンチマーク

$ go test -count 10 -test.bench BenchmarkAppendSlice2
BenchmarkAppendSlice2-8      5000000           253 ns/op
BenchmarkAppendSlice2-8     10000000           243 ns/op
BenchmarkAppendSlice2-8     10000000           206 ns/op
BenchmarkAppendSlice2-8     10000000           204 ns/op
BenchmarkAppendSlice2-8     10000000           198 ns/op
BenchmarkAppendSlice2-8     10000000           205 ns/op
BenchmarkAppendSlice2-8     10000000           200 ns/op
BenchmarkAppendSlice2-8     10000000           201 ns/op
BenchmarkAppendSlice2-8     10000000           201 ns/op
BenchmarkAppendSlice2-8     10000000           202 ns/op
PASS
ok      github.com/inari111/test    22.293s

まとめ

パターン1のslice同士の結合のほうがパフォーマンスよさそう。
もし間違ってたら教えていただけると嬉しい。