開発中のアプリのパフォーマンスの改善のために、Instrumentsで→↓→↓→↓→↓しているときに、Date
のExtensionの処理がちょくちょく出てきた。
調べてた結果↓
Cache Formatters for Efficiency
Creating a date formatter is not a cheap operation. If you are likely to use a formatter frequently, it is typically more efficient to cache a single instance than to create and dispose of multiple instances. One approach is to use a static variable.
by Data Formatting Guide - developer.apple.com
DateFormatter
のインスタンス生成は、軽い処理ではないため、何度も使われる箇所では単一のDateFormatter
のインスタンスをキャッシュして使いまわそうとのこと。。。
パフォーマンス計測
パフォーマンスコード
// DateFormatter ではなく ISO8601DateFormatter を使用 🙇
extension Date {
private struct Formatter {
static let iso8601Formatter: ISO8601DateFormatter = ISO8601DateFormatter()
}
var ISO8601String: String {
let formatter = ISO8601DateFormatter()
return formatter.string(from: self)
}
var ISO8601StringWithCache: String {
return Formatter.iso8601Formatter.string(from: self)
}
}
let count = 10000
let date = ISO8601DateFormatter().date(from: "1990-01-01T00:00:00+0900")!
var start = Date()
(1...count).forEach { _ in
_ = date.ISO8601String
}
print("毎回インスタンスを生成: \(Date().timeIntervalSince(start))")
start = Date()
(1...count).forEach { _ in
_ = date.ISO8601StringWithCache
}
print("インスタンスを生成キャッシュ: \(Date().timeIntervalSince(start))")
結果
毎回インスタンスを生成: 3.0555260181427
インスタンスを生成キャッシュ: 0.5390740633010864
まとめ
- 定期的にパフォーマンス計測をして、アプリのパフォーマンス改善をしてみましょう
-
Date
のExtensionを確認してみよう - むやみなFormatterのキャッシュは注意
参考
- https://blog.kishikawakatsumi.com/entry/20140214/1392372659
- https://stackoverflow.com/questions/38574569/performance-issues-while-parsing-dates
- https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW12
- https://tech-tokyobay.manju.tokyo/archives/87