[Swift] 配列(Array) reserveCapacity にはどれくらいの効果があるのか

2020年8月1日土曜日

Swift

t f B! P L

UnityC#にて

var list = new List<int>(10)

というように初期に最低限必要と思われるメモリ容量を確保しておくと処理が軽くなって高速化するときいた

UnityC# で手軽にできる高速化テクニックを7種類、紹介しています。※コメントにて動画の補足情報があります。 ▼『Unity使いこなし術』の再生リスト https://www.youtube.com/playlist?list=PLKDiJl9C6HD43V-HdFI55pUkXsMR3N_Ib ★今回の内容...

そこでSwiftではどのようにこの初期メモリ確保できるのか調べたところ

reserveCapacityという物があった

ではどれくらい速くなるのだろうか気になったので調べた

環境

MacBook Pro (13-inch, 2018)

MacOS Catalina 10.15.6

Apple Swift version 5.2.4 (swiftlang-1103.0.32.9 clang-1103.0.32.53)

結論

  • reserveCapacityを使っても使わなくてもほぼ変わらない
  • 確保したCapacityサイズが小さい場合、遅くなる
  • 余裕を持ってCapacityを確保すると少し速くなる時が稀にある
  • 特別な理由がなければ使う必要なさそう

僕の測定方法が正しければこの結果になる。

UnityC#ほど重要視する必要ないように思った

まあ、Swift(速い)というだけ最適化されてるのかな?

実験

使用したコードと結果を貼り付けておきます

Benchmarkクラスは他の時も使うので少しオプションが多くなっています。

読みにくくてすみません。

Benchmark.swift

まず、使用したコードです。

なんとなくArrayクラスも測定してみました。


import Foundation

Benchmark.Excute("set capacity", decimal: 5, ave: true){
    var a: [Int] = []
    a.reserveCapacity(100000)
    for i in 0...100000 {
        a.append(i)
    }
}

Benchmark.Excute("normal", decimal: 5, ave: true){
    var a: [Int] = []
    for i in 0...100000 {
        a.append(i)
    }
}

Benchmark.Excute("use Array class", decimal: 5, ave: true){
    var a: Array<Int> = Array()
    for i in 0...100000 {
        a.append(i)
    }
}


class Benchmark {
  static func Excute( _ name: String, decimal: Int = 3 , ave: Bool = false , _ process: () -> ()) {
    let aveLoop: Int = 20
    var elapsed: TimeInterval
    if ave {
        var r: TimeInterval = 0
        for _ in 0...aveLoop {
            let start = Date()
            process()
            r += Date().timeIntervalSince(start)
        }
        elapsed = r/Double(aveLoop)
    }else {
        let start = Date()
        process()
        elapsed = Date().timeIntervalSince(start)
    }
    let formatedElapsed = String(format: "%.\(decimal)f", elapsed)
    print("""
    [result]
    name : \(name)
    time : \(formatedElapsed)

    """)
  }
}
			

結果

Capacityを確保した時

0.09695 ~ 0.09772


普通の配列(Capacityを確保しない)

0.09641 ~ 0.09699


Arrayクラス

0.09541 ~ 0.09777

まとめ

何も気にせずに普通の配列使ってればいいなと思いました。

ミスや、僕が勘違いしている点などがあったら指摘していただけると嬉しいです。

自己紹介

自分の写真
県立高校理数科2年
Unity2年目
Twitter
Note

人気の投稿

[Vim] coc.nvim + coc-clangdの構文チェックでboostのエラーが発生する

C++の拡張ライブラリ、Boost。 AtCoderでも使用が認められているライブラリです。 様々な便利機能が搭載されています。 競技プログラミングで使えるBoostライブラリ 初級編 から一部抜粋すると、 boost...

QooQ