内存性能中 Buffer 和 Cache 的概念。简单复习一下,Buffer 和 Cache 的设计目的,是为了提升系统的 I/O 性能。它们利用内存,充当起慢速磁盘与快速 CPU 之间的桥梁,可以加速 I/O 的访问速度。

Buffer 和 Cache 分别缓存的是对磁盘和文件系统的读写数据。

  • 从写的角度来说,不仅可以优化磁盘和文件的写入,对应用程序也有好处,应用程序可以在数据真正落盘前,就返回去做其他工作。

  • 从读的角度来说,不仅可以提高那些频繁访问数据的读取速度,也降低了频繁 I/O 对磁盘的压力。

既然 Buffer 和 Cache 对系统性能有很大影响,那我们在软件开发的过程中,能不能利用这一点,来优化 I/O 性能,提升应用程序的运行效率呢?

答案自然是肯定的。今天,我就用几个案例帮助你更好地理解缓存的作用,并学习如何充分利用这些缓存来提高程序效率。

为了方便你理解,Buffer 和 Cache 我仍然用英文表示,避免跟“缓存”一词混淆。而文中的“缓存”,通指数据在内存中的临时存储。

缓存命中率

在案例开始前,你应该习惯性地先问自己一个问题,你想要做成某件事情,结果应该怎么评估?比如说,我们想利用缓存来提升程序的运行效率,应该怎么评估这个效果呢?换句话说,有没有哪个指标可以衡量缓存使用的好坏呢?

我估计你已经想到了,缓存的命中率。所谓缓存命中率,是指直接通过缓存获取数据的请求次数,占所有数据请求次数的百分比。

命中率越高,表示使用缓存带来的收益越高,应用程序的性能也就越好。

实际上,缓存是现在所有高并发系统必需的核心模块,主要作用就是把经常访问的数据(也就是热点数据),提前读入到内存中。这样,下次访问时就可以直接从内存读取数据,而不需要经过硬盘,从而加快应用程序的响应速度。

这些独立的缓存模块通常会提供查询接口,方便我们随时查看缓存的命中情况。不过 Linux 系统中并没有直接提供这些接口,所以这里我要介绍一下,cachestat 和 cachetop ,它们正是查看系统缓存命中情况的工具。

  • cachestat 提供了整个操作系统缓存的读写命中情况。

  • cachetop 提供了每个进程的缓存命中情况。

这两个工具都是bcc软件包的一部分,它们基于 Linux 内核的 eBPF(extended Berkeley Packet Filters)机制,来跟踪内核中管理的缓存,并输出缓存的使用和命中情况。

这里注意,eBPF 的工作原理不是我们今天的重点,记住这个名字即可,后面文章中我们会详细学习。今天要掌握的重点,是这两个工具的使用方法。

使用 cachestat 和 cachetop 前,我们首先要安装 bcc 软件包。比如,在 Ubuntu 系统中,你可以运行下面的命令来安装:

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4052245BD4284CDDecho "deb https://repo.iovisor.org/apt/xenial xenial main" | sudo tee /etc/apt/sources.list.d/iovisor.listsudo apt-get updatesudo apt-get install -y bcc-tools libbcc-examples linux-headers-$(uname -r)

操作完这些步骤,bcc 提供的所有工具就都安装到 /usr/share/bcc/tools 这个目录中了。不过这里提醒你,bcc 软件包默认不会把这些工具配置到系统的 PATH 路径中,所以你得自己手动配置:

export PATH=$PATH:/usr/share/bcc/tools

配置完,你就可以运行 cachestat 和 cachetop 命令了。比如,下面就是一个 cachestat 的运行界面,它以 1 秒的时间间隔,输出了 3 组缓存统计数据:

终端运行cachestat 发现报错如下所示:

wj@wj:~/WORK/M2_perfetto_tools$ cachestatIn file included from :317:In file included from :7:In file included from /virtual/include/bcc/bpf.h:12:In file included from include/linux/types.h:6:In file included from include/uapi/linux/types.h:14:In file included from ./include/uapi/linux/posix_types.h:5:In file included from include/linux/stddef.h:5:In file included from include/uapi/linux/stddef.h:5:In file included from include/linux/compiler_types.h:80:include/linux/compiler-clang.h:41:9: warning: '__HAVE_BUILTIN_BSWAP32__' macro redefined [-Wmacro-redefined]#define __HAVE_BUILTIN_BSWAP32__        ^:4:9: note: previous definition is here#define __HAVE_BUILTIN_BSWAP32__ 1        ^In file included from :317:In file included from :7:In file included from /virtual/include/bcc/bpf.h:12:In file included from include/linux/types.h:6:In file included from include/uapi/linux/types.h:14:In file included from ./include/uapi/linux/posix_types.h:5:In file included from include/linux/stddef.h:5:In file included from include/uapi/linux/stddef.h:5:In file included from include/linux/compiler_types.h:80:include/linux/compiler-clang.h:42:9: warning: '__HAVE_BUILTIN_BSWAP64__' macro redefined [-Wmacro-redefined]#define __HAVE_BUILTIN_BSWAP64__        ^:5:9: note: previous definition is here#define __HAVE_BUILTIN_BSWAP64__ 1        ^In file included from :317:In file included from :7:In file included from /virtual/include/bcc/bpf.h:12:In file included from include/linux/types.h:6:In file included from include/uapi/linux/types.h:14:In file included from ./include/uapi/linux/posix_types.h:5:In file included from include/linux/stddef.h:5:In file included from include/uapi/linux/stddef.h:5:In file included from include/linux/compiler_types.h:80:include/linux/compiler-clang.h:43:9: warning: '__HAVE_BUILTIN_BSWAP16__' macro redefined [-Wmacro-redefined]#define __HAVE_BUILTIN_BSWAP16__        ^:3:9: note: previous definition is here#define __HAVE_BUILTIN_BSWAP16__ 1        ^In file included from /virtual/main.c:2:In file included from include/uapi/linux/ptrace.h:153:In file included from ./arch/x86/include/asm/ptrace.h:5:./arch/x86/include/asm/segment.h:255:2: error: expected '(' after 'asm'        alternative_io ("lsl %[seg],%[p]",        ^./arch/x86/include/asm/alternative.h:248:2: note: expanded from macro 'alternative_io'        asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, feature)   \        ^include/linux/compiler_types.h:270:24: note: expanded from macro 'asm_inline'#define asm_inline asm __inline                       ^3 warnings and 1 error generated.Traceback (most recent call last):  File "/usr/share/bcc/tools/cachestat", line 96, in     b = BPF(text=bpf_text)  File "/usr/lib/python2.7/dist-packages/bcc/__init__.py", line 325, in __init__    raise Exception("Failed to compile BPF text")Exception: Failed to compile BPF text

发现BPF报错,怎么回事?

未完待续….