百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

为什么手工drop_caches之后cache值并未减少?

toyiye 2024-07-26 22:01 7 浏览 0 评论

在Linux系统上查看内存使用状况最常用的命令是"free",其中buffers和cache通常被认为是可以回收的:

$ free total used free shared buffers cachedMem: 32764716 1067548 31697168 158332 12 593096-/+ buffers/cache: 474440 32290276Swap: 2103292 0 2103292

当内存紧张的时候,有一个常用的手段就是使用下面的命令来手工回收cache:

$ echo 1 > /proc/sys/vm/drop_caches

注:drop_caches接受以下三种值:

  • To free pagecache:
echo 1 > /proc/sys/vm/drop_caches
  • To free reclaimable slab objects (includes dentries and inodes):
echo 2 > /proc/sys/vm/drop_caches
  • To free slab objects and pagecache:
echo 3 > /proc/sys/vm/drop_caches

当我们考虑有多少cache可供回收的时候,首先要知道的是:不同版本的"free"命令计算cache值的算法不同,据不完全统计举例如下:

  1. 版本:procps-3.2.8-36
  2. cache值等于/proc/meminfo中的"Cached";
  3. 版本:procps-3.3.9-10.1
  4. cache值等于/proc/meminfo的 [Cached + SReclaimable];
  5. 版本:procps-ng-3.3.10-3
  6. cache值等于/proc/meminfo的 [Cached + Slab]。

注:

/proc/meminfo中的"Cached"表示page cache所占用的内存大小;

"Slab"表示内核Slab所占用的内存大小,slab有的可回收有的不可回收,其中可回收的通过"SReclaimable"表示,不可回收的通过"SUnreclaim"表示。

所以,对上述第2、3版本的"free"命令,"echo 1 > /proc/sys/vm/drop_caches"对其中的SReclaimable或Slab部分是不起作用的。

即便仅考虑page cache (对应于 /proc/meminfo 的"Cached"),也并不是所有的页面都可以回收的:

首先,drop_caches只回收clean pages,不回收dirty pages,参见

https://www.kernel.org/doc/Documentation/sysctl/vm.txt

所以如果想回收更多的cache,应该在drop_caches之前先执行"sync"命令,把dirty pages变成clean pages。

其次,即使提前执行了sync命令,drop_cache操作也不可能把cache值降到0,甚至有时候cache值几乎没有下降,这是为什么呢?因为page cache中包含的tmpfs和共享内存是不能通过drop_caches回收的。

Page cache用于缓存文件里的数据,不仅包括普通的磁盘文件,还包括了tmpfs文件,tmpfs文件系统是将一部分内存空间模拟成文件系统,由于背后并没有对应着磁盘,无法进行paging(换页),只能进行swapping(交换),在执行drop_cache操作的时候tmpfs对应的page cache并不会回收。

我们通过实验来观察tmpfs文件对free命令的影响:

挂载一个3G大小的tmpfs:
$ mount -t tmpfs -o size=3G none /mytmpfs/
此时free命令看到的内存使用状况:
$ free
 total used free shared buffers cached
Mem: 65942736 2343336 63599400 9492 8952 92848
-/+ buffers/cache: 2241536 63701200 
Swap: 33038332 0 33038332 
在tmpfs上新建一个2G大小的文件,free命令看到"cached"增加了2GB,注意"shared"也增加了2GB:
$ dd if=/dev/zero of=/mytmpfs/testfile bs=1G count=2
2+0 records in
2+0 records out
2147483648 bytes (2.1 GB) copied, 2.42736 s, 885 MB/s
$ free
 total used free shared buffers cached
Mem: 65942736 4423404 61519332 2106644 9088 2190064
-/+ buffers/cache: 2224252 63718484 
Swap: 33038332 0 33038332 
执行drop_caches,再观察free命令的"cached"值,发现刚才增加的2GB并未被回收:
$ sync
$ sudo sh -c 'echo 1 > /proc/sys/vm/drop_caches'
$ free
 total used free shared buffers cached
