zoukankan      html  css  js  c++  java
  • Linux性能优化实战学习笔记:第十七讲

    一、缓存命中率

    1、引子

    1、我们想利用缓存来提升程序的运行效率,应该怎么评估这个效果呢?

    用衡量缓存好坏的指标

    2、有没有哪个指标可以衡量缓存使用的好坏呢?

    缓存命中率

    3、什么是缓存命中率?

    所谓缓存命中率,是指直接通过缓存获取数据的请求次数,占所有数据请求次数的百分比。命中率越高,表示使用缓存带来的收益越高,应用程序的性能也就越好

    2、查看系统命中情况的工具

    1、缓存在高并发系统的应用

    实际上、缓存是现在所有高并发系统必须的核心模块,主要作用就是把经常访问的数据(也就是热点数据),提取读入到内存中,这样下次访问时就可以直接从内存读取数据,而不需要过硬盘,从而加快应用程序的响应速度

    这些独立的缓存模块通常会提供查询接口,方便我们随时查看缓存的命中率率。不过Linux系统中并没有直接提供这些接口,
    所以我这里介绍一下cachestat 和 cachetop它们正是查看系统缓存命中情况的工具。

    2、查看系统命中情况的工具

    cachestat 提供了整个操作系统缓存的读写命中情况。

    cachetop 提供了每个进程的缓存命中情况。

    这两个工具都是 bcc 软件包的一部分,它们基于 Linux 内核的 eBPF(extended Berkeley PacketFilters)机制,来跟踪内核中管理的缓存,并输出缓存的使...

    3、cachestat和cachetop的使用方法

    在 Ubuntu 系统中

    sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4052245BD4284CDD
    echo "deb https://repo.iovisor.org/apt/xenial xenial main" | sudo tee /etc/apt/sources.list.d/iovisor.list
    sudo apt-get update
    sudo apt-get install -y bcc-tools libbcc-examples linux-headers-$(uname -r)

    操作完这些步骤,bcc 提供的所有工具就都安装到 /usr/share/bcc/tools 这个目录中了。不过这里提醒你,bcc 软件包默认不会把这些工具配置到系统的的 PATH 路径中,所以你得自己手动配置:

    export PATH=$PATH:/usr/share/bcc/tools

    cachestat 的运行界面,它以 1 秒的时间间隔,输出了 3 组缓存统计数据:

    cachestat 1 3
    TOTAL MISSES HITS DIRTIES BUFFERS_MB CACHED_MB
    2 0 2 1 17 279
    2 0 2 1 17 279
    2 0 2 1 17 279 

    cachetop

    cachetop
    11:58:50 Buffers MB: 258 / Cached MB: 347 / Sort: HITS / Order: ascending
    PID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT%
    13029 root python 1 0 0 100.0% 0.0%

    它的输出跟 top 类似,默认按照缓存的命中次数(HITS)排序,展示了每个进程的缓存命中情况。具体到每一个指标,

    这里的 HITS、MISSES 和 DIRTIES ,跟cachestat 里的含义一样,分别代表间隔时间内的缓存命中次数、未命中次数以及新增到缓存中的脏页数。

    而 READ_HIT 和 WRITE_HIT ,分别表示读和写的缓存命中率

    二、指定文件的缓存大小

    除了缓存的命中率外,还有一个指标你可能也会很感兴趣,那就是指定文件在内存中的缓存大小。你可以使用 pcstat这个工具,来查看文件在内存中的缓存大小以及缓存比例。

    pcstat 是一个基于 Go 语言开发的工具,所以安装它之前,你首先应该安装 Go 语言,你可以点击这里下载安装。

    安装完 Go 语言,再运行下面的命令安装 pcstat:

    export GOPATH=~/go
    $ export PATH=~/go/bin:$PATH
    $ go get golang.org/x/sys/unix
    $ go get github.com/tobert/pcstat/pcstat

    /bin/ls 这个文件的缓存情况:

    pcstat /bin/ls
    +---------+----------------+------------+-----------+---------+
    | Name | Size (bytes) | Pages | Cached | Percent |
    |---------+----------------+------------+-----------+---------|
    | /bin/ls | 133792 | 33 | 0 | 000.000 |
    +---------+----------------+------------+-----------+---------+

    如果你执行一下 ls 命令,再运行相同的命令来查看的话,就会发现 /bin/ls 都在缓存中了:

    ls
    $ pcstat /bin/ls
    +---------+----------------+------------+-----------+---------+
    | Name | Size (bytes) | Pages | Cached | Percent |
    |---------+----------------+------------+-----------+---------|
    | /bin/ls | 133792 | 33 | 33 | 100.000 |
    +---------+----------------+------------+-----------+---------+


    知道了缓存相应的指标和查看系统缓存的方法后我们就开始施展了

    三、案例一

    1、然后,使用 dd 命令生成一个临时文件,用于后面的文件读取测试:

    # 生成一个 512MB 的临时文件
    $ dd if=/dev/sda1 of=file bs=1M count=512
    # 清理缓存
    $ echo 3 > /proc/sys/vm/drop_caches

    2、确认刚刚生成的文件不在缓存中(终端一)

    pcstat file
    +-------+----------------+------------+-----------+---------+
    | Name | Size (bytes) | Pages | Cached | Percent |
    |-------+----------------+------------+-----------+---------|
    | file | 536870912 | 131072 | 0 | 000.000 |
    +-------+----------------+------------+-----------+---------+

    3、运行 cachetop 命令

    # 每隔 5 秒刷新一次数据
    $ cachetop 5

    4、查看cachetop界面的缓存命中情况(终端一)

    PID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT%
    ...
    3264 root dd 37077 37330 0 49.8% 50.2%

    实验二

    5、运行dd命令测试文件的读取速度(终端二)

    dd if=file of=/dev/null bs=1M
    512+0 records in
    512+0 records out
    536870912 bytes (537 MB, 512 MiB) copied, 16.0509 s, 33.4 MB/s

    6、终端一 查看cachetop界面的缓存命中情况(终端一)

    10:45:22 Buffers MB: 4 / Cached MB: 719 / Sort: HITS / Order: ascending
    PID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT%
    ...
    32642 root dd 131637 0 0 100.0% 0.0%

    7、运行dd命令测试文件的读取速度(终端二)

    dd if=file of=/dev/null bs=1M
    512+0 records in
    512+0 records out
    536870912 bytes (537 MB, 512 MiB) copied, 0.118415 s, 4.5 GB/s

    8、再回到第一个终端查看cachetop 的情况

    10:45:22 Buffers MB: 4 / Cached MB: 719 / Sort: HITS / Order: ascending
    PID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT%
    ...
    32642 root dd 131637 0 0 100.0% 0.0%

    9、回到第二个终端,再次执行 pcstat 查看文件file 的缓存情况:

    pcstat file
    +-------+----------------+------------+-----------+---------+
    | Name | Size (bytes) | Pages | Cached | Percent |
    |-------+----------------+------------+-----------+---------|
    | file | 536870912 | 131072 | 131072 | 100.000 |
    +-------+----------------+------------+-----------+---------+

    四、案例二

    1、第一个终端运行

    # 每隔 5 秒刷新一次数据
    $ cachetop 5

    2、第二个终端运行案例

    docker run --privileged --name=app -itd feisky/app:io-direct

    3、确认案例已经正常启动终端二

    docker logs app
    Reading data from disk /dev/sdb1 with buffer size 33554432
    Time used: 0.929935 s to read 33554432 bytes
    Time used: 0.949625 s to read 33554432 bytes

    4、回到第一个终端,先看看 cachetop 的输出

    16:39:18 Buffers MB: 73 / Cached MB: 281 / Sort: HITS / Order: ascending
    PID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT%
    21881 root app 1024 0 0 100.0% 0.0%

    5、继续在第二个终端

    # strace -p $(pgrep app)
    strace: Process 4988 attached
    restart_syscall(<... resuming interrupted nanosleep ...>) = 0
    openat(AT_FDCWD, "/dev/sdb1", O_RDONLY|O_DIRECT) = 4
    mmap(NULL, 33558528, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f448d240000
    read(4, "8vq213314264u3734336K22425@37112522262252q221
    030225bD252266@J"..., 33554432) = 33554432
    write(1, "Time used: 0.948897 s to read 33"..., 45) = 45
    close(4) = 0

    6、案例应用源代码

    int flags = O_RDONLY | O_LARGEFILE | O_DIRECT; 
    int fd = open(disk, flags, 0755);

    7、运行修复后应用

    # 删除上述案例应用
    $ docker rm -f app
    
    # 运行修复后的应用
    $ docker run --privileged --name=app -itd feisky/app:io-cached

    8、在第二个终端查看应用程序

    docker logs app
    Reading data from disk /dev/sdb1 with buffer size 33554432
    Time used: 0.037342 s s to read 33554432 bytes
    Time used: 0.029676 s to read 33554432 bytes

    9、在回到第一个终端 cachetop

    16:40:08 Buffers MB: 73 / Cached MB: 281 / Sort: HITS / Order: ascending
    PID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT%
    22106 root app 40960 0 0 100.0% 0.0%

    四、总结

    Buffers 和 Cache 都是操作系统来管理的,应用程序并不能直接控制这些缓存的内容和生命周期。

    所以,在应用程序开发中,一般要用专门的缓存组件,来进一步提升性能。

    比如,程序内部可以使用堆或者栈明确声明内存空间,来存储需要缓存的数据。

    再或者,使用 Redis 这类外部缓存服务,优化数据的访问效率。

  • 相关阅读:
    Analysis Services features supported by SQL Server editions
    Azure DevOps to Azure AppServices
    Power BI For Competition
    Win10开机“提示语音”以及”随机播放音乐”
    Azure DevOps
    Allow Only Ajax Requests For An Action In ASP.NET Core
    Mobile CI/CD 101
    Configure SSL for SharePoint 2013
    AWS Step Function Serverless Applications
    Cordova Upload Images using File Transfer Plugin and .Net core WebAPI
  • 原文地址:https://www.cnblogs.com/luoahong/p/10839790.html
Copyright © 2011-2022 走看看