暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

3790.内存碎片调试

张鹏 2025-03-28
236

3790.内存碎片调试
Buddy 算法简介
Buddy 算法是 Linux 内核中用于管理物理内存碎片的一种算法。它将所有空闲的内存块按照 2 的幂次方大小分成 11 个块链表,分别对应 1、2、4、8、16、32、64、128、256、512、1024 个页块(page blocks)。当需要分配内存时,内核会根据请求的大小从相应的块链表中查找并分配内存块。如果找不到合适大小的内存块,则会从更大的块链表中分割出一个来,并更新相应的链表信息。
/proc/buddyinfo 文件内容
/proc/buddyinfo 文件记录了当前系统中每个 NUMA 节点(如果支持 NUMA 技术)和每个内存区域(zone)中不同大小内存块的空闲数量。文件内容通常按照以下格式显示:
Node X, zone Y Z1 Z2 Z4 … Z1024
Node X:表示 NUMA 节点的编号。
zone Y:表示内存区域的名称,如 DMA、Normal、HighMem 等。
Z1, Z2, Z4, …, Z1024:分别表示大小为 1、2、4、…、1024 个页块的内存块的空闲数量。
示例解读
假设 /proc/buddyinfo 文件的内容如下:
Node 0, zone DMA 23 15 4 5 2 3 3 2 3 1 0
Node 0, zone Normal 149 100 52 33 23 5 32 8 12 2 59
Node 0, zone HighMem 11 21 23 49 29 15 8 16 12 2 142
这表示:
在 Node 0 的 DMA 区域中,有 23 个 1 页块的空闲内存块,15 个 2 页块的空闲内存块,以此类推。
在 Node 0 的 Normal 区域中,有 149 个 1 页块的空闲内存块,100 个 2 页块的空闲内存块,以此类推。
在 Node 0 的 HighMem 区域中,有 11 个 1 页块的空闲内存块,21 个 2 页块的空闲内存块,以此类推。
使用场景
/proc/buddyinfo 文件主要用于系统调试和性能分析。通过查看这个文件,可以了解当前系统中内存碎片的情况,以及不同大小内存块的空闲数量。这对于优化内存使用、减少内存碎片、提高系统性能等方面都有很大的帮助。
注意事项
/proc/buddyinfo 文件是内核动态生成的,因此其内容会随着系统的运行而发生变化。
在使用这个文件时,需要注意文件内容的格式和含义,以便正确地解读和分析。
由于不同版本的 Linux 内核和发行版可能对 /proc/buddyinfo 文件的内容有所差异,因此在使用时需要参考相应版本的文档或资料。
meminfo
/proc/meminfo 文件是 Linux 系统中一个非常重要的文件,它提供了关于系统内存使用情况的详细信息。以下是对 /proc/meminfo 文件中各个字段的解释:
MemTotal:
表示系统总内存大小,即物理内存总量。
单位通常是 KB,但也可以通过命令输出格式或工具进行转换。
MemFree:
表示系统空闲内存大小,即未被分配的内存量。
这些内存还没有被使用,是系统可用的空闲资源。
MemAvailable:
表示系统可用内存大小,这是考虑到缓存和内存回收后真正可用于新分配的内存量。
这个值通常比 MemFree 要大一些,因为它包括了可以回收的缓存内存。
Buffers:
表示为块设备做缓存的内存空间大小。
这些内存被用于缓存 I/O 操作的数据,以提高系统性能。
Cached:
表示分配给文件缓冲区的内存空间大小。
这些内存被用于缓存文件系统中的数据,以加快文件访问速度。
SwapCached:
表示来自交换分区的缓存页面大小,这些页面已被交换回内存但尚未被修改。
在内存紧张时,这些页面可以被释放以腾出空间。
Active:
表示最近被使用或访问的内存量。
这些内存是活跃的,即它们最近被系统或进程使用过。
Inactive:
表示最近未使用但可能被重新使用的内存量。
这些内存是非活跃的,但它们仍然可以被系统或进程重新使用。
Active(anon) 和 Inactive(anon):
分别表示活跃的匿名内存和不活跃的匿名内存大小。
匿名内存是指未映射到文件的内存页面,它们通常属于进程的私有内存。
Active(file) 和 Inactive(file):
分别表示活跃的文件缓存内存和不活跃的文件缓存内存大小。
这些内存被用于缓存文件系统中的数据。
Unevictable:
表示无法被回收或释放的内存大小。
这些内存页被锁定在内存中,无法被交换或回收。
Mlocked:
表示由于内存锁定而无法被交换的内存大小。
这些内存页被程序锁定在物理内存上,以防止它们被交换到磁盘上。
SwapTotal 和 SwapFree:
分别表示总交换分区的大小和空闲交换分区的大小。
交换分区是系统用于在内存不足时暂时存储数据的磁盘空间。
Dirty 和 Writeback:
分别表示等待被写回到磁盘的内存大小和正在被写的内存大小。
这些内存页包含了需要被写回到磁盘的数据。
AnonPages:
表示未映射到文件的匿名内存大小。
这些内存页没有与任何文件相关联,通常用于进程的私有数据。
Mapped:
表示内存映射的文件大小。
这些内存页被映射到文件上,允许进程直接访问文件数据。
Shmem:
表示共享内存大小。
共享内存允许多个进程共享同一块内存区域。
Slab、SReclaimable 和 SUnreclaim:
分别表示用于内核数据结构的缓存内存大小、可回收的 Slab 内存大小和不可回收的 Slab 内存大小。
Slab 分配器是内核中用于管理小块内存的一种机制。
KernelStack:
表示内核堆栈使用的内存量。
内核堆栈是内核为每个线程分配的内存区域,用于存储线程的上下文信息。
PageTables:
表示页表使用的内存大小。
页表是内核用于将虚拟地址映射到物理地址的数据结构。
CommitLimit 和 Committed_AS:
分别表示系统可以分配的最大内存量(包括交换分区)和已承诺的内存量(已被程序申请但可能未实际使用)。
CommitLimit 是系统可以分配的内存上限,而 Committed_AS 是当前已承诺使用的内存量。
VmallocTotal、VmallocUsed 和 VmallocChunk:
分别表示可供 vmalloc 分配的虚拟内存总量、已使用的 vmalloc 内存量和当前可用的最大 vmalloc 内存块大小。
vmalloc 是内核中用于分配大块连续虚拟内存的一种机制。
这些字段提供了系统管理员和开发人员了解系统内存使用情况的重要信息,有助于进行性能优化和故障排查。
板卡信息
正常板卡信息

