Linux磁盘缓存实验

举报
张俭 发表于 2023/12/29 17:42:13 2023/12/29
【摘要】 原文地址https://www.linuxatemyram.com/play.html希望你现在不再认为Linux吞掉了你的内存。您可以执行以下一些有趣的操作来了解磁盘缓存的工作方式。注意:所示示例适用于2009年及之后的不带SSD的硬件。 您可能需要将此处的几个示例数字乘以10才能看到明显的效果。 磁盘缓存对应用程序内存分配的影响既然我已经声明了 磁盘缓存并不影响应用程序获取内存。那我们...

原文地址

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中的数据将被换出。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。