Linux磁盘缓存实验
原文地址
https://www.linuxatemyram.com/play.html
希望你现在不再认为Linux
吞掉了你的内存。您可以执行以下一些有趣的操作来了解磁盘缓存的工作方式。
注意:所示示例适用于2009年及之后的不带SSD的硬件。 您可能需要将此处的几个示例数字乘以10才能看到明显的效果。
磁盘缓存对应用程序内存分配的影响
既然我已经声明了 磁盘缓存并不影响应用程序获取内存。那我们就从这里开始。这是一个C代码munch.c
尽可能地吞噬内存,直到程序异常退出,或者达到指定的限制
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
int max = -1;
int mb = 0;
char* buffer;
if(argc > 1)
max = atoi(argv[1]);
while((buffer=malloc(1024*1024)) != NULL && mb != max) {
memset(buffer, 0, 1024*1024);
mb++;
printf("Allocated %d MB\n", mb);
}
return 0;
}
内存不足并不是一件有趣的事,但是OOM杀手应该结束这个过程,希望其余的一切都不会受到干扰。 我们必须要禁用交换功能,否则应用程序也会吞噬掉交换内存。
sudo swapoff -a
free -m
你的free输出可能不一样,拥有一列available,而不是**-/+**这一行
total used free shared buffers cached
Mem: 1504 1490 14 0 24 809
-/+ buffers/cache: 656 848
Swap: 0 0 0
$ gcc munch.c -o munch
$ ./munch
Allocated 1 MB
Allocated 2 MB
(...)
Allocated 877 MB
Allocated 878 MB
Allocated 879 MB
Killed
$ free -m
total used free shared buffers cached
Mem: 1504 650 854 0 1 67
-/+ buffers/cache: 581 923
Swap: 0 0 0
尽管free显示只有14MB可用,但这也没有阻挡应用程序吞噬了879MB内存。然后,cache已经快空了,但是随着文件的读取,写入,它会逐渐填满。试试看。
磁盘缓存对交换的影响
我也说了磁盘缓存并不会导致应用程序使用交换内存。让我们也来试试,还是使用上次的程序。这次我们开着交换内存来使用它,然后限制它只是用数百兆内存
$ free -m
total used free shared buffers cached
Mem: 1504 1490 14 0 10 874
-/+ buffers/cache: 605 899
Swap: 2047 6 2041
$ ./munch 400
Allocated 1 MB
Allocated 2 MB
(...)
Allocated 399 MB
Allocated 400 MB
$ free -m
total used free shared buffers cached
Mem: 1504 1090 414 0 5 485
-/+ buffers/cache: 598 906
Swap: 2047 6 2041
它使用了400MB内存,都是从磁盘缓存中获取,没有发起交换。同样地,我们可以再次填充磁盘缓存,并且也不会开始占用交换空间。 如果您在一个终端中运行watch free -m
并且在另一个终端运行find -f -exec cat {} +> / dev / null
。您可以看到cached
增加,而free
将减少。 过了一会儿,free 越来越少,但是交换一直没有触发。
清理磁盘缓存
为了进行实验,能够删除磁盘缓存非常方便。 为此,我们可以使用特殊文件/proc/sys/vm/drop_caches
。 通过向其写入3,我们可以清除大部分磁盘缓存:
$ free -m
total used free shared buffers cached
Mem: 1504 1471 33 0 36 801
-/+ buffers/cache: 633 871
Swap: 2047 6 2041
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
3
$ free -m
total used free shared buffers cached
Mem: 1504 763 741 0 0 134
-/+ buffers/cache: 629 875
Swap: 2047 6 2041
注意“ buffers”和“ cached”下降,free mem上升,而free + buffers / cache保持不变。
磁盘缓存在加载时候的作用
让我们制作两个测试程序,一个用Python,一个用Java。 Python和Java都具有相当大的运行时,必须加载这些运行时才能运行该应用程序。 这是磁盘缓存发挥其魔力的完美场景
$ cat hello.py
print "Hello World! Love, Python"
$ cat Hello.java
class Hello {
public static void main(String[] args) throws Exception {
System.out.println("Hello World! Regards, Java");
}
}
$ javac Hello.java
$ python hello.py
Hello World! Love, Python
$ java Hello
Hello World! Regards, Java
我们的程序运行起来了。现在我们把磁盘缓存清理,查看需要多长时间运行它们
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
3
$ time python hello.py
Hello World! Love, Python
real 0m1.026s
user 0m0.020s
sys 0m0.020s
$ time java Hello
Hello World! Regards, Java
real 0m2.174s
user 0m0.100s
sys 0m0.056s
$
哇。 对于Python是1秒,对于Java是2秒? 只是打个招呼。 但是,现在运行它们所需的所有文件都将位于磁盘高速缓存中,因此可以直接从内存中获取它们。 让我们再试一次:
$ time python hello.py
Hello World! Love, Python
real 0m0.022s
user 0m0.016s
sys 0m0.008s
$ time java Hello
Hello World! Regards, Java
real 0m0.139s
user 0m0.060s
sys 0m0.028s
$
耶! Python现在仅需22毫秒即可运行,而Java使用139ms。 快了45到15倍! 您所有的应用程序都会自动获得提升!
磁盘缓存在文件读取时候的作用
让我们做一个大文件,看看磁盘缓存如何影响我们读取它的速度。 我正在制作200MB的文件,但是如果您的可用RAM较少,则可以对其进行调整。
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
3
$ free -m
total used free shared buffers cached
Mem: 1504 546 958 0 0 85
-/+ buffers/cache: 461 1043
Swap: 2047 6 2041
$ dd if=/dev/zero of=bigfile bs=1M count=200
200+0 records in
200+0 records out
209715200 bytes (210 MB) copied, 6.66191 s, 31.5 MB/s
$ ls -lh bigfile
-rw-r--r-- 1 vidar vidar 200M 2009-04-25 12:30 bigfile
$ free -m
total used free shared buffers cached
Mem: 1504 753 750 0 0 285
-/+ buffers/cache: 468 1036
Swap: 2047 6 2041
由于文件刚刚被写入,因此它将进入磁盘缓存。 200MB的文件在“缓存”中引起了200MB的增加。 让我们read
它,清除缓存,然后再次read
以查看它有多快:
$ time cat bigfile > /dev/null
real 0m0.139s
user 0m0.008s
sys 0m0.128s
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
3
$ time cat bigfile > /dev/null
real 0m8.688s
user 0m0.020s
sys 0m0.336s
$
这次提速了超过50倍
总结
Linux磁盘缓存非常简单。他使用备用内存大大提高磁盘访问速度,而不会占用应用程序的内存。在Linux上完全使用的ram存储是有效的硬件使用,而不是警告信号。
注
缓存的某些部分无法删除,甚至无法容纳新的应用程序。这包括已被某些应用程序锁定的mmap页面,尚未写入存储器的脏页面以及存储在tmpfs中的数据(包括用于共享内存的/ dev / shm)。 mmap锁定的页面被卡在页面缓存中。大部分情况下,脏页都会被迅速写出。如果可能,tmpfs中的数据将被换出。
- 点赞
- 收藏
- 关注作者
评论(0)