[转帖]MALLOC_ARENA_MAX=1 与 MALLOC_ARENA_MAX=4有什么区别?

malloc,arena,max,什么,区别 · 浏览次数 : 0

小编点评

**问题:** MALLOC_ARENA_MAX 控制不住内存分配数量,导致创建多个thread arena,影响内存使用效率。 **分析:** 1. **内存池机制:** - glibc 中实现了内存池,应用程序可以通过内存池来获取和释放内存。 - 每个线程都分配一个内存区域作为线程 arena。 2. **thread arena 的创建:** - 在申请内存时,如果线程 arena空间不足,glibc 会创建一个新的 thread arena。 - 每个线程申请 64M 的内存,如果创建的 thread arena 个数超过 4 个,就无法满足所有线程的内存需求。 3. **内存释放:** - 在线程退出时,释放其所分配的内存空间。 - 然而,当创建多个 thread arena 时,释放线程 arena 的过程可能导致阻塞,因为其他线程可能正在申请这些内存。 - 如果线程 arena 的数量设置过低,会导致内存泄漏。 4. **测试结果:** - 通过测试程序,发现设置 MALLOC_ARENA_MAX 为 1 时,线程创建的 thread arena 个数过多,导致内存泄漏。 - 即使设置 MALLOC_ARENA_MAX 为其他值,也可能出现内存泄漏,因为每个线程仍然可以创建新的 thread arena。 **结论:** 设置 MALLOC_ARENA_MAX 值为 1 可以控制线程 arena 的数量,但这也可能导致内存泄漏。建议根据实际需求设置此参数,以平衡性能和内存利用率。 **其他提示:** - 确保线程 arena 的大小足够来存放所有需要存储的数据。 - 考虑使用其他内存分配技术,例如 mmap 或 slab。 - 监控进程内存占用情况,并在内存泄漏时采取措施。

正文

  • https://www.easyice.cn/archives/341

     

2019年 Elastic开发者大会的时候我曾经说过 glibc 导致的堆外内存过多问题:

如果应用程序每次分配内存的时候都通过系统调用 mmap,sbrk等来分配,效率会很低,所以glibc 中实现了一个内存池,应用程序使用内存的时候通过glibc的内存池来提供,早期的 glibc 版本中,只有一个内存池,称为 main arena,在多线程场景中,每次分配和释放需要进行加锁。后来为了降低锁的粒度,从glibc 2.10版本开始引入了 thread arena,线程在申请内存的时候,glibc 为他创建一个 thread arena,这个内存池的大小一般是64M,thread arena被不被某个线程独占,全部的 thread arena被加入到环形链表,被所有线程共享使用。

环境变量 MALLOC_ARENA_MAX 用来控制进程可以创建的 thread arena 数量上限(默认为 cpu core*8),在 Hadoop 中这个值设置为 4,军义兄发现要设置为1,否则控制不住,但是不清楚原因,按照常规的理解,既然这个参数可以生效,就应该准确地控制 arena 数量,和数值设置成多少没关系,查阅资料没有找到相关描述。近日一个 Hadoop 的 NameNode 占用内存比预期值多了40G,pmap 看一下,多出来的基本就是 64M 的 thread arena,查看进程当前的环境变量值:

 

 

确认为4,于是分析一下 MALLOC_ARENA_MAX 控制不住的原因。

这种情况通过简单的测试程序可以复现,看了一下 glibc 的相关代码,基本搞清楚了来龙去脉。

MALLOC_ARENA_MAX 控制不住的原因

如果 MALLOC_ARENA_MAX 设置为 n,当 n 个 thread arena 的内存空间全被占满的时候,线程新申请内存的时候优先创建新的 arena,不受 n 的限制,并且是无上限的。测试过程如下:

创建10个线程,每个线程申请64M 内存,不能直接 malloc 64M,因为glibc对于大块内存的申请直接 mmap

 

 

编译执行这个程序:

 

 

然后 pmap 查看进程内存空间:

 

 

标红的区域为进程创建的 thread arena,当配置的 n 个 thread arena空间不足时,glibc 有两种处理方式:

  • 创建新的 thread arena
  • 从 main arena 分配

绝大部分情况下,会创建新的 thread arena。

从实现上来说,arena_lookup查找分配区和 arena_lock锁分配区的时候并不关心该分配区的空间是否足够,如果 arena_lock 到的分配区空间不足,就创建新的thread arena
函数:sysmalloc

new_heap 创建新的 thread arena 时并不检查MALLOC_ARENA_MAX的配置值。

MALLOC_ARENA_MAX 可以生效的情况