Mem: 65942736 4430388 61512348 2106644 5284 2183096
-/+ buffers/cache: 2242008 63700728 
Swap: 33038332 0 33038332 
最后删除tmpfs上的文件,free命令看到"Cached"和"Shared"同时减少2GB:
$ rm /mytmpfs/testfile
$ free
 total used free shared buffers cached
Mem: 65942736 2324096 63618640 9784 6228 87412
-/+ buffers/cache: 2230456 63712280 
Swap: 33038332 0 33038332 

结论:

tmpfs占用的page cache是不能通过drop_caches操作回收的,tmpfs占用的page cache同时也算进了"shared"中,也就是说,被视为共享内存。

inux kernel利用tmpfs实现共享内存(shared memory),参见:

https://www.kernel.org/doc/Documentation/filesystems/tmpfs.txt

所以共享内存也和tmpfs一样,属于page cache,但又不能被drop_caches回收。这里所说的共享内存包括:

  • SysV shared memory
  • 是通过shmget申请的共享内存,用"ipcs -m"或"cat /proc/sysvipc/shm"查看;
  • POSIX shared memory
  • 是通过shm_open申请的共享内存,用"ls /dev/shm"查看;
  • shared anonymous mmap
  • 通过mmap(…MAP_ANONYMOUS|MAP_SHARED…)申请的内存,可以用"pmap -x"或者"cat /proc/<PID>/maps"查看;
  • 注:mmap调用参数如果不是MAP_ANONYMOUS|MAP_SHARED,则不属于tmpfs,比如MAP_ANONYMOUS|MAP_PRIVATE根本不属于page cache而是属于AnonPages,MAP_SHARED属于普通文件,对应的page cache可以回写硬盘并回收。


我们通过一个实验来观察共享内存对free命令的影响。以下程序通过shared anonymous mmap方式申请256MB大小的内存:

#include <sys/mman.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#define MAP_SIZE 268435456int main(){ char *addr; ssize_t s; addr = mmap(NULL, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0); if (addr == MAP_FAILED) { fprintf(stderr, "mmap failed\n"); exit(EXIT_FAILURE); } memset(addr, 9, MAP_SIZE); printf("mmap done, memset done, check free output. Press any key to exit...\n"); getchar(); exit(EXIT_SUCCESS);}


实验过程如下:

先回收cache,设置初始状态:$ sync; sudo sh -c 'echo 1 > /proc/sys/vm/drop_caches'; free total used free shared buffers cachedMem: 65942736 2401684 63541052 9576 3648 54820-/+ buffers/cache: 2343216 63599520 Swap: 33038332 0 33038332 然后执行我们的测试程序,申请256MB共享内存:$ ./mmap_testmmap done, memset done, check free output. Press any key to exit...在另一个窗口里观察,看到cache值增加了256MB,注意"shared"也同时增加了256MB:$ free total used free shared buffers cachedMem: 65942736 2652796 63289940 271720 6380 321760-/+ buffers/cache: 2324656 63618080 Swap: 33038332 0 33038332 执行drop_caches,发现刚才新增的256MBcache值并未被回收:$ sync; sudo sh -c 'echo 1 > /proc/sys/vm/drop_caches'; free total used free shared buffers cachedMem: 65942736 2666452 63276284 271720 3628 316532-/+ buffers/cache: 2346292 63596444 Swap: 33038332 0 33038332 退出mmap_test程序,再看cache值就减少了256MB,注意"shared"也同时减少256MB:$ free total used free shared buffers cachedMem: 65942736 2400268 63542468 9576 4796 59148-/+ buffers/cache: 2336324 63606412 Swap: 33038332 0 33038332

结论:cache值包含了共享内存的大小,然而drop_caches是不能回收它的。

