关联文章: 1_读缓存cache优化
1.问题与验证
问题现象
1.htop free命令发现系统 buffer/cache 内存占用高
free -h
total used free shared buff/cache available
Mem: 61Gi 15Gi 569Mi 1.7Gi 45Gi 43Gi
Swap: 30Gi 0.0Ki 30Gi
cat /proc/meminfo
orgrep -E "Buff|Cache" /proc/meminfo
Buffers: 370568 kB
Cached: 45599784 kB
SwapCached: 0 kB
猜想
写文件是否造成系统cache增加?
测试示例1: dd生成文件_确认是否增加系统缓存cache
5.1_dd_验证写文件_cache增加.sh gitee在线
#!/bin/bash
function show_cache_buffer_info()
{
free -m
grep -E 'Buffers|Cached' /proc/meminfo
}
sync; echo 3 > /proc/sys/vm/drop_caches
show_cache_buffer_info
dd if=/dev/zero of=test.img bs=1M count=512
show_cache_buffer_info
测试结果
./5.1_dd_验证写文件_cache增加.sh
total used free shared buff/cache available
Mem: 7901 1113 6445 7 343 6544
Swap: 2047 0 2047
Buffers: 2168 kB
Cached: 304968 k
SwapCached: 0 kB
512+0 records in
512+0 records out
536870912 bytes (537 MB, 512 MiB) copied, 0.5336 s, 1.0 GB/s
total used free shared buff/cache available
Mem: 7901 1120 5822 7 958 6529
Swap: 2047 0 2047
Buffers: 7668 kB
Cached: 916124 kB
SwapCached: 0 kB
测试结论:
写文件也会增加系统buffer/cache
2.解决方案
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED)
主动释放文件句柄, 系统缓存cache
说明:
POSIX_FADV_NORMAL: 没有特殊的建议;让内核根据其默认策略来决定。
POSIX_FADV_SEQUENTIAL: 预期对文件的访问将是顺序的。在这种情况下,内核可能会选择不缓存早期读取的数据,因为它假设这些数据不会再被访问。
POSIX_FADV_RANDOM: 预期对文件的访问将是随机的。这会提示内核尝试保持尽可能多的数据在缓存中。
POSIX_FADV_NOREUSE: 预期对文件中的信息的访问不会重复。内核可能会选择减少对这些数据的缓存。
POSIX_FADV_WILLNEED: 预期不久之后将会访问文件中的信息。内核可能会尽量提前将数据加载到缓存中。
POSIX_FADV_DONTNEED: 文件中的信息不再需要。内核可以丢弃任何与该区域相关的缓存数据。
参考文档:
示例
gitee在线代码5_写文件_是否会生成buffer_cache.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define KB_SIZE 1024
#define MB_SIZE (1024 * KB_SIZE)
#define GB_SIZE (1024 * MB_SIZE)
#define BUF_4K (4 * KB_SIZE)
void show_cache_buffer_info()
{
system("free -m");
system("grep -E 'Buffers|Cached' /proc/meminfo");
}
void help()
{
char* help_str = "\
默认 正常读文件 \n\
1 n NOREUSE \n\
2 d DONTNEED\n";
printf("%s", help_str);
}
int main(int argc, char* argv[])
{
// 0.清空系统 cache/buffer
system("sync; echo 3 > /proc/sys/vm/drop_caches");
show_cache_buffer_info();
// 1.创建文件
int fd = open("test.txt", O_WRONLY | O_CREAT, 0644);
if (fd < 0)
{
perror("open");
exit(1);
}
// 2.写文件
char buf[BUF_4K];
int count = MB_SIZE * 512;
while (count > 0)
{
write(fd, buf, BUF_4K);
count -= BUF_4K;
}
// 3.释放 缓存
fsync(fd); // fsync将写数据落盘,这样才能确保 page cache全部释放成功
if (argc == 2)
{
char opt = *argv[1];
if (opt == '1' || opt == 'n')
posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE);
if (opt == '2' || opt == 'd')
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
}
// 4.关闭文件
close(fd);
show_cache_buffer_info();
}
测试1: ./5_写文件_是否会生成buffer_cache.out
total used free shared buff/cache available
Mem: 7901 1056 6419 7 425 6600
Swap: 2047 0 2047
Buffers: 8708 kB
Cached: 381292 kB
SwapCached: 0 kB
total used free shared buff/cache available
Mem: 7901 1054 5897 7 950 6596
Swap: 2047 0 2047
Buffers: 8720 kB
Cached: 905556 kB
SwapCached: 0 kB
测试2: ./5_写文件_是否会生成buffer_cache.out 2
total used free shared buff/cache available
Mem: 7901 1066 6499 7 336 6590
Swap: 2047 0 2047
Buffers: 2524 kB
Cached: 297488 kB
SwapCached: 0 kB
total used free shared buff/cache available
Mem: 7901 1067 6496 7 337 6589
Swap: 2047 0 2047
Buffers: 3300 kB
Cached: 297800 kB
SwapCached: 0 kB
小结
- 系统调用
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
可以主动释放写文件的缓存
3.个人总结
目前做的产品是智能机器, 和自动驾驶产品, 需要采集与记录大量的数据,日志
posix_fadvise
主动释放缓存cache, 主要应用场景
- 对于ros2 bag record命令记录的话题数据, 修改ros源代码, 在close关闭文件句柄前, 调用posix_fadvise主动释放cache
- 同理 对于程序中记录日志/数据, 如果只是记录, 不查看, 不上传, 调用posix_fadvise也能释放更多的内存空间
- 对于开发debug阶段, 需要频繁查看日志, 可能反而会降低性能(需要重新读取文件数据, 加载到内存缓存中)