📚

【Go】スライスに要素を追加する処理時間の比較

2024/11/15に公開

概要

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

環境

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

計測方法

  • []int型のスライスに10,000,000回要素を追加する処理を100回繰り返し、インデックスを直接指定する方法がappendの何倍速いかを計測。
  • バラつきがあるかもしれないので↑を10回計測する。

サンプルコード

package main

import (
	"fmt"
	"time"
)

func main() {
	for i := 0; i < 10; i++ {
		fmt.Printf("-----%v回目-----\n", i+1)
		PerformanceHnadler()
	}
}

func PerformanceDemo(size int) (appendElapsed, indexElapsed time.Duration) {
	var slice []int

	// appendのパフォーマンス測定
	start := time.Now()
	for i := 0; i < size; i++ {
		slice = append(slice, i)
	}
	appendElapsed = time.Since(start)

	// スライスをリセット
	slice = make([]int, size)

	// インデックスを指定して直接要素を追加のパフォーマンス測定
	start = time.Now()
	for i := 0; i < size; i++ {
		slice[i] = i
	}
	indexElapsed = time.Since(start)

	return appendElapsed, indexElapsed
}

func PerformanceHnadler() {
	const size = 10000000
	count := 100
	var appendElapsed, indexElapsed time.Duration
	for i := 0; i < count; i++ {
		ae, ie := PerformanceDemo(size)
		appendElapsed += ae
		indexElapsed += ie
	}
	fmt.Printf("スライスに %v 個の要素を追加。 %v 回繰り返す\n", size, count)
	fmt.Printf("append: %v\n", appendElapsed)
	fmt.Printf("インデックスを指定して直接要素を追加: %v\n", indexElapsed)

	// appendElapsed が 0 でないことを確認して比率を計算
	if appendElapsed <= 0 {
		fmt.Println("appendElapsedが0のため、比率を計算できません")
	}
	speedRatio := float64(appendElapsed) / float64(indexElapsed)
	fmt.Printf("インデックス指定の方が append より %.2f 倍速い\n", speedRatio)
}

計測結果

-----1回目-----
スライスに 10000000 個の要素を追加。 100 回繰り返す
append: 2.495103789s
インデックスを指定して直接要素を追加: 353.483706ms
インデックス指定の方が append より 7.06 倍速い
-----2回目-----
スライスに 10000000 個の要素を追加。 100 回繰り返す
append: 2.401919877s
インデックスを指定して直接要素を追加: 332.053092ms
インデックス指定の方が append より 7.23 倍速い
-----3回目-----
スライスに 10000000 個の要素を追加。 100 回繰り返す
append: 2.410335913s
インデックスを指定して直接要素を追加: 332.230956ms
インデックス指定の方が append より 7.26 倍速い
-----4回目-----
スライスに 10000000 個の要素を追加。 100 回繰り返す
append: 2.441136288s
インデックスを指定して直接要素を追加: 333.297583ms
インデックス指定の方が append より 7.32 倍速い
-----5回目-----
スライスに 10000000 個の要素を追加。 100 回繰り返す
append: 2.469971122s
インデックスを指定して直接要素を追加: 334.017664ms
インデックス指定の方が append より 7.39 倍速い
-----6回目-----
スライスに 10000000 個の要素を追加。 100 回繰り返す
append: 2.526165877s
インデックスを指定して直接要素を追加: 334.303588ms
インデックス指定の方が append より 7.56 倍速い
-----7回目-----
スライスに 10000000 個の要素を追加。 100 回繰り返す
append: 2.515495208s
インデックスを指定して直接要素を追加: 333.801793ms
インデックス指定の方が append より 7.54 倍速い
-----8回目-----
スライスに 10000000 個の要素を追加。 100 回繰り返す
append: 2.524867495s
インデックスを指定して直接要素を追加: 333.606957ms
インデックス指定の方が append より 7.57 倍速い
-----9回目-----
スライスに 10000000 個の要素を追加。 100 回繰り返す
append: 2.522722656s
インデックスを指定して直接要素を追加: 333.727789ms
インデックス指定の方が append より 7.56 倍速い
-----10回目-----
スライスに 10000000 個の要素を追加。 100 回繰り返す
append: 2.535952582s
インデックスを指定して直接要素を追加: 332.531624ms
インデックス指定の方が append より 7.63 倍速い

結論

  • 今回の計測方法ではインデックス指定の方が append より 約7倍速かった
  • データ量が少ないときはそこまで影響はないかもしれないが、スライスに要素を追加する際にあらかじめサイズが分かっている場合は、インデックスを指定する方法を使用するようにしたい
  • ベンチマークテストも行ってみたい
GitHubで編集を提案

Discussion