Android高性能日志写入方案-mmap

2020-04-08  本文已影响0人  Jesse505

前言

最近在做一个新零售的收银app,对于app稳定性要求比较高,但是难免会出现一些难以复现的问题,针对这些问题,分析日志有时候是解决问题的必要手段。下面我们主要分析下日志写入方案的实现。详细代码可参考AwesomeLog,如果能够帮到你,希望给个star,感谢。

常规方案的缺陷

看到这里,难道真的就没有高性能又能保证日志完整性的方案了吗?答案是mmap。mmap是个什么鬼?我们接着往下看。

什么是mmap

mmap是一种内存映射文件的方法,即将一个文件或者其他对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对应关系;实现这样的映射关系后,进程就可以采用指针的方式读写操作这一块内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必调用read,write等系统调用函数,相反,内核空间堆这段区域的修改也直接反应到用户空间,从而可以实现不同进程间的文件共享。

网上很多文章都说 mmap 完全绕开了页缓存机制,其实这并不正确。我们最终映射的物理内存依然在页缓存中,它可以带来的好处有:

mmap.jpg

从上面的图看来,我们使用 mmap 仅仅只需要一次数据拷贝。

mmap使用场景

mmap 比较适合于对同一块区域频繁读写的情况,推荐也使用线程来操作。

具体实现

在Android中可以将文件通过Java提供的MappedByteBuffer映射到内存,然后进行读写。(微信的xlog模块mmap实现是基于C++代码实现)

MappedByteBuffer 位于 Java NIO 包下,用于将文件内容映射到缓冲区,使用的即是 mmap 技术。通过 FileChannel 的 map 方法可以创建缓冲区。

RandomAccessFile raf = new RandomAccessFile(file, "rw");
//position映射文件的起始位置,size映射文件的大小
MappedByteBuffer buffer = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, position, size);
//往缓冲区里写入字节数据
buffer.put(log);

有一点比较坑,Java 虽然提供了 map 方法,但是并没有提供 unmap 方法,通过 Google 得知 unmap 方法是有的,不过是私有的,我们可以通过反射调用获取unmap方法(Android 9.0以上对反射做了限制,可以参考这篇博文绕过限制)

    /**
     * 解除内存与文件的映射
     * */
    private void unmap(MappedByteBuffer mbbi) {
        if (mbbi == null) {
            return;
        }
        try {
            Class<?> clazz = Class.forName("sun.nio.ch.FileChannelImpl");
            Method m = clazz.getDeclaredMethod("unmap", MappedByteBuffer.class);
            m.setAccessible(true);
            m.invoke(null, mbbi);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

在这里记录一个点,刚开始在写入文件的时候,我是使用mmap将日志直接写入文件,这样的话需要通过代码去实现动态扩容,挺麻烦的,后来发现xlog是将日志写入高速缓冲区,这块高速缓冲区是使用mmap映射出来的内存区,被映射的磁盘文件是它新建的一个缓存文件,当高速缓冲区内容写到一定阈值时,通知后台线程将缓冲区的内容写入文件。借鉴xlog的方案,后面我们也改为先写入缓存中,当写满了之后,再flush到目标文件,也可以手动调用flush,将缓存刷新到目标文件

至于微信为什么这么做,肯定也是出于性能的原因啦,具体的可参考微信跨平台组件mars-xlog架构分析及迁移思路

总结

这篇文章主要讲了日志写入常规方案存在的一些缺陷以及原因,进而引出mmap的定义,优势和使用场景。最后主要讲了mmap的具体实现以及如何应用到日志写入当中。详细代码可参考AwesomeLog,如果能够帮到你,希望给个star,感谢

参考文档:《Android开发高手课》、微信xlog

上一篇下一篇

猜你喜欢

热点阅读