0x00 前言

在写完了 CPU 的的性能分析笔记后,接下来是分析内存的性能问题,在分析内存的性能问题之前,肯定是需要了解内存的原理,这里的原理指的是内存软件层面的原理,如内存如何进行分配、释放等等,而不是说内存的硬件结构、内存寄存器、TLB 等等。

0x01 内存映射

常常我们在买电脑前,我们都关心一个参数:内存大小,这直接关系到我们电脑的性能,但这里的大小指的是物理内存的大小,而在操作系统上,我们的程序在运行的过程中并不是直接使用物理内存的,而是用到了虚拟内存,即通过将物理内存映射成虚拟内存供进程使用,这也正是计算机世界的规则之抽象和分层。

当程序被执行的时候,所有用到的内存地址都是虚拟内存的地址,然后再由操作系统将虚拟地址转换成物理地址,这样程序便无需关心真正的物理地址是什么,从而在程序编译的时候无需知道真正的物理地址,同时不同的进程之间也起到的隔离的作用。

具体的内存映射可以总结出以下几点:

  1. 虚拟地址分为内核空间和用户空间,同时虚拟内存模型是一个倒着的栈,栈底是高地址。如下所示:
    clipboard.png
  2. 虚拟地址和物理地址之间是要通过一个东西关联的,就像一个索引,而这个东西就是页表,Linux 用的是四级页表

0x02 内存分配与回收

分配

C 标准库使用 malloc 函数提供内存分配,有两种实现方式:

  1. brk():分配小于 128k 的内存,通过移动堆顶的位置
  2. mmap():分配大于 128k 的内存,在文件映射段找一块空闲的内存分配出去
  3. slab 分配器: 分配小于 1k 的内存,用的内存是 blk 释放的被缓存起来的内存

优缺点

  1. brk(): 频繁内存分配会造成内存碎片
  2. mmap:内存用完了会放掉,然后再次申请会有缺页异常,使内核的负担增大

释放

  1. 回收缓存: LRU算法
  2. 回收不常访问的内存,swap 到磁盘:可能会导致性能问题
  3. OOM:使用 oom_score 的权重杀进程

0x03 内存参数

free(全局)

clipboard.png

  1. total: 总内存
  2. used: 已使用内存
  3. free: 未使用内存
  4. shared: 共享
  5. buff/cache: 缓存和缓冲
  6. available: 新进程

top (单个进程)

clipboard.png

  1. VIRT(Virtual): 进程虚拟内存,只要申请过就会计算,即使没分配物理内存,所以会比实际的物理内存大很多
  2. RES(Resident): 常驻内存,即实际物理内存,不包括 swap
  3. SHR(Shared): 共享内存,比如根据前面的虚拟内存图所示,动态库段和程序代码段都属于共享内存,但也不是所有 Shared 都是共享的,有些非共享的动态库也算在了里面
  4. MEM%: 物理内存的占用百分比了

0x04 总结

今天的笔记总结下来就是,先不讨论内存的物理结构(或许后续会总结下计算机原理的内存硬件结构~),在软件层面使用内存:

  1. 不直接使用物理内存,进程是使用虚拟内存,这也是计算机抽象的一种体现
  2. 内存的分配和回收的方式的种类和方式
  3. 在 Linux 上如何查看内存的参数

在了解了内存的基本一些原理后,我们便可以进行深入的内存性能分析了。