内存性能监控:Buffer 和 Cache 如何影响系统性能?

文摘   2024-11-20 09:01   广东  

点击上方【蓝字】关注博主

 深入探讨了内存的本质、虚拟内存与物理内存的映射关系,并详细阐述了 Buffer 和 Cache 在内存优化中的重要作用。通过了解这些概念,我们可以更清晰地理解系统资源的分配和利用方式,从而更好地掌控系统性能。

01

内存是什么?

内存直接影响着程序运行的效率和系统稳定性。我们常说的“内存”通常是指虚拟内存,而操作系统实际使用的则是物理内存。


虚拟内存:虚拟内存是操作系统为每个进程创建的一个独立的、连续的地址空间,它允许进程访问比物理内存更大的内存范围。每个进程都认为自己拥有了完整的虚拟内存空间,但实际上,这只是一层抽象。历史上,在虚拟内存尚未引入之前,程序使用的都是物理地址,因此其寻址空间受到CPU地址线条数的限制。例如,在32位平台下,寻址的范围是232,即4GB。这种限制在进程管理上带来了诸多挑战:

  1. 内存资源竞争:如果每个进程都被分配4GB的物理内存,当多个进程同时需要执行时,物理内存显然不够用。此时,未获得内存资源的进程只能等待,这会导致系统效率低下,频繁的内存装入和剔除操作更是增加了开销。

  2. 安全性问题:程序直接访问物理内存的方式,意味着一个进程可能会修改其他进程的数据,甚至改写内核空间的数据,这是不安全的。

  3. 地址分配混乱:由于内存是随机分配的,不同进程的地址空间可能不一致,导致程序运行的地址不正确。

物理内存:物理内存则是计算机硬件中实际存在的内存芯片,它的容量是有限的。操作系统会将多个进程的虚拟内存映射到物理内存上,并使用页表来记录虚拟地址和物理地址之间的对应关系。

虚拟内存与物理内存之间的关系:

  • 映射关系:操作系统通过页表将虚拟内存空间映射到物理内存空间。页表类似于一个字典,将虚拟地址作为键,物理地址作为值。

  • 按需分配:进程在运行时并不会立即将所有虚拟内存空间映射到物理内存,而是根据需要进行分配,即按需分页。当进程访问一个从未被分配物理内存的地址时,就会触发缺页异常。

  • 页面置换: 当物理内存空间不足时,操作系统会使用页面置换算法选择一个页,将其从物理内存中移出,并将其交换到磁盘上,释放出空间。

虚拟内存和物理内存示意图:

虚拟内存的优势:

  • 每个进程都被虚拟分配4GB的地址空间,多个进程共享物理内存,提高了内存利用率,减少了内存浪费。

  • 每个进程拥有独立的虚拟内存空间,可以有效隔离进程,防止一个进程访问另一个进程的内存空间,增强了系统安全。

  • 虚拟内存允许程序访问比物理内存更大的内存空间,可以运行更大更复杂的程序。

当进程尝试访问某个地址时,必经如下步骤:

  1. 地址转换:进程首先需要将虚拟地址转换为实际的物理地址。

  2. 内存共享:所有进程共享物理内存,且每个进程仅映射其所需的虚拟地址空间。

  3. 页表管理:进程需了解哪些虚拟地址已映射到物理内存,哪些未映射(可能位于磁盘),以及在物理内存中的具体位置,通常通过页表进行管理。

  4. 页表结构:页表中的每一条记录分为两部分,第一部分指示该页是否在物理内存中,第二部分则给出物理地址(若在的话)。

  5. 缺页异常:当进程访问虚拟地址时,若页表显示该页不在物理内存,则会触发缺页异常。

  6. 处理缺页异常:操作系统会立即阻塞该进程,并从硬盘将对应页调入内存。若物理内存已满,则需依据操作系统的页面置换算法决定覆盖哪一页。

当进程访问一个不在物理内存中的虚拟地址时,就会触发缺页异常。操作系统会执行以下步骤来处理缺页异常:

  1. 检查页表:操作系统会检查页表,发现对应的页面不在物理内存中。

  2. 选择页面:操作系统会根据页面置换算法选择一个页面,将其从物理内存中移出,并将内容写入磁盘。

  3. 加载页面:操作系统会从磁盘中读取需要访问的页面,并将它加载到物理内存中。

  4. 更新页表:操作系统会更新页表,将新加载的页面地址记录到页表中。

  5. 恢复进程:操作系统会恢复被阻塞的进程,使其继续运行。