与上面的结论相同,只有在thread arena没有被占满的情况下。为 MALLOC_ARENA_MAX设置的阈值可以控制住设定的数量。

将上面的测试程序修改为每个线程申请4M 内存,其他不变:

 

 

运行时参数不变,pmap 查看进程内存情况,共创建了3个 thread arena

为什么 MALLOC_ARENA_MAX 设置为1 能够控制住

当设置为1,相当于禁用了 thread arena,arena_lookup每次都会返回 main arena, 不会创建任何 thread arena

总结

当 glibc 的内存池空间不足时,优先创建thread arena进行分配。但是在内存释放的时候,又需要等待 top chunk释放掉,才能释放一个连续的空间给操作系统,造成 thread arena 存在非常多的一个主要原因是存在很多生命周期比较长的对象,如果这些对象能够及时释放,虽然进程可能会在短时间创建许多 thread arena,但实际上并不占据 RES,所以根本问题还是那些具有长生命周期的对象。

当只使用 main arena 的情况下,虽然具有长生命周期的对象不变,但是内存池中的空间被重用的几率比多个 thread arena 更高,进程占据的的 RES 要相对少一些。

参考

https://paper.seebug.org/papers/Archive/refs/heap/glibc内存管理ptmalloc源代码分析.pdf
http://pwn4.fun/2016/04/11/深入理解glibc-malloc/
https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/

与[转帖]MALLOC_ARENA_MAX=1 与 MALLOC_ARENA_MAX=4有什么区别?相似的内容:

[转帖]MALLOC_ARENA_MAX=1 与 MALLOC_ARENA_MAX=4有什么区别?

https://www.easyice.cn/archives/341 2019年 Elastic开发者大会的时候我曾经说过 glibc 导致的堆外内存过多问题: 如果应用程序每次分配内存的时候都通过系统调用 mmap,sbrk等来分配,效率会很低,所以glibc 中实现了一个内存池,应用程序使用内

[转帖]Java原生内存管理(native memory management)(5)-MALLOC_ARENA_MAX

https://zhuanlan.zhihu.com/p/423000502 这篇文章来说说和PhantomReference/finalize无关的东西 - MALLOC_ARENA_MAX. 这个东西只对Linux里的Java有用, 如果你在Linux上有内存耗尽(OOM, out of mem

[转帖]malloc()与 alloc()区别

https://www.cnblogs.com/longyi1234/archive/2010/03/22/malloc.html malloc()与 alloc() C语言跟内存分配方式 (1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量

[转帖]大页内存的使用:大页内存分配与释放

目录 函数声明 函数原型与使用 函数声明 void *malloc_huge_pages(size_t size);void free_huge_pages(void *ptr); 函数原型与使用 #include #include #include

[转帖]jemalloc内存分配算法

https://www.cnblogs.com/xiaojiesir/p/15450732.html jemalloc内存分配算法简介 jemalloc 是由 Jason Evans 在 FreeBSD 项目中引入的新一代内存分配器。它是一个通用的 malloc 实现,侧重于减少内存碎片和提升高并发

[转帖]文文的复习笔记--底层内存管理

内存分配方式: c++中,内存分成五个区: 堆:new分配执行的内存块,一个new一个delete。 栈:执行函数,局部变量的存储单元在栈上创建,执行结束存储单元自动释放。 自由存储区:由malloc分配的内存块,和堆相似,用free结束自己的生命。 全局/静态存储区:全局变量和静态变量被分配到这一

[转帖]一次操作系统报错OutOfMemory Error的处理记录

在启动公司内嵌的tomcat容器时出现报错, 如下: # There is insufficient memory for the Java Runtime Environment to continue.# Native memory allocation (malloc) failed to a

[转帖]

Linux ubuntu20.04 网络配置(图文教程) 因为我是刚装好的最小系统,所以很多东西都没有,在开始配置之前需要做下准备 环境准备 系统:ubuntu20.04网卡:双网卡 网卡一:供连接互联网使用网卡二:供连接内网使用(看情况,如果一张网卡足够,没必要做第二张网卡) 工具: net-to

[转帖]

https://cloud.tencent.com/developer/article/2168105?areaSource=104001.13&traceId=zcVNsKTUApF9rNJSkcCbB 前言 Redis作为高性能的内存数据库,在大数据量的情况下也会遇到性能瓶颈,日常开发中只有时刻

[转帖]ISV 、OSV、 SIG 概念

ISV 、OSV、 SIG 概念 2022-10-14 12:29530原创大杂烩 本文链接:https://www.cndba.cn/dave/article/108699 1. ISV: Independent Software Vendors “独立软件开发商”,特指专门从事软件的开发、生产、