• Linux进程、Cgroup、容器的内存指标


    Linux 上监控内存开销时,存在多种指标,本文区分它们的定义、用途。

    进程内存

    • Linux 会准确记录每个进程占用的 CPU 时长,但统计一个进程占用的内存比较麻烦、有误差,常见的算法有 RSS、WSS 等。

      • 内核会记录每个内存 Page 是否被进程占用,但不知道被哪个进程占用。
    • 虚拟集(Virtual Set Size,VSZ)

      • :进程申请分配的内存量。
      • 例如进程多次调用 malloc() ,申请分配多块内存空间。它们的体积之和就是 VSZ 。
    • 常驻集(Resident Set Size ,RSS)

      • :进程长期驻留的内存量。是指进程的 Page Table 中,引发过缺页异常的 Pages 数。
      • 假设进程 A 申请分配了 10MB 内存空间,实际只在 2MB 内存空间中写入了数据。则 VSZ 为 10MB , RSS 为 2MB 。
        • 如果进程释放一些已用内存,则统计的 RSS 不会减少。因此 RSS 可能比进程实际占用的内存虚高。
      • RSS = 进程占用的非共享内存 + SHR。
        • RSS 包括堆、栈、共享内存,不包括 Swap ,也不包括 page tables、huge page、kernel stack、struct thread_info、struct task_struct 等。
        • 用如下命令可统计所有进程的 RSS 内存之和,但这样会重复累计 SHR 内存,因此计算结果比所有进程实际占用的内存量虚高。为了减少误差,应该统计所有进程的 PSS 内存之和。
          ps -eo rss | awk 'NR>1' | awk '{sum+=$1} END {print sum/1024}'
          
          • 1
    • SHR

      • :Shared Memory ,进程占用的共享内存。
      • 例如多个进程可能导入同一个共享库 glibc 。
    • 比例集(Proportional Set Size,PSS)

      • :按比例估算出进程的常驻内存。
      • PSS = 进程独占的非共享内存 + 进程平均占用的 SHR
      • 假设进程 A 的 RSS 为 10MB ,其中 8MB 为非共享内存,2MB 为与其它 N 个进程共享的内存。则进程 A 的 PSS = 8 + 2/(N+1) MB 。
    • 工作集(Working Set Size ,WSS)

      • :进程保持工作所需的内存。是估算进程最近访问过的 Pages 数,包括物理内存、内核内存、脏页。
      • 一个进程的 RSS 总是大于等于 WSS ,因为 RSS 可能虚高。

    Cgroup内存

    • Linux Cgroup 用于分组管理进程。一个 Cgroup 内可以包含一组多个进程,通过 Cgroup 参数监控、限制它们的CPU、内存开销。
      • 例如用 cat /sys/fs/cgroup/memory/memory.stat 可查看 Cgroup 的内存指标。
      • 关于内存的几个 Cgroup 参数:
        memory.limit_in_bytes # 限制进程最大的内存使用量,取值为 -1 则不限制
        memory.usage_in_bytes # 记录进程当前的内存使用量,包括 RSS、swap、Page Cache
        memory.oom_control    # 取值为 0 时,启用 OOM-killer ,当进程占用的内存超过限制时杀死它。取值为 1 时,禁用 OOM-killer ,只会暂停进程
        
        • 1
        • 2
        • 3

    容器内存

    • Docker 基于 Linux Cgroup 技术限制容器占用的 CPU、内存等系统资源,每个容器属于一个 Cgroup 。
    • 通常使用 cAdvisor 监控容器,它会读取容器的 Cgroup 参数,生成以下监控指标:
      container_memory_usage_bytes              # 容器占用的全部内存,读取自 Cgroup 的 memory.usage_in_bytes 文件,等于 rss + swap + cache
      container_memory_rss                      # 容器占用的 rss 内存,读取自 Cgroup 的 memory.stat 文件中的 total_rss 字段
      container_memory_swap                     # 容器占用的 swap 内存
      container_memory_cache                    # 容器占用的 Page Cache 内存
      container_memory_working_set_bytes        # 容器的工作集内存,等于 memory.usage_in_bytes - memory.stat.total_inactive_file
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 假设容器启动之后不断增加内存,则当 container_memory_usage_bytes 达到 Cgroup 限制的 memory.limit_in_bytes 时,不会触发 OOM ,而是停止增长。
        • 因为 container_memory_usage_bytes = rss + swap + cache ,在总和 container_memory_usage_bytes 不变的情况下,容器可以减少 container_memory_cache ,继续增加 container_memory_rss 。
        • 当 container_memory_working_set_bytes 达到 Cgroup 内存限制时,会触发 OOM ,杀死容器内进程。
  • 相关阅读:
    程序连接oracle查询数据的环境配置
    hudi系列-设置合理清理策略
    JavaWeb_第3章_HTTP&Tomcat&Servlet
    kafka学习-生产者
    分布式事务理论以及解决方案
    vue3.2单文件组件 <script setup> 语法糖常用写法
    反射(类加载、加载流程、加载的五个阶段、获取类结构信息、反射暴破创建实例、操作属性、操作方法)
    R语言---scale函数,match函数和%in%详解
    操作系统 OS
    docker commit 和docker build (实战使用以及区别)
  • 原文地址:https://blog.csdn.net/qq_35952638/article/details/127674184