麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 系統(tǒng) > Android > 正文

Android高性能日志寫入方案的實(shí)現(xiàn)

2019-10-21 21:30:26
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

前言

公司目前在做一款企業(yè)級(jí)智能客服系統(tǒng),對(duì)于系統(tǒng)穩(wěn)定性要求很高,不過(guò)難保用戶在使用中不會(huì)出現(xiàn)問(wèn)題,而 Android SDK 集成在客戶的 APP 中,同時(shí)由于 Android 碎片化的問(wèn)題,對(duì)于 SDK 的問(wèn)題排查就顯得尤為困難,因此記錄下用戶的操作日志就顯得極為重要。

初始方案

一開(kāi)始,SDK 記錄日志的方式是直接通過(guò)寫文件,當(dāng)有一條日志要寫入的時(shí)候,首先,打開(kāi)文件,然后寫入日志,最后關(guān)閉文件。這樣做的問(wèn)題就在于頻繁的IO操作,影響程序的性能,而且 SDK 為了保證消息的及時(shí)性,還維護(hù)了一個(gè)后臺(tái)進(jìn)程,當(dāng)其中一個(gè)進(jìn)程進(jìn)行日志寫入時(shí),另一個(gè)就會(huì)被鎖在門外等著,問(wèn)題就愈發(fā)嚴(yán)重。使用這種方案雖然當(dāng)前看上去對(duì)程序的影響不大,但是隨著日志量的增加,更多的IO操作,一定會(huì)造成性能瓶頸。

下面我們來(lái)分析下直接寫入文件的流程:

  • 用戶發(fā)起 write 操作
  • 操作系統(tǒng)查找頁(yè)緩存
    a.若未命中,則產(chǎn)生缺頁(yè)異常,然后創(chuàng)建頁(yè)緩存,將用戶傳入的內(nèi)容寫入頁(yè)緩存
    b.若命中,則直接將用戶傳入的內(nèi)容寫入頁(yè)緩存
  • 用戶 write 調(diào)用完成
  • 頁(yè)被修改后成為臟頁(yè),操作系統(tǒng)有兩種機(jī)制將臟頁(yè)寫回磁盤
    a.用戶手動(dòng)調(diào)用 fsync()
    b.由 pdflush 進(jìn)程定時(shí)將臟頁(yè)寫回磁盤

可以看出,數(shù)據(jù)從程序?qū)懭氲酱疟P的過(guò)程中,其實(shí)牽涉到兩次數(shù)據(jù)拷貝:一次是用戶空間內(nèi)存拷貝到內(nèi)核空間的緩存,一次是回寫時(shí)內(nèi)核空間的緩存到硬盤的拷貝。當(dāng)發(fā)生回寫時(shí)也涉及到了內(nèi)核空間和用戶空間頻繁切換。

而且相對(duì)于機(jī)械硬盤,SSD 存儲(chǔ)還有一個(gè)“寫入放大”的問(wèn)題。這個(gè)問(wèn)題主要和 SSD 存儲(chǔ)的物理結(jié)構(gòu)有關(guān)。當(dāng) SSD 被全部寫過(guò)一遍之后,再寫入的數(shù)據(jù)是不可以直接更新,只可以通過(guò)覆蓋重寫,在覆蓋之前需要先擦除數(shù)據(jù)。但寫入的最小單位是 Page,擦除的最小單位是 Block,而 Block 遠(yuǎn)大于 Page,所以在寫入新數(shù)據(jù)時(shí)就需要先把 Block 上的數(shù)據(jù)讀出來(lái)和要寫入的數(shù)據(jù)合并在一起,再把 Block 擦除,最后把讀出來(lái)的數(shù)據(jù)重新寫入到存儲(chǔ)上,這樣導(dǎo)致實(shí)際寫入的數(shù)據(jù)可能遠(yuǎn)遠(yuǎn)大于最開(kāi)始需要寫入的數(shù)據(jù)。

沒(méi)想到簡(jiǎn)單的寫文件竟然涉及了這么多操作,只是對(duì)于應(yīng)用層透明而已。

既然每寫一次文件會(huì)執(zhí)行這么多次操作,那么我們能不能將日志緩存起來(lái),當(dāng)達(dá)到一定的數(shù)量后再一次性的寫入磁盤中呢?
這樣確實(shí)能夠大量減少 IO 次數(shù),但是卻會(huì)引發(fā)另一個(gè)更嚴(yán)重的問(wèn)題——丟日志

把日志緩存在內(nèi)存中,當(dāng)程序發(fā)生 Crash 或進(jìn)程被殺后就無(wú)法保證日志的完整性,而且由于 SDK 存在多進(jìn)程,也無(wú)法保證多進(jìn)程下日志的順序。

一個(gè)完善的日志方案,需要滿足

  • 高效,不能影響系統(tǒng)性能,不能因?yàn)橐肓巳罩灸K而造成應(yīng)用卡頓
  • 保證日志的完整性,如果不能保證日志完整,那么日志收集就沒(méi)有意義了
  • 對(duì)于多進(jìn)程應(yīng)用,要保證最終看到的日志順序的準(zhǔn)確性

高性能方案