内存碎片恶化后的信息:

调试方法:
cat /proc/sys/vm/swappiness
echo 10 > /proc/sys/vm/swappiness
内存碎片问题可以通过多种方式强制回收。以下是一些常用的方法和命令:
使用命令回收内存碎片
sync命令:
功能:强制将内存中的脏数据写回磁盘,释放内存。
使用方法:执行sync命令。
效果:腾出较大的连续内存块,减少碎片。
echo命令:
功能:通过向/proc/sys/vm/drop_caches文件中写入值来清除系统中的缓存。
使用方法:
释放页面缓存:echo 1 > /proc/sys/vm/drop_caches
释放页面缓存和目录项缓存:echo 2 > /proc/sys/vm/drop_caches
释放页面缓存、目录项缓存和inode缓存:echo 3 > /proc/sys/vm/drop_caches
效果:释放被缓存的数据所占用的内存,减少内存碎片。
wq mem reclaim命令:
功能:强制Linux内核进行内存回收。
使用方法:执行echo w > /proc/sysrq-trigger命令。
注意事项:过度频繁地使用这个命令可能会导致系统性能下降,需要根据实际情况来判断何时使用。
调整系统参数优化内存管理
增加swappiness的值:
功能:控制内核换出内存的相关策略。
方法:通过sysctl命令设置,如sysctl -w vm.swappiness=XX(XX为具体的值,通常建议根据系统实际情况调整)。
效果:提高内核主动换出内存的可能性,从而整合更大的连续内存块,减少碎片。
调整vm配置:
文件位置:/etc/sysctl.conf
可调整参数:
vfs_cache_pressure:控制inode cache和dentry cache的回收速度。
min_free_kbytes:控制系统将内存swap out到交换空间的积极性。
其他影响内存管理的配置项。
调整建议:根据系统实际情况谨慎调整,并测试对系统性能的影响。
优化程序内存分配
程序应避免过度分配或不释放内存,这会加剧内存碎片问题。
应根据实际需要合理分配和及时释放内存,以减少内存碎片的产生。
使用内存碎片整理工具
可以安装一些专门的内存碎片整理工具,如Compact或Ramster等。
这些工具可以定期帮助整理内存,提高内存利用效率。
调整 M_MMAP_THRESHOLD
C++程序的内存回收主要依赖于操作系统的内存管理。使用mallopt函数来调整GNU C库中的内存分配器的行为。这个值决定了当请求的内存块大于这个值时,内存分配器会使用mmap系统调用来分配内存。
#include <malloc.h>
#include <stdio.h>
int main() {
// 设置M_MMAP_THRESHOLD为32K字节
int ret = mallopt(M_MMAP_THRESHOLD, 32*1024);
if (ret == 1) {
printf(“M_MMAP_THRESHOLD set successfully\n”);
} else {
printf(“Failed to set M_MMAP_THRESHOLD\n”);
}
return 0;
}
内存阈值设置:
PTMalloc内存管理优化:原理与实战指南-CSDN博客
内存压测
stress --cpu 4 --vm 2 --vm-bytes 1G --hdd 2 --timeout 300s

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论