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. 文件只需要读取一次, 后续不会再次读取: 如配置文件, 或只读取一次的数据

相关推荐
Lisonseekpan2 小时前
Java Caffeine 高性能缓存库详解与使用案例
java·后端·spring·缓存
沐浴露z9 小时前
分布式场景下防止【缓存击穿】的不同方案
redis·分布式·缓存·redission
Lisonseekpan10 小时前
Spring Boot 中使用 Caffeine 缓存详解与案例
java·spring boot·后端·spring·缓存
kfepiza14 小时前
Spring的三级缓存原理 笔记251008
笔记·spring·缓存
jun711814 小时前
msi mesi moesi cpu缓存一致性
缓存
235161 天前
【MySQL】MVCC:从核心原理到幻读解决方案
java·数据库·后端·sql·mysql·缓存
夏鹏今天学习了吗1 天前
【LeetCode热题100(35/100)】LRU 缓存
算法·leetcode·缓存
昔冰_G1 天前
Vue内置组件KeepAlive——缓存组件实例
vue.js·缓存·vue3·vue2·keep-alive·vue组件缓存·vue内置组件
2301_772093562 天前
tuchuang_myfiles&&share文件列表_共享文件
大数据·前端·javascript·数据库·redis·分布式·缓存
老朋友此林2 天前
高并发下如何保证 Caffeine + Redis 多级缓存的一致性问题?MySQL、Redis 缓存一致性问题?
数据库·redis·缓存