YSNHatenaBlog

iOS, Swift, Android, Web, JavaScript, AWSなどについて

SwiftのOptionalのオーバーヘッド

気になることがあってOptionalのunwrapのオーバーヘッドを調べてみました。

先に結論

  • 参照型のunwrapはパフォーマンスが低下する
  • 値型のunwrapはあまりパフォーマンスは低下しない

方法

Counterという型のcountを10,000,000回インクリメントするのを10回平均するコードを書いて、 アプリの起動時に計測させるようにしました。

環境: iPhone 7, デバッグ実行

Optionalな参照型の場合

class Counter {
    
    var count: Int = 0
}

let n = 10
var sum: TimeInterval = 0

for _ in 0..<n {

    let now = Date()
    let counter: Counter? = Counter()

    for _ in 0..<10000000 {
        
        counter?.count += 1
    }
    
    sum += -now.timeIntervalSinceNow
}

let ave = sum / Double(n)
print(ave)

結果: 0.248754590749741[秒]

counterのOptionalを外してみました。 該当箇所だけ書きます。

    let counter: Counter = Counter()

    for _ in 0..<10000000 {
        
        counter.count += 1
    }

結果: 0.0492702841758728[秒]

かなり違います。

ちなみにforce unwrapでも遅いです。

let counter: Counter! = Counter()

for _ in 0..<10000000 {
    
    counter.count += 1
}

結果: 0.234673696756363[秒]

Optionalな値型の場合

ほぼ同じコードで、Counterstructにしてみます。

struct Counter {
    
    var count: Int = 0
}

let n = 10
var sum: TimeInterval = 0

for _ in 0..<n {

    let now = Date()
    var counter: Counter? = Counter()

    for _ in 0..<10000000 {
        
        counter?.count += 1
    }
    
    sum += -now.timeIntervalSinceNow
}

let ave = sum / Double(n)
print(ave)

結果: 0.0521551012992859[s]

速いです。

Optionalを外してみます。

var counter: Counter = Counter()

for _ in 0..<10000000 {
    
    counter.count += 1
}

結果: 0.0496872007846832[s]

あまり変わらないです。