既然無(wú)法減少寫入次數(shù),那么我們能不能在寫文件的過(guò)程中去優(yōu)化呢?

答案是可以的,使用 mmap

mmap是一種內(nèi)存映射文件的方法,即將一個(gè)文件或者其它對(duì)象映射到進(jìn)程的地址空間,實(shí)現(xiàn)文件磁盤地址和進(jìn)程虛擬地址空間中一段虛擬地址的一一對(duì)映關(guān)系,函數(shù)原型如下

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

 

mAndroid,高性能,日志寫入map操作提供了一種機(jī)制,讓用戶程序直接訪問(wèn)設(shè)備內(nèi)存,這種機(jī)制,相比較在用戶空間和內(nèi)核空間互相拷貝數(shù)據(jù),效率更高。在要求高性能的應(yīng)用中比較常用。

時(shí) mmap 能夠保證日志的完整性,mmap 的回寫時(shí)機(jī):

  • 內(nèi)存不足
  • 進(jìn)程退出
  • 調(diào)用 msync 或者 munmap
  • 不設(shè)置 MAP_NOSYNC 情況下 30s-60s(僅限FreeBSD)

當(dāng)映射一個(gè)文件后,程序就會(huì)在 native 內(nèi)存中申請(qǐng)一塊相同大小的空間,因此建議每次映射一小段內(nèi)容,如 64k,寫滿后再重新映射文件后面的內(nèi)容。

日志寫入性能和完整性的問(wèn)題解決了,那么如何保證多進(jìn)程下日志的順序呢?

由于 mmap 是采用共享內(nèi)存的方式寫入數(shù)據(jù),如果兩個(gè)進(jìn)程同時(shí)映射一個(gè)文件,那么一定會(huì)造成日志覆蓋的問(wèn)題。

既然不能直接保證順序,那我們只能退而求其次,兩個(gè)進(jìn)程分別映射不同的文件,每天合并一次,合并時(shí)對(duì)日志進(jìn)行排序。

繼續(xù)優(yōu)化

根據(jù)上述方案,設(shè)計(jì) jni 接口,打包 so,引入 SDK,看似沒(méi)什么問(wèn)題了,但是作為一款 SDK,總覺(jué)得包含 so 不太友好,在一定程度上會(huì)增加接入的難度。

那么能不能不用 so 呢?

其實(shí) Java 中已經(jīng)提供了內(nèi)存映射的實(shí)現(xiàn)——MappedByteBuffer

MappedByteBuffer 位于 Java NIO 包下,用于將文件內(nèi)容映射到緩沖區(qū),使用的即是 mmap 技術(shù)。通過(guò) FileChannel 的 map 方法可以創(chuàng)建緩沖區(qū)

RandomAccessFileraf = new RandomAccessFile(file, "rw");MappedByteBuffer buffer = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, position, size);

為了測(cè)試 MappedByteBuffer 的效率,我們把 64byte 的數(shù)據(jù)分別寫入內(nèi)存、MappedByteBuffer 和磁盤文件 50 萬(wàn)次,并統(tǒng)計(jì)耗時(shí)

 

方法 耗時(shí)
內(nèi)存 384ms
MappedByteBuffer 700ms
磁盤文件 16805ms

 

可以看出 MappedByteBuffer 雖然不及寫入內(nèi)存的性能,但是相比較寫入磁盤文件,已經(jīng)有了質(zhì)的提升。

總結(jié)

本文主要分析了直接寫文件記錄日志方式存在的問(wèn)題,并引申出高性能文件寫入方案 mmap,兼顧了寫入性能和完整性,并通過(guò)補(bǔ)償方案確保多進(jìn)程下日志的順序。最后發(fā)現(xiàn)了內(nèi)存映射在 Java 層的實(shí)現(xiàn),避免了引入 so。

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到Android開(kāi)發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 九九视频精品在线观看 | 国产品久久 | 成人毛片网站 | 国产免费中文字幕 | a一级黄 | 久久久久av电影 | 欧美日韩一区,二区,三区,久久精品 | 99在线啪| 久久久精品视频在线观看 | 成人国产精品免费 | 香蕉久久久精品 | 欧美成人午夜一区二区三区 | 免费男女视频 | 久久精品一二三区白丝高潮 | 精品中文视频 | 久久国产一级片 | 视频毛片 | 欧美精品久久久久久久久久 | 欧美精品成人一区二区三区四区 | 性爱视频在线免费 | 黄污网站在线观看 | 国产一区成人 | 欧美一级鲁丝片免费看 | 精品国产观看 | 九九精品在线观看视频 | 天天撸日日夜夜 | 国产午夜免费不卡精品理论片 | 一区国产在线观看 | 亚洲欧美天堂 | 亚洲一区二区免费视频 | 午夜久久久精品一区二区三区 | 最新欧美精品一区二区三区 | 国产亚洲精品久久久久久久久 | 国产91久久精品 | 欧美成人免费电影 | 国产免费小视频在线观看 | 久久成人精品视频 | 久久久www成人免费精品 | 国内精品久久久久久影视8 嫩草影院在线观看网站成人 | 黄色片免费在线播放 | 欧美成人精品h版在线观看 久久久久久三区 |