11
7

More than 3 years have passed since last update.

Goで空のスライスを作る時

Posted at

Goにおける空スライスの作り方

Goでは空のスライスを作る方法が二種類あります。
型Typeについて
1. スライスリテラル記法による作成 []Type{}
2. Goのビルトイン関数による作成 make([]Type, 0)

正直どっちも対してやってることは変わらないだろうと思い習慣的に使っていたmakeによる作成をあらゆる場面で使っていました。というのも、makeはキャパシティ指定ができるので後からappendすることを想定した場合にキャパシティ確保分の時間をセーブできるだろうと思っていました。しかしある時にベンチマークを眺めているとruntime.mallocgcがやたらと時間を食っていたため掘っていくとmakeの行にたどり着いたため、「もしや」と思い空のスライスリテラルに書き換えてみたらパフォーマンスが改善しました。

ベンチマーク

こうなってくると実際にどの程度実行時に影響があるのかが気になります。そこで次のようなベンチマークを書いてみました。

func BenchmarkSliceAllocation(b *testing.B) {
    var p []byte

    b.Run("empty slice literal syntax", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            p = []byte{}
        }
    })

    func([]byte) {}(p)

    b.Run("make zero-length slice", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            p = make([]byte, 0)
        }
    })

    func([]byte) {}(p)
}
empty_slice_literal_syntax-4            161896716            0.765 ns/op
make_zero-length_slice-4                23673788             5.10 ns/op

実行してみてびっくり、なんと空のスライスリテラルはmakeの6倍以上早かったのです。

最適化に関してはド素人なのでこれ以上は掘ってないのですがそもそもキャパシティ付きでmakeする目的が間違ってたんだろうなという気持ちになりつつあります。
もし詳しい方がいたらご指摘いただけましたら幸いです。

11
7
10

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
7