今天就跟大家聊聊有關(guān)APP是如何高效保存日志,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供甘泉網(wǎng)站建設(shè)、甘泉做網(wǎng)站、甘泉網(wǎng)站設(shè)計、甘泉網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、甘泉企業(yè)網(wǎng)站模板建站服務(wù),十載甘泉做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。
有過嵌入式開發(fā)經(jīng)驗的都知道日志的存儲是個比較麻煩的問題。之前ARM開源了一款項目:cmbacktrace,github地址就不貼了,可以將crash時的堆棧信息進行保存。但是對于手機app來說,光保存程序崩潰時的日志信息時遠(yuǎn)遠(yuǎn)不夠的,根本無法定位到具體原因。在講解淘系使用的日志系統(tǒng)之前,先看一下最通用的日志系統(tǒng)。
通用方案一
主流的日志模塊比如logback,是屬于實時日志記錄系統(tǒng),也就是每產(chǎn)生一句日志就進行加密存入磁盤文件。這樣有個缺點就是I/O過于密集占用大量CPU資源,影響程序性能,極易卡頓。一般使用與app開發(fā)調(diào)試階段,正式發(fā)版肯定要把log功能關(guān)閉,等用戶產(chǎn)生程序崩潰等反應(yīng)問題時,才重新打一個調(diào)試包進行復(fù)現(xiàn)。但是很多時候場景不完全相同,很難復(fù)現(xiàn)問題。
前文有講過cache數(shù)據(jù)與磁盤數(shù)據(jù)之間的關(guān)系:進程是如何使用內(nèi)存的?
程序?qū)懳募僮鞯臅r候,并不是直接操作磁盤里的文件,而是先把數(shù)據(jù)寫入系統(tǒng)緩存,也就是臟頁中,然后操作系統(tǒng)的守護進程update進程會定時(一般為30s)將臟頁更新到磁盤里。數(shù)據(jù)寫入磁盤存在兩次拷貝:從用戶空間內(nèi)存拷貝到內(nèi)核空間內(nèi)存,然后從內(nèi)核空間flush寫入到磁盤。加上具體寫入磁盤的操作無法由程序控制,因此這里會造成CPU峰值過高導(dǎo)致性能降低。
通用方案二
直接使用Android的logsdk當(dāng)然方便,但是會造成性能問題,那么我們可以先將日志保存到內(nèi)存緩存,達到一定大小后再加密寫入文件。同時為了減少數(shù)據(jù)流,先對數(shù)據(jù)進行壓縮再寫入(借鑒HTTP網(wǎng)絡(luò)傳輸?shù)淖龇ǎUw方案如下圖:
這種方案不需要實時保存日志,不會產(chǎn)生CPU峰值。但是丟日志的問題仍然沒解決。比如程序crash異常退出時,很多場景并不會有系統(tǒng)事件通知,也就無法保存crash時的堆棧。鵝廠的嵌入式操作系統(tǒng)Tencenttiny OS宣稱在stm32系列單板上解決了這個問題,但是使用起來仍然差強人意。更為重要的是,Android系統(tǒng)比嵌入式系統(tǒng)復(fù)雜的多,很多方案無法直接套用。
手淘優(yōu)化方案
手淘app主要從兩個方面來提高日志使用效率。
mmap
通過調(diào)用mmap存儲映射I/O,具體方案就是將磁盤文件映射到用戶空間緩沖區(qū)上,對內(nèi)存緩沖區(qū)執(zhí)行數(shù)據(jù)操作時,相當(dāng)于操作磁盤中的文件。這樣的好處就是不需要使用read和write。映射方案如下圖所示。
使用mmap的好處是免去一次實時數(shù)據(jù)拷貝,同時可以通過調(diào)用msync、munmap將數(shù)據(jù)臟頁寫回磁盤文件,對于應(yīng)用層可控(起一個后臺線程異步執(zhí)行就行)。優(yōu)化后具體效果可以參看APUE圖14-28。
這里要注意,intmadvise(caddr_t addr, size_t len, int advice);這個接口在Unix說明是可以通過使用madv_willneed參數(shù)來預(yù)加載磁盤文件到內(nèi)存,但是在mac上實驗并沒什么效果,因此妥善的方案是對每個頁執(zhí)行讀取一個字節(jié)的操作,這樣保證文件加載到內(nèi)存中。
數(shù)據(jù)壓縮
數(shù)據(jù)是先加密還是先壓縮?標(biāo)準(zhǔn)做法是先壓縮再加密。明文一般都有冗余度,壓縮之后內(nèi)容會變少。相反如果先加密,會破壞文件的冗余度。通用的壓縮方法主要有g(shù)zip、huffman等,手淘借鑒HTTP2的hpack頭部壓縮,在facebook開源的zstd壓縮算法基礎(chǔ)上進行了網(wǎng)絡(luò)傳輸?shù)膬?yōu)化。因為日志中通常會有大量相同特性的短語,因此會在服務(wù)端常駐一個字典,并且適時更新由客戶端拉取,通過字典壓縮提升壓縮率。同時為了防止數(shù)據(jù)損壞影響整個壓縮包無法解壓,采用流式壓縮(即日志達到32k時進行壓縮)。分塊壓縮雖然總體效率略低,但是因為不會在短時間內(nèi)幾種打包壓縮,不會造成CPU峰值。
實際使用過程中還對外置SD卡進行了適配,當(dāng)SD卡被刪除時會將日志存入臨時緩存,每次進程被殺掉時清理緩存,防止長時間占用用戶空間造成輿情。
看完上述內(nèi)容,你們對APP是如何高效保存日志有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。