已复制
全屏展示
复制代码

linux 页缓存实践总结


· 3 min read

一. 什么是页缓存

在Linux中,页缓存(Page Cache)是内核对磁盘上文件数据的缓存机制。当程序需要读取文件数据时,内核会将文件数据读取到页缓存中,而不是直接从磁盘读取。这样当同一个文件数据被多次访问时,就可以从内存中快速获取,而不必每次都进行磁盘访问,从而提高了文件的读取性能。

Linux的页缓存是建立在虚拟内存系统之上的,通过将磁盘上的数据映射到内核虚拟地址空间的页面中,实现了文件数据的缓存。页面大小通常是4KB,这也是Linux中的最小内存单位。

二. 查看页缓存

使用 free 命令可以查看当前的内存使用情况,其中的 buf/cache 项就表示了页缓存。

# free -m
              total        used        free      shared  buff/cache   available
Mem:            985         670          76           6         238         171
Swap:             0           0           0

除了 free 命令,也可以用第三方的工具 hcache 查看,git地址: https://github.com/silenceshell/hcache

# ./hcache -top 10 -bname
+------------------------+----------------+------------+-----------+---------+
| Name                   | Size (bytes)   | Pages      | Cached    | Percent |
|------------------------+----------------+------------+-----------+---------|
| gitea                  | 107443064      | 26232      | 4732      | 018.039 |
| leanote_xxxxxxxxxxx.ns | 16777216       | 4096       | 4096      | 100.000 |
| leanote_yyyyyyyyyy.ns  | 16777216       | 4096       | 4096      | 100.000 |
| local.ns               | 16777216       | 4096       | 4096      | 100.000 |
| admin.ns               | 16777216       | 4096       | 4096      | 100.000 |
| system.journal         | 25165824       | 6144       | 2313      | 037.646 |
| leanote-linux-amd64    | 18633425       | 4550       | 1962      | 043.121 |
| leanote-linux-amd64    | 18633425       | 4550       | 1928      | 042.374 |
| aliyun-service         | 14175859       | 3461       | 1704      | 049.234 |
| mongod                 | 22310536       | 5447       | 1339      | 024.582 |
+------------------------+----------------+------------+-----------+---------+

三. 使用Python处理页缓存

  • 虚拟空间:请放弃虚拟内存这个概念,那个是广告性的概念,在开发中没有意义。开发中只有虚拟空间的概念,进程看到的所有地址组成的空间,就是虚拟空间。虚拟空间是某个进程对分配给它的所有物理地址(已经分配的和将会分配的)的重新映射。
  • mmap原理:在应用这一层,把文件的某一段,当作内存一样来访问。当发起mmap调用的时候,它只是在你的虚拟空间中分配了一段空间,连真实的物理地址都不会分配的,当你访问这段空间时会在这个时间分配物理内存,并用文件的内容填充这片内存,然后才返回你进程的上下文,这时你的程序才会感知到这片内存里有数据。驱动每次读入多少页面,页面的分配算法等等这些不是由mmap来决定的。

下面的代码,表示首先写一个文件,然后用 mmap 去与这个文件做一个映射。

import time
import mmap

with open("/tmp/test", "w") as f:
    f.write("hello\n"*20000000)

f = open("/tmp/test")
m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
m.read()

time.sleep(300)

# 运行这个程序:python3 page_cache.py

然后使用 hcache 命令来查看缓存的情况

# ./hcache -top 100 | grep -E "test|---| Name "
+------------------+----------------+------------+-----------+---------+
| Name             | Size (bytes)   | Pages      | Cached    | Percent |
|------------------+----------------+------------+-----------+---------|
| /tmp/test        | 120000000      | 29297      | 18209     | 062.153 |
+------------------+----------------+------------+-----------+---------+

或者找到这个进程的 pid

# ll /proc/3571/map_files/
total 0
lr-------- 1 root root 64 Apr 16 11:54 400000-7b4000 -> /usr/bin/python3.6
lr-------- 1 root root 64 Apr 16 11:54 7ff254e32000-7ff25c0a3000 -> /tmp/test
lr-------- 1 root root 64 Apr 16 11:54 7ff25c607000-7ff25c7a4000 -> /lib/x86_64-linux-gnu/libm-2.27.so
lr-------- 1 root root 64 Apr 16 11:54 7ff25c7a4000-7ff25c9a3000 -> /lib/x86_64-linux-gnu/libm-2.27.so
lr-------- 1 root root 64 Apr 16 11:54 7ff25c9a3000-7ff25c9a4000 -> /lib/x86_64-linux-gnu/libm-2.27.so
lr-------- 1 root root 64 Apr 16 11:54 7ff25c9a4000-7ff25c9a5000 -> /lib/x86_64-linux-gnu/libm-2.27.so
......

参考资料

🔗

文章推荐