页表工作原理示意图:

  1. CPU 想访问虚拟地址所在的虚拟页(VP3)。

  2. 根据页表,找出页表中第三条的值,判断有效位。

  3. 如果有效位为 1,代表该页面在物理内存中,根据物理页号找到对应的物理页面,获取数据。

  4. 如果有效位为 0,代表该页面不在物理内存中,触发缺页异常,调用内核缺页异常处理程序。

  5. 内核选择一个页面作为被覆盖的页面,将该页面的内容写入磁盘。

  6. 将 VP3 映射的磁盘文件缓存到被选择的物理页面上。

  7. 更新页表,将有效位设置为 1,并将物理页号写入页表。

  8. 缺页异常处理完毕后,返回中断前的指令,重新执行,此时缓存命中。

  9. 将找到的内容映射到高速缓存中,CPU 从高速缓存中获取该值,结束。

示例,假设一个进程需要访问虚拟地址0x1000,而该地址对应的物理内存页尚未加载到物理内存中:

  1. CPU 发出访问0x1000的请求。

  2. 操作系统检查页表,发现0x1000对应的页面不在物理内存中,而是位于磁盘上的某个位置。

  3. 操作系统选择一个物理内存页面,将它写入磁盘。

  4. 操作系统从磁盘读取0x1000对应的页面,并将其加载到物理内存中。

  5. 操作系统更新页表,将0x1000对应的物理页面地址记录到页表中。

  6. CPU 再次访问0x1000时,会命中缓存,直接从物理内存中获取数据。


进程创建与内存映射:当进程创建时,内核为其分配4GB的虚拟内存。此时,内存仅是一个布局尚未实际装入数据,映射关系已建立,但数据和代码(如.text .data段)仍保留在硬盘上。只有当进程实际访问时,发生缺页异常,才会将数据复制到物理内存中。


在进程动态分配内存(使用malloc)时,同样只是在虚拟内存中划分空间,页表项的设置也只是虚拟内存的管理,只有当进程实际访问该内存时,才会触发缺页异常。

虚拟内存是操作系统的一种重要的内存管理机制,它为每个进程提供了独立的地址空间,并通过页表将虚拟地址映射到物理地址,实现了内存共享和保护,提高了内存利用率,为现代操作系统提供了高效可靠的内存管理能力。

除了按需分页,操作系统还可能使用预读技术,提前将磁盘上的页面加载到物理内存中,以减少缺页异常的发生频率。页表本身也存储在物理内存中,操作系统会使用多级页表来管理虚拟内存空间,以节省内存空间。

02

内存中的 buffer 和 cache

root@ubuntu:/home/root# free -h
total used free shared buff/cache available
Mem: 5.9G 1.2G 1.1G 36M 3.6G 4.3G
Swap: 974M 12K 974M

该界面展示了物理内存(Mem)与交换分区(Swap)使用情况的详细信息,包括总内存、已用内存、缓存区、可用内存等关键参数。在这里,缓存是由 Buffer 和 Cache 两部分组成的总和。

  • Mem 行(第二行)是内存的使用情况。涵盖了物业内存总量、已使用量与可用量。

  • Swap 行(第三行)是交换空间的使用情况,反映了系统在物理内存不足时如何借助虚拟内存来进行数据存储。

  • total 列显示系统总的可用物理内存和交换空间大小。表明资源的整体可用性。

  • used 列显示已经被使用的物理内存和交换空间,帮助用户了解当前内存的实际使用情况。

  • free 列显示还有多少物理内存和交换空间可用使用,从而为应用程序的运行提供参考。

  • shared 列显示被共享使用的物理内存大小,反映了多个进程间共享数据的程度。

  • buff/cache 列显示被 buffer 和 cache 使用的物理内存大小。当系统启动或平时运行时,这部分内存会被作为缓存使用,以提高性能。

  • available 列显示还可以被应用程序使用的物理内存大小。

