Keito

© 2024 Keito

技術ブログとポートフォリオ

【Go】スライスに要素を追加する処理のベンチマークテスト比較

更新日2025/3/13/(木) 12:38
タグ
Go

概要

スライスに要素を追加するappendインデックスを直接指定する方法のパフォーマンスが気になったので、ベンチマークテストの比較を行ってみた。

環境

  • MacBook Air M1 メモリ16GB、go 1.23.0

計測方法

  • []int型のスライスに10,000,000回要素を追加する処理のベンチマークテストを実施

サンプルコード

package main import "testing" const size = 10000000 // ベンチマーク関数: append の場合 func BenchmarkAppend(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { var slice []int for j := 0; j < size; j++ { slice = append(slice, j) } } } // ベンチマーク関数: slice[i] = int の場合 func BenchmarkIndexAssignment(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { slice := make([]int, size) for j := 0; j < size; j++ { slice[j] = j } } }

計測結果

goos: darwin goarch: arm64 pkg: performance cpu: Apple M1 BenchmarkAppend-8 40 29059970 ns/op 492000713 B/op 51 allocs/op BenchmarkIndexAssignment-8 264 4503033 ns/op 80003085 B/op 1 allocs/op PASS ok performance 3.679s

※ベンチマークテストでは内部で複数回の計測を実施しており、テストを数回実行しても結果のばらつきはほとんどなかったので1回分のみを記載

append(BenchmarkAppend-8)

  • 実行回数: 40回
  • 平均実行時間: 29,059,970 ns/op(約29.1ms/1回)
  • メモリ使用量: 492,000,713 B/op(約492MB/1回)
  • メモリアロケーション回数: 51回

インデックス指定(BenchmarkIndexAssignment-8)

  • 実行回数: 264回
  • 平均実行時間: 4,503,033 ns/op(約4.5ms/1回)
  • メモリ使用量: 80,003,085 B/op(約80MB/1回)
  • メモリアロケーション回数: 1回

比較

appendインデックス指定
実行回数40回264回
平均実行時間29,059,970 ns/op(約29.1ms/1回)4,503,033 ns/op(約4.5ms/1回)
メモリ使用量492,000,713 B/op(約492MB/1回)80,003,085 B/op(約80MB/1回)
メモリアロケーション回数51回1回
  • 実行回数
    • インデックス指定append と比べて実行回数は 約6倍多い
  • 実行時間
    • インデックス指定append と比べて実行速度が 約6倍速い
  • メモリ使用量
    • インデックス指定append約6分の1 のメモリ使用量
  • アロケーション回数:
    • インデックス指定 は最初に要素数分のメモリを確保するので 1回 のみ

結論

  • 今回の計測方法ではインデックス指定の方が append より 実行速度、メモリ効率共に優れている結果となった
  • データ量が少ないときはそこまで影響はないかもしれないが、スライスに要素を追加する際にあらかじめサイズが分かっている場合は、インデックスを指定する方法を使用するようにしたい