总结:为什么drop_caches操作不能回收所有的page cache?

  • dirty pages不能回收;
  • 共享内存和tmpfs不能回收(注意观察free命令显示的shared值);
  • 不同版本的free命令有不同的计算cache值的方法,有的包含了slab或SReclaimable,"echo 1 > /proc/sys/vm/drop_caches"是不能回收slab的,"echo 3 > /proc/sys/vm/drop_caches"也只是回收slab中的SReclaimable部分。

相关推荐

「编程」Java GUI 基础(java编程语言基础)

图形化学习是外功,内功外功配合才能所向披靡。一、JFrameJAVASWING导入包importjavax.swing.*导入包importjava.awt.*JFrameframe=new...

这六个Java技术当年是多么风光,而现在又有几个人用过

嗨,雷猴啊,今天我给大家分享下我的开发历程中,我知道的那些被淘汰的技术或者框架。不知道你们都知道吗?也不知道你们都有没有用过,但是它们之前都是风靡一时,让我们再来了解一次吧。偷偷告诉大家有些我甚至都没...

开发第一个Swing程序(开发第一个java程序实验报告)

packagecom.web.www;importjavax.swing.*;/**第一个Swing程序*/publicclassSwing1extendsJFrame{publicSw...

Java课程设计项目实例《远程屏幕分享监视》第2部分

Java课程设计项目实例《远程屏幕分享监视》第2部分1、服务器端ScreenMonitoringServer程序类及相关的功能方法的编程实现(1)创建出服务器端的ScreenMonitoringSer...

新手学Java编程语言怎么入门?知识点都帮你整理好了

新手学Java编程语言怎么入门?下面和千锋广州小编一起来看看吧!掌握语言基础是第一步,了解Java基础知识,Java关键字、核心概念或者基本编码技术。掌握操作符、控制执行流程、访问权限控制、复用类、多...

Java Swing组件“HelloWorld”程序演示实例

Java源代码:/*首先导入Swing需要的包*/importjavax.swing.*;importjavax.swing.UIManager;importjava.awt.*;import...

新年Java小游戏之「年兽大作战」祝您笑口常开

这个游戏加上编写文章,上班摸鱼时间加上回家的空闲时间,大概花了三天多。java写这玩应真的很痛苦,各种状态位,各种图片和逻辑判断,脑袋都快炸了。而且肯定没有前端的精致,效果一般,偶尔会有卡顿,各位就图...

10分钟掌握 JMeter接口测试的基础入门

嘿。大家好,我是4U:...

JMeter 的简单安装说明(jmeter安装配置)

最近在做一组性能测试,接触到了JMeter这个测试工具,在这里记录一下JMeter的介绍以及简单安装过程。JMeter简介...

Jmeter压测实例分享——新手儿也能一学就会!

JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。它可以用于测试静态和动态资源,例如静态文件、Java...

过年必备Java动态烟花教程如何用Canvas和Timer实现炫酷烟花动画

烟花是一种常见的庆祝活动和节日的方式,它们在夜空中绽放出各种颜色和形状,给人们带来美丽和欢乐。你是否想过用Java编程来模拟烟花的效果呢?如果你对此感兴趣,那么这篇教程就是为你准备的。在这篇教程中,你...

全程软件测试(九十五):Jmeter技能基础—读书笔记

jmeter是一款优秀的开源性能测试工具,目前最新版本3.0版本,官网文档地址:http://jmeter.apache.org/usermanual/index.html一、优点...

原创 JAVA Swing JFrame窗口的建立

importjava.awt.*;importjavax.swing.*;publicclassExample1extendsJFrame{//定义一个类继承JFrame类public...

Java Swing组件下的JComboBox组件实例

运行成功的界面:java源代码:一定要注意:执行环境(JRE)javaSE-1.8/*首先导入JButtontest所需要的包*/importjavax.swing.*;importjavax.s...

Java引包的几种方法(java 引用)

第一种方法可以在Superclass这里输入javax.swing.JFrame进行引包也可以在类体外面输入importjavax.swing.JFrame;进行引包还可以点击JFrame然后点击I...

取消回复欢迎 发表评论:

请填写验证码