内存碎片产生原因及如何避免内存碎片

内存碎片产生原因及如何避免内存碎片

内存碎片是指已经分配的内存块之间出现未被利用的空间,这种空间会导致内存利用率降低,从而影响系统的性能和稳定性。

内存碎片产生的原因

主要有以下几种:

频繁的内存分配和释放:由于内存分配和释放不均衡,容易导致一些小的碎片不同大小的内存分配:当系统中分配的内存大小不一致时,也会导致碎片内存对齐的问题:当内存分配时没有对齐,也会导致碎片如何避免内存碎片?

可以采用以下策略:

内存池:使用内存池可以减少频繁的内存分配和释放,从而避免碎片的产生。统一内存分配方式:使用相同的内存分配方式可以避免不同大小的内存分配。对齐内存分配:通过对齐内存分配,可以减少内存碎片的产生。使用内存压缩算法:内存压缩算法可以将内存中的碎片进行整理,从而减少碎片。避免内存泄漏:内存泄漏会导致一些内存无法释放,也会导致碎片的产生。综上所述,避免内存碎片需要注意内存分配的方式、内存对齐及防止内存泄露。

从实践来讲,两种方法可以减少内存碎片。

1)回收内存,减少碎片

2)压缩碎片

在长时间运行的Linux操作系统中,系统日志有时会出现无法分配高阶内存的报错信息:

Aug 4 22:58:15 server1 kernel: : [69229257.683658] xenwatch: page allocation failure. order:4, mode:0xd0

Aug 4 22:58:15 server1 kernel: : [69229257.683665] Pid: 168, comm: xenwatch Tainted: GF --------------- 2.6.32-358.23.2.el5.x86_64 #1

Aug 4 22:58:15 server1 kernel: : [69229257.683672] Call Trace:

Aug 4 22:58:15 server1 kernel: : [69229257.683688] [] ? __alloc_pages_nodemask+0x67a/0x8c0

Aug 4 22:58:15 server1 kernel: : [69229257.683697] [] ? number+0x2ff/0x330

Aug 4 22:58:15 server1 kernel: : [69229257.683706] [] ? kmem_getpages+0x60/0x150

进一步查看的系统内存(cache多可能是io导致的,为了提高io效率留下的缓存,这部分内存实际是可以释放的):

此时使用cat /proc/buddyinfo观察内存order分配情况,可以看到内存碎片化严重(大量的低阶内存页,但是几乎没有高阶内存页,0多表示伙伴系统没有大块内存了)

# cat /proc/buddyinfo

Node 0, zone DMA 2 2 2 1 2 1 1 0 0 0 2

Node 0, zone DMA32 32995 4377 762 211 157 108 68 23 3 0 0

Node 0, zone Normal 127146 68215 1614 0 0 0 0 0 0 0 1

处理的方法主要采用drop_caches(抛弃缓存),然后使用compact_memory合并低阶内存页来创造出足够的高阶内存页。

drop_caches

Linux Kernel 2.6.16之后的内核提供了一个设置内核抛弃 页缓存 和/或 目录(dentry)和索引节点(inode)缓存,这样可以释放出大量内存。

### 释放页缓存

echo 1 > /proc/sys/vm/drop_caches

### 释放目录和索引节点缓存(inode and dentry cache)

echo 2 > /proc/sys/vm/drop_caches

### 同时释放 页、目录、索引节点缓存:

echo 3 > /proc/sys/vm/drop_caches

上述操作是无害的操作,并且智慧释放完全没有使用的内存对象。脏对象(dirty objects)将继续被使用直到它们被写入到磁盘中,所以内存脏对象不会被释放。不过,如果在执行drop_caches之前执行sync指令,则会将脏对象刷新到磁盘中,这样drop_caches操作会释放出更多内存。

注意:drop_caches需要花费一些时间(在终端中可以看到大约几十秒时间),此时再次使用cat /proc/buddyinfo可以看到立即出现了大量高阶内存页。

但是drop_caches这个触发动作是一次性的,也就是说,并不因为cat /proc/sys/vm/drop_caches时显示输出内容是3就表示系统不缓存内容。相反,一旦完成drop_caches,系统立即自动对后续内存对象进行缓存。所以要再次触发缓存清理,需要再次执行 echo 3 > /proc/sys/vm/drop_caches。

如果重复echo 3 > /proc/sys/vm/drop_caches不能再次释放缓存,可以先尝试echo 0 > /proc/sys/vm/drop_caches然后再执行echo 3 > /proc/sys/vm/drop_caches。

compact_memory

当内核编译参数设置了CONFIG_COMPACTION,就会在/proc/sys/vm/compact_memory有入口文件。将1写入到这个文件,则所有的zones就会进行压缩,以便能够尽可能地提供连续内存块。对于需要分配大页的时候这个功能非常重要,不过,进程会在需要时直接进行内存压缩(compact memory)。

实际操作案例

清理缓存前检测

#cat /proc/buddyinfo

Node 0, zone DMA 2 2 2 1 2 1 1 0 0 0 2

Node 0, zone DMA32 32995 4377 762 211 157 108 68 23 3 0 0

Node 0, zone Normal 127146 68215 1614 0 0 0 0 0 0 0 1

执行缓存释放

# echo 3 > /proc/sys/vm/drop_caches

清理缓存后检测

# cat /proc/buddyinfo

Node 0, zone DMA 2 2 2 1 2 1 1 0 0 0 2

Node 0, zone DMA32 76826 65298 43784 20780 5272 616 90 32 4 0 0

Node 0, zone Normal 524538 365499 176074 45644 4338 140 6 0 0 0 1

开始执行压缩

# echo 1 > /proc/sys/vm/compact_memory

然后再次检查内存页分布,可以看到逐渐出现更多的高阶内存页

# cat /proc/buddyinfo

Node 0, zone DMA 2 2 2 1 2 1 1 0 0 0 2

Node 0, zone DMA32 18217 13464 8621 4666 2654 2087 1609 1040 517 130 3

Node 0, zone Normal 145048 131183 76864 38454 20405 11854 5149 1143 96 3

相关文章

黑咖啡加可乐 可乐冲咖啡 365国际速发彩票

黑咖啡加可乐 可乐冲咖啡

📅 06-30 👁️ 2766
武魂2各职业介绍及怎么选择门派分析? 365365bet娱乐场

武魂2各职业介绍及怎么选择门派分析?

📅 07-25 👁️ 3565
泡椒凤爪泡多久可以吃 365国际速发彩票

泡椒凤爪泡多久可以吃

📅 07-12 👁️ 9537