在用instruments的time profiler工具測試之後,我驚奇地發現大約一半的處理時間用於解析日期,所以我的任務是提高日期解析效能。
每個json物件可能有幾個日期,格式為iso 8601
字串。 對於每個物件,使用dateformatter
將日期字串轉換為date
物件,然後使用core data
儲存這些物件。 我正在為每個物件建立乙個新的日期格式轉換方法,類似於以下:
for datestring in lotsofdatestrings
複製**
你可能不認為建立乙個dateformatter
物件會非常昂貴,但是你錯了:建立一次dateformatter
並重新使用它會帶來很大的效能提公升。
首先,它到底有多快? 格式化100,000個日期字串的簡單測試發現以下內容:
formatter creation
time
*****
10.88 seconds
once
4.15 seconds
哇 - 這是乙個很大的進步。 不足以完全解決效能問題,但足以說明dateformatter
建立成本很高。
我建議使用類似以下方式作為建立任何dateformatter
的預設方式。 使用此方法建立的dateformatter
都會自動快取以供日後使用,即使對於uitableview
單元重用等更複雜的情況也是如此。 要使用它,只需呼叫dateformatter.cached(withformat:「」
) - 沒有比這更容易了。
private
var cachedformatters = [string : dateformatter]()
extension
dateformatter
let formatter = dateformatter()
formatter.dateformat = format
cachedformatters[format] = formatter
return formatter
}}複製**
儘管有很大改進,但速度提公升2倍還不夠。經過一番研究,我發現ios 10
有乙個新的日期格式化類,iso8601dateformatter
......很好!不幸的是ios 9
支援是必須的,但是讓我們看看它與普通的舊dateformatter
相比如何。
使用100,000個日期字串執行相同的測試出需要4.19秒,這比dateformatter
慢一點,但僅僅是。如果你支援ios 10+
並且效能不是問題,你應該仍然可以使用這個新類,儘管速度會有輕微降低 - 它可能會更徹底地處理所有可能的iso 8601
標準。
對替代日期解析解決方案的更多研究獲得了乙個有趣的函式:strptime()
。 它是乙個舊的c函式,用於低階日期解析,完成我們需要的所有格式化說明符。 它可以直接在swift中使用,你可以按如下方式使用它。
func
parse
(datestring: string)
-> date?
strptime(cdatestring, "%y-%m-%dt%h:%m:%s%z", &timecomponents)
return
date(timeintervalsince1970: double(mktime(&timecomponents)))
}複製**
最終的解決方案使用另乙個從sscanf()
派生的c函式vsscanf()
。
vsscanf()
速度很快,但我花了一些時間搞清楚如何將其轉換為date
而不會影響效能。 讓我們直截了當:
class
iso8601dateparser
) components.year = year.pointee
components.minute = minute.pointee
components.day = day.pointee
components.hour = hour.pointee
components.month = month.pointee
components.second = int(second.pointee)
// work out the timezone offset
if houroffset.pointee < 0
let offset = parsecount <= 6 ? 0 :
houroffset.pointee * 3600 + minuteoffset.pointee * 60
// cache calendars per timezone
// (setting it each date conversion is not performant)
iflet calendar = calendarcache[offset]
var calendar = calendar(identifier: .gregorian)
guard
let timezone = timezone(secondsfromgmt: offset) else
calendar.timezone = timezone
calendarcache[offset] = calendar
return calendar.date(from: components)
}}複製**
這可以在0.67秒內解析100,000個日期字串 - 幾乎比原始方法快20倍,比使用快取dateformatter
快6倍。
另外我也看到兩篇dateformatter效能**的文章,可以配合著看
[效能優化]dateformatter輕度優化探索
[效能優化]dateformatter深度優化探索
效能測試 效能測試步驟
針對此次庫內作業效能測試,梳理一下期間的工作流程 梳理已有的介面指令碼,確認需要做效能測試的幾個介面,即使用率高,對效能有要求的幾個主要介面。結合頁面的操作,和確認的介面,梳理具體的業務邏輯 同時,請開發人員部署了測試環境。測試環境的伺服器指標,盡量和生產環境一致。部署的時候,負載均衡等情況也盡量和...
《效能之巔》初識效能
效能是一門令人激動 富於變化的學科同時又充滿挑戰的學科。衡量效能乙個重要指標 延時 系統效能是對於整個系統進行研究,包括了所有的硬體元件和整個軟體棧。通用的軟體棧有哪些呢?包括作業系統 os 核心,資料庫和應用程式層。術語中的 全棧 有時候指的是程式應用環境,包含資料庫,應用程式,和 伺服器。效能通...
PHP效能 序 談效能
這裡不談php的效能和其他語言的效能,這裡討論php自身的效能問題。效能是什麼?通俗的來講,效能,就是在固定的環境下能做的事情的多少。為什麼要效能?1 每乙個軟體或 的環境是相對固定的 2 在相當的一段時間內,在保障增加的使用者數量的同時使得當前環境的軟體或 能夠正常執行 3 為了省錢 php的效能...