buffer/cache内存优化_posix_fadvise_主动释放读缓存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 or grep -E "Buff|Cache" /proc/meminfo

Buffers: 370568 kB

Cached: 45599784 kB

SwapCached: 0 kB

2.问题原因

原理

  • cache 读数据保存到内存,加速下次读速度
  • buffer 写缓冲区
    linux 系统为了提高下一次读取速度, 从内存cache中读取

cache加速读实例

第一次读取

dd if=/dev/zeroo of=test.img bs=1M count=512
free -h # 查看内存

total used free shared buff/cache available

Mem: 15Gi 3.7Gi 10Gi 516Mi 993Mi 11Gi

Swap: 4.0Gi 0B 4.0Gi
time grep 123 test.img
real 0m0.480s

user 0m0.138s

sys 0m0.110s

第二次读取

free -h # 查看内存, 确认cache是否增加

total used free shared buff/cache available

Mem: 15Gi 3.7Gi 10Gi 516Mi 1.5Gi 11Gi

Swap: 4.0Gi 0B 4.0Gi
time grep 123 test.img
real 0m0.163s

user 0m0.102s

sys 0m0.061s

结论:

  1. buffer/cache 由 993Mi 变为1.5Gi
  2. 第二次读取, 匹配关键字速度提升 0.480s --> 0.163s

3.优化与解决方法

1.不解决: 当系统内存不足时, 主动释放cache, 提供给程序,系统需要的内存

2.需要优化的场景

  1. 确认文件只需要读取一次, 后续不会再次读取: 比如配置文件, 只读取一次的数据

1.测试示例: posix_fadvise主动释放读缓存cache

在线gitee代码: 4_read_cache_读缓存优化_posix_fadvise.c

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[])
{
    int ret = 0;
    // 1.生产大文件
    if((ret=access("testfile.img", F_OK)) != 0)
        system("dd if=/dev/zero of=testfile.img bs=1M count=512");
    // 2.清空系统缓存
    system("sync; echo 3 > /proc/sys/vm/drop_caches");
    show_cache_buffer_info();

    // 3.打开文件
    int fd = open("testfile.img", O_RDONLY);
    if (fd < 0)
    {
        perror("open");
        exit(1);
    }

    // // 4.读缓存优化 --> 释放缓存,要在读取完之后再释放
    // if (argc == 2)
    // {
    //     char opt = *argv[1];
    //     if (opt == '1')
    //         posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE);
    //     if (opt == '2')
    //         posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
    // }

    // 5.读文件
    char buf[BUF_4K];
    while (1)
    {
        ret = read(fd, buf, BUF_4K);
        if (ret < 0)
        {
            perror("read");
            exit(1);
        }
        if (ret == 0)
        {
            break;
        }
    }

    // 6.释放读缓存
    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);
    }

    close(fd);
    show_cache_buffer_info();
}

1.默认读取文件--测试数据

time ./4_read_cache_读缓存 优化_posix_fadvise.out

复制代码
           total        used        free      shared  buff/cache   available

Mem: 15998 3566 11440 516 991 11636

Swap: 4096 0 4096

Buffers: 2828 kB

Cached: 938928 kB

SwapCached: 0 kB

复制代码
        total        used        free      shared  buff/cache   available

Mem: 15998 3555 10936 516 1506 11647

Swap: 4096 0 4096

Buffers: 3544 kB

Cached: 1464996 kB

SwapCached: 0 kB

real 0m0.491s

user 0m0.032s

sys 0m0.165s

2.posix_fadvise POSIX_FADV_NOREUSE预期对文件中的信息的访问不会重复 -- 测试数据

time ./4_read_cache_读缓存 优化_posix_fadvise.out 1

复制代码
           total        used        free      shared  buff/cache   available

Mem: 15998 3554 11452 516 990 11648

Swap: 4096 0 4096

Buffers: 2428 kB

Cached: 938988 kB

SwapCached: 0 kB

复制代码
           total        used        free      shared  buff/cache   available

Mem: 15998 3549 10942 516 1505 11653

Swap: 4096 0 4096

Buffers: 3300 kB

Cached: 1465136 kB

SwapCached: 0 kB

real 0m0.513s

user 0m0.026s

sys 0m0.218s

3.posix_fadvise POSIX_FADV_DONTNEED丢弃任何与该区域相关的缓存 -- 测试数据

time ./4_read_cache_读缓存 优化_posix_fadvise.out 2

复制代码
           total        used        free      shared  buff/cache   available

Mem: 15998 3562 11444 516 991 11640

Swap: 4096 0 4096

Buffers: 3028 kB

Cached: 938740 kB

SwapCached: 0 kB

total used free shared buff/cache available

Mem: 15998 3560 11442 516 994 11642

Swap: 4096 0 4096

Buffers: 4012 kB

Cached: 941124 kB

SwapCached: 0 kB

real 0m0.538s

user 0m0.035s

sys 0m0.232s

4.测试小结:

通过系统API posix_fadvise POSIX_FADV_DONTNEED 可以主动释放文件读缓存cache

4.总结

  1. 读缓存cache, 是系统为了提高下一次读取速度, 保存文件内存在内存中
  2. 确认是否优化减少读缓存cache
  3. 目前已知的读缓存cache优化点
    1. 文件只需要读取一次, 后续不会再次读取: 如配置文件, 或只读取一次的数据

相关推荐
刻BITTER1 天前
LocalLow 乱码文件排查 Intel INSC着色器缓存文件
缓存·哈希算法·着色器
熊出没1 天前
高并发高可用系统设计:限流、熔断、降级与多级缓存实战指南
缓存·高并发·架构设计·高可用
DLYSB_1 天前
门店断网了告警还在吗:边缘站点的缓存与续传架构
缓存·架构·报警灯
AIGC小尼1 天前
本地 AI 漫剧流水线模型缓存与特征向量持久化:IPAdapter 预编码、特征池复用与内存池管理实战
人工智能·spring boot·缓存·预编码算法·comfyui·ai漫剧
论文复现现场1 天前
DeepSeek V4.1 Flash 各平台价格怎么比?缓存、峰谷计费与 Python 成本计算
开发语言·python·缓存·大模型·成本优化·deepseek
豆角焖肉1 天前
SpringBoot + Redis 缓存实战
java·spring boot·redis·后端·缓存·菜单缓存
蓝胖的四次元口袋2 天前
Redis知识梳理(1)
数据库·redis·缓存
wefg12 天前
【Redis】C++ 自定义客户端
数据库·redis·缓存
一个有温度的技术博主2 天前
两级缓存一致性实战:Redis + 本地缓存,如何不让数据“分裂”?
redis·spring·缓存