[Swift 4] 文字列Subscriptについての検証と訂正

2017.09.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

先日掲載させていただきました [iOS 11] Swift 4は前バージョンから何が変わったか比較した の記事の中の 文字列(String)の強化 の項で、「文字列Subscript」について掲載しました。

その件について、monoさん からパフォーマンスコストについて指摘をいただきまして、あらためて検証をさせていただきました。 (ご指摘いただきましてありがとうございました)

extension String {
    
    func useMapPattern(_ i: Int) -> String {
        return map {String($0)}[i]
    }
    
    func useIndexPattern(_ i: Int) -> String  {
        return String(self[index(startIndex, offsetBy: i)])
    }
}

let str = """
1234567890\
1234567890\
1234567890\
1234567890\
1234567890\
1234567890\
1234567890\
1234567890\
1234567890\
1234567890
"""

var start: Date

start = Date()
for _ in (0...1000) {
    str.useMapPattern(99)
}
print(NSDate().timeIntervalSince(start))

start = Date()
for _ in (0...1000) {
    str.useIndexPattern(99)
}
print(NSDate().timeIntervalSince(start))

内容としましては、ブログに掲載した2つのパターンを String の拡張メソッドとして定義して、 100文字ある文字列の最後の文字を取得するという処理を Date クラスの仕組みを使って簡易的にベンチマーク計測しています。

結果は下記のようになりました。

1回目
6.08517903089523
0.146593034267426

2回目
5.52418601512909
0.098488986492157

3回目
5.80206298828125
0.0801700353622437

火を見るより明らかに、Indexを使った方法のほうがパフォーマンスは高いです。

掲載をする前に何度かの速度計測をしていたのですが、そこに何かしらの誤りがあったようです。 もし記事をご覧になって間違った認識をさせてしまっていましたら、お詫び申し上げます。 元記事も訂正させていただきますので、よろしくお願いいたします。