arena

jemalloc和内存管里

亡梦爱人 提交于 2020-03-11 12:25:24
netty的buffer引入了缓冲池。该缓冲池实现使用了jemalloc的思想。为了看懂这块代码学写了内容分配的知识。这里讲的内存分配是堆的内存分配,其他内容本文不会涉及。 内存分配是面向虚拟内存的而言的,以页为单位进行管理的,页的大小一般为4kb,当在堆里创建一个对象时(小于4kb),会分配一个页,当再次创建一个对象时会判断该页剩余大小是否够,够的话使用该页剩余的内存,减少系统调用。真实的内存分配算法比这个复杂了,效率不好的内存算法会导致出现很多内存碎片。 内存分配的核心思想概括起来有3条 1:首先讲内存区(memory pool)以最小单位(chunk)定义出来 ,然后区分对象大小分别管理内存,小内存定义不同的规格(bins),根据不同的bin分配固定大小的内存块,并用一个表 管理起来,大对象则以页为单位进行管理,配合小对象所在的页,降低碎片,设计一个好的存储方案(metadata)减少对内存的占用,同时优化内存信息的存储。以使对每个bin或大内存区域的访问性能最优且有上限。 2:当释放内存时,要能够合并小内存为大内存,该保留的保留下次可快速响应,不该保留的释放给系统 3:多线程环境下,每个线程可以独立的占有一段内存区间(TLS),这样线程内操作可以不加锁 jemalloc是freebsd的内存分配算法,他的layout如下: 1:arena:把内存分成许多不同的小块来分而治之

Go内存管理

走远了吗. 提交于 2020-02-07 06:59:31
1.前言 编写过C语言程序的肯定知道通过malloc()方法动态申请内存,其中内存分配器使用的是glibc提供的ptmalloc2。 除了glibc,业界比较出名的内存分配器有Google的tcmalloc和Facebook的jemalloc。 二者在避免内存碎片和性能上均比glic有比较大的优势,在多线程环境中效果更明显。 Golang中也实现了内存分配器,原理与tcmalloc类似,简单的说就是维护一块大的全局内存,每个线程(Golang中为P)维护一块小的私有内存,私有内存不足再从全局申请。 另外,内存分配与GC(垃圾回收)关系密切,所以了解GC前有必要了解内存分配的原理。 2.内存分配概览 3.基础概念 3.1预分配内存 为了方便自主管理内存,做法便是先向系统申请一块内存,然后将内存切割成小块,通过一定的内存分配算法管理内存。以64位系统为例,Golang程序启动时会向系统申请的内存,预申请的内存划 分为spans、bitmap、arena三部分。其中arena即为所谓的堆区,应用中需要的内存从这里分配。其中spans和bitmap是为了管理arena区而存在的。 arena的大小为512G,为了方便管理把arena区域划分成一个个的page,每个page为8KB,一共有512GB/8KB个page; spans区域存放span的指针,每个指针对应一个page

Linux堆的一些基础知识

吃可爱长大的小学妹 提交于 2019-12-06 00:49:07
目录 堆的概述 什么是堆 堆的基本操作 堆操作背后的系统调用 堆的相关数据结构 微观结构 malloc_chuck chunk相关宏 bin 宏观结构 arena heap_info malloc_state 深入了解堆实现 堆初始化 malloc_consolidate() 创建堆 unlink 申请内存块 _libc_malloc _int_malloc 释放内存块 _libc_free 内容来源 堆的概述 什么是堆 堆用来在程序运行时动态的分配内存,对其实就是虚拟空间里从地址向高地址增长的连续的线性区域。 堆的基本操作 void *malloc(unsigned int size):作用是在内存的动态存储区中分配一个长度为size的连续空间。此函数的返回值是分配区域的起始地址,或者说,此函数是一个指针型函数,返回的指针指向该分配域的开头位置。 void free(void *ptr):释放之前调用 calloc、malloc 或 realloc 所分配的内存空间。 堆操作背后的系统调用 brk():将数据段(.data)的最高地址指针_edata往高地址推。(从堆头开始,参数为地址) mmap():在进程的虚拟地址空间中(堆和栈中间,称为文件映射区域的地方)找一块空闲的虚拟内存。(分配大于128k) sbrk():将地址指针往高地址推。(从当前指针位置开始,参数为指针增量)

堆学习---1 宏观观察

倖福魔咒の 提交于 2019-11-29 23:48:51
动态内存的分配和释放最重要的就是malloc 和 free 这两个函数 一个是用于向操作系统索取动态的内存空间 一个是用于释放之前通过malloc或者relloc函数分配的空间。其 内部通过brk,sbrk和mmap 实现对内存的索取。 举个例子 当malloc(1024)的时候 即我们只需要1024Bytes,但是进程会向操作系统先批发一块大的内存块,又因为是主线程所以称为 main arena 它是一块非常大的 连续内存区域 紧邻在bss,即未初始化数据的下方 下面的图直接展示了它是在主线程的下方 开辟了 132KB大的空间 。之后的再次提交malloc之类的动态内存申请的时候,就会 先使用该arena直到消耗完这片连续的内存区域 。 当消耗完该块arena后,程序可以通过增加相应的 break location 即数据段高度(通过brk()和sbrk()实现) 并且会伴随着 Top Chunk 的变化 当使用free函数释放内存的时候 堆区域并不会立即被释放掉 而是会被添加这个 被free的区块到main arena的bin中 在glibc中 释放所需的数据结构跟bin这个数据结构有关 。 当之后用户再次请求动态内存的时候就不必先向操作系统提交请求,而是先从bin中找有木有合适的chunk,当区块均不合适的时候,才会向操作系统提交申请 多线程下的heap段

堆基础----2 开始入微数据结构

会有一股神秘感。 提交于 2019-11-29 23:48:22
有三个极其重要的 堆数据结构 是用于堆的管理 heap_info(Heap Header的存在) 线程即thread arena可能有 多个堆 ,虽然起初每个arena只有一个 堆段 ,但是随着malloc等函数消耗完堆空间后,新的堆会通过mmap到这个arena中,即受 这个arena的管辖!!! ,此时 这就会有个新的堆段 ,一个堆段有 一个heap_info的数据结构!!! main arena只有一个heap_info 即只有一个堆结构 所以不需要heap_info这个数据结构 所以只有thread arena需要heap_info结构来管理一到多个堆!!! malloc_state(Arena Header的存在) 一个Arena可能会有多个堆 但是 这些堆共有一个malloc_state的数据结构 ,malloc_state数据结构记录着 bins, top chunk, last remainder chunk的信息!!! malloc_chunk(Chunk Header的存在) ,一个堆由又可以划分为许多称为chunk的数据结构,每个chunk都有自己的Header头部信息 一个典型的main_arena和thread_arena的示意图如下 对于main_arena而言,Top Chunk位于heap的最高地址处 其内部每一个Chunk都有一个 malloc