对于buffer和cache的区别:

  1. Buffers 是对原始磁盘块的临时存储,也就是用来缓存磁盘的数据,通常不会特别大(20MB 左右)。这样,内核就可以把分散的写集中起来,统一优化磁盘的写入,比如可以把多次小的写合并成单次大的写等等。

  2. Cached 是从磁盘读取文件的页缓存,也就是用来缓存从文件读取的数据。这样,下次访问这些文件数据时,就可以直接从内存中快速获取,而不需要再次访问缓慢的磁盘。

  3. Buffer 既可以用作“将要写入磁盘数据的缓存”,也可以用作“从磁盘读取数据的缓存”。

  4. Cache 既可以用作“从文件读取数据的页缓存”,也可以用作“写文件的页缓存”。

Buffer 主要是针对磁盘数据进行的缓存,而 Cache 则是针对文件数据进行的缓存。它们在内存管理中各自扮演着重要的角色,既可以用于读请求,也可以用于写请求。


在读写普通文件的过程中,所有操作都经过文件系统,这个系统负责与物理磁盘之间的交互;然而,在进行对磁盘或分区的读写操作时,通常会跳过文件系统层,这被称为“裸I/O”。这两种读写方式在缓存使用上是有所区别的,正是本文讨论的 Buffer 和 Cache 的重要性所在。通过理解这两者之间的差异,可以更好地优化系统性能,确保数据存取的高效与准确。

03

内存优化监测

Buffer 和 Cache 分别用于缓存对磁盘和文件系统的读写数据。

  • 从写的角度来看,内存的优化不仅可以有效地提升磁盘和文件的写入效率,还能为应用程序带来实质性的好处。当数据被写入 Buffer 后,应用程序可以迅速返回去继续执行其他工作,而不必等待数据真正落到磁盘上。这一机制极大地提高了系统的响应速度,使得应用程序能够保持良好的用户体验,尤其在处理大量数据时,能够显著缩短工作延迟。同时,系统会在适当时机将这些数据从 Buffer 中写入磁盘,确保数据的持久性与安全性。

  • 从读的角度来看,优秀的内存管理优化能够显著提高那些频繁访问数据的读取速度。当数据经过 Cache 存储后,下次读取时便可以直接从内存中快速提取,相比之下,这种方式无疑要比每次都访问较慢的磁盘来的高效得多。通过降低磁盘的随机 I/O 操作频率,内存优化还能够有效减轻对磁盘的压力。这种减轻压力的效果不仅延长了磁盘的使用寿命,同时也提升了系统整体的稳定性,进一步优化了系统性能。

因此,内存的优化与监测不是一项单一的任务,而是一系列复杂操作的结合,涉及对 Buffer 和 Cache 有效利用,以最大化性能和资源利用率。通过持续的监测和调整,确保系统在读写操作过程中始终能够保持高效和稳定。这种优化过程不仅适用于大型应用程序,也惠及日常使用场景,为用户带来更流畅的体验。

一些用于监测Linux内存的方法和工具:

  1. free:这个命令提供了系统内存的使用情况,包括总内存、已用内存、空闲内存、缓存和交换内存等信息。

    free -h
  2. top/htop:这两个命令可以监测系统的性能,包括内存和CPU的使用情况。htop提供了更友好的界面。

  3. vmstat:这个命令显示了关于虚拟内存、进程、CPU活动等的统计信息。

    vmstat 1
  4. sar:通过sysstat工具包提供了系统资源的收集和报告功能,可以监测内存、CPU、IO等。

    sar -r 1
04

总结

  • 虚拟内存是操作系统为每个进程提供的独立地址空间,通过页表将虚拟地址映射到物理地址,实现了内存共享和保护,提高了内存利用率。

  • 物理内存则是计算机硬件中实际存在的内存芯片,其容量是有限的。

  • Buffer是针对磁盘数据进行的缓存,可以用于优化磁盘读写操作,提高效率和稳定性。

  • Cache是针对文件数据进行的缓存,可以提高文件访问速度,降低磁盘的随机 I/O 操作频率。

  • 内存监测工具如 free、top、htop、vmstat 和 sar 可以帮助我们监控系统内存的使用情况,及时发现并解决潜在问题。

公众号: Lion 莱恩呀

微信号: 关注获取

扫码关注 了解更多内容

点个 在看 你最好看


Lion 莱恩呀
专注分享高性能服务器后台开发技术知识,涵盖多个领域,包括C/C++、Linux、网络协议、设计模式、中间件、云原生、数据库、分布式架构等。目标是通过理论与代码实践的结合,让世界上看似难以掌握的技术变得易于理解与掌握。
 最新文章