前言
我覺得開發(fā)技術的提升不僅僅是知識含量的增加,更重要的是開闊自己的思路,在解決同樣的問題時方案能夠更勝一籌,讓程序能夠更有效率,更優(yōu)雅。這些思路往往都是在冥思苦想后的靈光一現(xiàn)。下面我舉幾個例子,包括 JSPatch 的方法調用思路,微信讀書如何處理數(shù)據(jù)層卡頓,微信終端跨平臺組件 mars 里日志模塊 xlog 的性能優(yōu)化方案,以及自己在 SMCheckProject 項目中對使用方法的解析思路。
JSPatch中的方法調用
JSPatch作者 bang 在 《JSPatch實現(xiàn)原理詳解》 這篇博客中提到方法調用的實現(xiàn)比如 UIView.alloc() 在開始時為了能夠讓這個方法調用,需要給 UIView 對象添加 alloc 方法。由于 JS 沒有 OC 那樣的轉發(fā)機制,所以 bang 開始的時候采用了一個復雜的方式,在 require 生成類對象時通過類名用 Runtime 的方法找出此類所有方法,然后 JS 為每個方法生成一個函數(shù),這樣的函數(shù)用方法名去 OC 調用對應的方法。
這樣的想法可行,但是效率性能難以接受,消耗的增長是指數(shù)級的。因為不光是當前的類需要遍歷,父類直到頂層都需要,會出現(xiàn)內存消耗過度的問題。后來 bang 苦苦找解決方案,突然腦洞大開,想到如果能夠實現(xiàn)調用一個不存在的方法能夠轉發(fā)到一個指定函數(shù)執(zhí)行就好了,于是把 JS 里方法調用都替換掉改成調用 __c() 函數(shù),把相關信息傳給 OC ,OC 再用 Runtime 來調用相應的方法返回結果。這樣做不用遍歷,不用保存方法,我覺得這種腦洞大開想到的方案的這種思路是非常值得學習,當一種思路越陷越深時,要時刻提醒自己,跳出來再看看,是不是還有其它的路可以走。
微信讀書處理數(shù)據(jù)層卡頓
在 WeRead團隊博客里有篇文章 《微信讀書 iOS 質量保證及性能監(jiān)控》 介紹了他們對數(shù)據(jù)層的性能監(jiān)控。他們數(shù)據(jù)層使用的是 YDataCenter,在這個數(shù)據(jù)層框架里一次 SQL 的完整操作要經過等待 cache 隊列,放入 cache 隊列執(zhí)行,等待 db 隊列,放入 db 隊列四個步驟。將這四個步驟的時間和對應 SQL 記錄下來,因為這樣的 SQL 操作較多,所以只將超過指定時間的記錄下來,這樣能以最小的代價找出那些造成阻塞卡頓的 SQL 和場景出來進行優(yōu)化。
日志文件寫磁盤導致大量IO引起程序卡頓
微信團隊在介紹他們微信終端跨平臺組件 mars 里的日志模塊時提到了他們對日志寫磁盤處理的考慮過程。一般的簡單的處理都會采取兩次數(shù)據(jù)拷貝實現(xiàn)寫入磁盤,第一次是從用戶空間內存拷貝到內核空間的緩存,第二次是回寫內核空間的緩存到磁盤。但是頻繁的空間切換使得應用層的性能不可控。
一般為了解決空間切換都會采用先將日志緩存到內存中,達到設置的大小后再壓縮加密寫入文件,但是這個方案的壓縮還是會有讓 cpu 飆升的可能,還有個很嚴重的丟日志的問題。如何能夠完美處理呢。
mars 的日志模塊 xlog 最終采用了 mmap 這種內存映射文件的方法來作為一個既能夠有直接寫內存的性能,又具有直接寫文件可靠性的方案。從測試來看寫內存和寫 mmap 的耗時幾乎是一樣的。
SMCheckProject項目中對使用過的方法的解析
在 SMCheckProject 這個項目有需要解析出所有使用過的方法,一開始會想到使用遞歸,以前我做 STMAssembleView 中對自定義的 DSL 語言解析時就是使用的遞歸,這樣時間復雜度就會是 O(nlogn) ,這次我換了個思路,將復雜度降低到了 n ,思路大概是 創(chuàng)建一個字典,鍵值就是深度,模擬語法樹結構,從左到右深度的增加根據(jù) [ 符號,減少根據(jù) ] 符號,值會在 [ 時創(chuàng)建一個 Method 結構體,根據(jù) ] 來完成結構體,將其添加到 methods 數(shù)組中 。 這種優(yōu)化在項目小文件少時看不出很大的區(qū)別,但是在項目規(guī)模非常龐大時卻能將總時間省掉不少。
靈光一現(xiàn)后需要付出的努力
當然光是有個好的思路和想法是完全不夠的,為了能夠實現(xiàn)思路也是八方英雄各顯神通。從有了利用編譯原理中分析語法轉換語法這個思路進行動態(tài)化開始,逐步演化到開發(fā)一套全自動編譯器實現(xiàn)OC源碼轉字節(jié)碼后通過自建虛擬機與Native運行時互聯(lián)。下面我列出些相關的文章,可以看到大量的基礎知識積累是這些好的思路必備的基礎,光是有著靈活的大腦也是不夠的。
- 用 Swift 搭建一個微型編譯器
- Antlr
- 從antlr扯淡到一點點編譯原理
- JSPatch Convertor 實現(xiàn)原理詳解
- JSPatch實現(xiàn)原理詳解
- Swift Playground微型編譯器
- 4種語言編譯器加字節(jié)碼虛擬機
- 如何著手看懂Clang Static Analyzer的源碼工作流程?
- Swift: Challenges and Opportunity for Language and Compiler Research
- DynamicCocoa:滴滴 iOS 動態(tài)化方案的誕生與起航
- OCS——史上最瘋狂的iOS動態(tài)化方案 - 簡書