原文鏈接:https://blog.csdn.net/Tencent_Bugly/article/details/53157830
舊日志方案
傳統(tǒng)的日志方案每有一句日志就加密寫進(jìn)文件。這樣在使用過程中不僅存在大量的 GC,更致命的是因?yàn)橛写罅康?IO 需要寫入,影響程序性能很容易導(dǎo)致程序卡頓。replase版本需要關(guān)閉,無法定位線上問題。
當(dāng)寫文件的時(shí)候,并不是把數(shù)據(jù)直接寫入了磁盤,牽涉到兩次數(shù)據(jù)拷貝:一次是用戶空間內(nèi)存拷貝到內(nèi)核空間的緩存dirty page中,一次是回寫時(shí)內(nèi)核空間的緩存到硬盤的拷貝。當(dāng)發(fā)生回寫時(shí),也涉及到了內(nèi)核空間和用戶空間頻繁切換。
系統(tǒng)一般會(huì)在下面幾種情況把 dirty page 寫入到磁盤:
- 定時(shí)回寫,相關(guān)變量在/proc/sys/vm/dirty_writeback_centisecs和/proc/sys/vm/dirty_expire_centisecs中定義。
- 調(diào)用 write 的時(shí)候,發(fā)現(xiàn) dirty page 占用內(nèi)存超過系統(tǒng)內(nèi)存一定比例,相關(guān)變量在/proc/sys/vm/dirty_background_ratio( 后臺運(yùn)行不阻塞 write)和/proc/sys/vm/dirty_ratio(阻塞 write)中定義。
- 內(nèi)存不足。
需要的日志方案
- 流暢性:流暢性不僅包括了系統(tǒng)沒有卡頓,還要盡量保證沒有 CPU 峰值
- 完整性:任何時(shí)刻都有日志可查。不能因?yàn)槌绦虮徊僮飨到y(tǒng)殺掉或者發(fā)生了未捕捉到的 Crash 就丟了部分日志
- 容錯(cuò)性:當(dāng)日志文件中的部分日志數(shù)據(jù)損壞時(shí)應(yīng)該盡量最小化對整個(gè)日志文件的影響
- 安全性:日志內(nèi)容需要進(jìn)行加密
xlog-V2.0 方案
使用流式壓縮方式對單行日志進(jìn)行壓縮,壓縮加密后寫進(jìn)作為 log 中間 buffer的 mmap 中,當(dāng) mmap 中的數(shù)據(jù)到達(dá)一定大小后再寫進(jìn)磁盤文件中
mmap
mmap 是使用邏輯內(nèi)存對磁盤文件進(jìn)行映射,中間只是進(jìn)行映射沒有任何拷貝操作,避免了寫文件的數(shù)據(jù)拷貝。 操作內(nèi)存就相當(dāng)于在操作文件,避免了內(nèi)核空間和用戶空間的頻繁切換。mmap幾乎和直接寫內(nèi)存一樣的性能。
mmap的回寫時(shí)機(jī):
- 內(nèi)存不足
- 進(jìn)程退出
- 調(diào)用 msync 或者 munmap
- 不設(shè)置 MAP_NOSYNC 情況下 30s-60s(僅限FreeBSD)
壓縮
流式壓縮是把時(shí)間分散在整個(gè)生命周期內(nèi),CPU 的曲線更平滑,相當(dāng)于把壓縮過程中使用的資源均分在整個(gè) app 生命周期內(nèi)。