erts_alloc
erts_alloc
C库
erts_alloc
库摘要
Erlang运行时系统内部内存分配程序库。
描述
erts_alloc
是一个Erlang运行时系统内存分配器库。erts_alloc
为Erlang运行时系统提供了许多内存分配器。
分配器
有下列分配器:
temp_allocAllocator用于临时allocations.eheap_allocAllocator用于Erlang堆数据,如Erlang进程堆。 binary_allocAllocator用于Erlang二进制data.ets_allocAllocator用于ets data.driver_allocAllocator用于驱动程序data.literal_allocAllocator用于Erlang中的常量项code.sl_allocAllocator用于预期寿命短的内存块.ll_allocAllocator用于预期的内存块例如,用于某些常用固定大小数据类型的Erlang code.fix_allocA快速分配器。HiPE应用程序用于特定体系结构上的本机可执行代码(x86_64).std_allocAllocator用于大多数未分配内存块的.exec_allocAllocator通过上面描述的任何其他分配器.sys_alloc这通常是特定OS.mseg_allocA内存段分配器上使用的默认malloc实现。它由其他分配器用于分配内存段,并且仅在具有mmap系统调用的系统上可用。被释放的内存段在被销毁之前会在段缓存中保留一段时间。分配段时,如果可能的话使用缓存段,而不是创建新段。这可以减少系统调用的次数。
sys_alloc
与literal_alloc
始终启用并且不能禁用。exec_alloc
仅在需要时才可用并且不能被禁用。mseg_alloc
如果可用并且启用了使用它的分配器,则始终处于启用状态。所有其他分配器都可以为enabled or disabled
。默认情况下,所有分配器都已启用。分配器被禁用时,将sys_alloc
被使用,而不是被禁用的分配器。
主要思想erts_alloc
库是将不同使用的内存块分离到不同的内存区域,以减少内存碎片。与那些分配频率较低的内存块相比,在寻找适合于频繁分配的内存块方面所付出的努力较少,就可以获得性能上的提高。
alloc_util框架
内部调用的框架alloc_util
用于实现分配器。sys_alloc
与mseg_alloc
不使用此框架,所以下面也不能
适用于他们。
分配器管理多个区域,称为载体,其中放置了存储器块。 载体要么放置在单独的内存段中(通过mseg_alloc分配),要么放在堆段中(通过sys_alloc分配)。
- 多块载波用于存储多个块。
- 单块载波用于存储一个块。
- 大于单块载波阈值(
sbct
)参数值的块放置在单块载体中。
- 小于参数值的块
sbct
放置在多块载体中。
通常分配器会创建一个“主多载波载波”。主多块载体永远不会被释放。主多载波载波的大小由参数值决定mmbcs
。
mseg_alloc
根据以下参数决定分配的多块载波的大小:
- 最大多块载体大小(
lmbcs
)的值
- 最小的多块载体大小(
smbcs
)
- 多块载体生长阶段(
mbcgs
)
如果nc是由分配器管理的当前多块载波数量(主多块载波除外),则当由此分配器分配的下一个mseg_alloc多块载波大小大约为smbcs + nc *(lmbcs-smbcs)/ mbcgs时,当nc <= 当nc> mbcgs时,mbcgs和lmbcs。 如果参数sbct的值大于参数lmbcs的值,则分配器可能必须创建大于参数lmbcs的值的多块载体。 通过mseg_alloc分配的单块载体大小为整个页面。
通过sys_alloc分配的载波大小是根据sys_alloc载波大小(ycs)参数的值决定的。 载体的大小是满足请求的参数ycs的值的最小倍数。
空闲块的合并总是立即执行。使用空闲块中的边界标记(页眉和页脚),这使合并时间复杂度不变。
分配器用于多块载体的内存分配策略可以使用参数进行配置as
。以下策略可用:
最佳配合
策略:找到满足请求块大小的最小块。
实现:使用平衡的二进制搜索树。时间复杂度与logN成正比,其中N是自由块的大小。
地址顺序最适合
策略:找到满足请求块大小的最小块。如果找到多个块,请选择地址最低的块。
实现:使用平衡的二进制搜索树。时间复杂度与logN成正比,其中N是自由块的数目。
地址顺序优先匹配
策略:找到地址最低的块,以满足所请求的块大小。
实现:使用平衡的二进制搜索树。时间复杂度与logN成正比,其中N是自由块的数目。
地址顺序优先匹配载波最佳匹配
策略:找到载体
使用能够满足所请求的块大小的最低地址,然后使用“最佳匹配”策略在该载波中找到一个块。
实现:使用平衡的二进制搜索树。时间复杂度与logN成正比,其中N是自由块的数目。
地址顺序优先匹配 载波地址顺序最佳匹配
策略:找到载体
使用能够满足请求块大小的最低地址,然后使用“地址顺序最佳匹配”策略在该载波中找到一个块。
实现:使用平衡的二进制搜索树。时间复杂度与logN成正比,其中N是自由块的数目。
良好配合
策略:尝试找到最合适的,但满足于在有限的搜索中发现的最佳匹配。
实现:实现使用最大块搜索深度(在每个列表中)的分离空闲列表来快速找到合适的结果。当最大块搜索深度较小时(默认为3),此实现的时间复杂度是恒定的。最大程序段搜索深度可以使用参数进行配置mbsd
。
合适匹配
策略:不要寻找匹配,只检查一个自由块,看看它是否满足要求。这一战略仅用于临时拨款。
实现:检查自由列表中的第一个块。如果满足请求,则使用该请求,否则创建新的载体。实现的时间复杂度是不变的。
从ERTS 5.6.1开始,仿真器拒绝在其他分配器上使用该策略temp_alloc
。这是因为它只会导致其他分配器出现问题。
除了上面描述的普通分配器之外,一些预分配器用于某些特定的数据类型。这些预分配器在运行系统启动时为某些数据类型预先分配固定数量的内存。只要预先分配的内存可用,就可以使用它。当没有预分配的内存时,内存将在普通的分配器中分配。这些预分配器通常比普通分配器快得多,但只能满足有限数量的请求。
系统标志影响erts_alloc
警告
只有当你确定自己在做什么时,才使用这些标志。不适当的设置会导致严重的性能下降,甚至在运行期间的任何时候都会导致系统崩溃。
内存分配器系统标志具有以下语法:+M<S><P> <V>,其中<S>是标识子系统的字母,<P>是参数,<V>是要使用的值。这些标志可以erl(1)作为命令行参数传递给Erlang仿真器()。
影响特定分配器的系统标志具有大写字母<S>。分配器使用以下字母:
B: binary_alloc
D: std_alloc
E: ets_alloc
F: fix_alloc
H: eheap_alloc
I: literal_alloc
L: ll_alloc
M: mseg_alloc
R: driver_alloc
S: sl_alloc
T: temp_alloc
X: exec_alloc
Y: sys_alloc
用于配置mseg_alloc的标志
+MMamcbf <size>
绝对最大缓存不合适(以千字节为单位)。如果内存段缓存中的某个段的大小超过了所请求的大小且该值超过了此参数的值,则该段不会被重用。默认为4096
。
+MMrmcbf <ratio>
相对最大缓存不合适度(百分比)。如果内存段高速缓存的大小超过所请求的大小,并且所请求大小的相对最大高速缓存不良适配百分比超过了该大小,则内存段高速缓存中的某个段不会重用 默认为20
。
+MMsco true|false
设置超级运营商专用标志。 默认为true。 当使用超级运营商并且该标志为真时,mseg_alloc仅在超级运营商中创建运营商。 请注意,alloc_util框架可以创建sys_alloc运营商,所以如果您希望所有运营商都在超级运营商中创建,您因此希望禁止使用sys_alloc运营商,同时也将+ Musac传递给false。 当该标志为假时,当超载波满时,mseg_alloc尝试在超级载波之外创建载波。
注
将此标志设置false
为在所有系统上都不受支持。该标志然后被忽略。
+MMscrfsd <amount>
设置超级载波保留的空闲段描述符。 默认为65536.此参数确定为超级运营商使用的空闲段描述符保留的内存量。 如果系统用完空闲的段描述符的保留内存,则使用其他内存。 但是,这可能会导致碎片问题,所以您希望确保这种情况永远不会发生。 可以从调用erlang:system_info({allocator,mseg_alloc})的结果的erts_mmap元组部分中检索使用的最大空闲段描述符。
+MMscrpm true|false
设置超级运营商预留物理内存标志。 默认为true。 当这个标志为真时,物理内存在创建时一次为整个超级载体保留。 保留之后保持不变。 当此标志设置为false时,创建时只为超级运营商保留虚拟地址空间。 系统尝试在超级运营商的运营商创建时预留物理存储器,并试图在超级运营商的运营商破坏后保留物理存储器。
注
物理内存的保留意味着高度依赖于操作系统,以及它如何配置。例如,Linux上不同的内存过量使用设置会彻底改变这种行为。
将此标志设置为false可能不被所有系统支持。 该标志然后被忽略。
+MMscs <size in MB>
设置超级载体大小(以MB为单位)。默认为0
,即默认禁用超级运营商。超级载体是虚拟地址空间中的一个大的连续区域。mseg_alloc
如果它存在,总是试图在超级运营商中创建新的运营商。请注意,该alloc_util
框架可以创建sys_alloc
运营商。有关更多信息,请参阅+MMsco
。
+MMmcs <amount>
最大缓存段。内存段缓存中存储的最大内存段数。有效范围是[0, 30]
。默认为10
。
用于配置sys_alloc的标志
+MYe true
启用sys_alloc
。
注
sys_alloc
不能被禁用。
+MYm libc
malloc
库使用。只有libc
可用。libc
支持标准libc
malloc
实施。默认libc
使用。
+MYtt <size>
修剪阈值大小(以千字节为单位)。 这是由malloc保存的最高可用内存量(由sbrk分配)(未发布到操作系统)。 当堆顶部的可用内存量超过修剪阈值时,malloc释放它(通过调用sbrk)。 修剪阈值以千字节为单位指定。 默认为128。
注
只有在仿真器与GNU C库链接并使用其实现时,该标志才有效malloc
。
+MYtp <size>
顶部垫大小(以千字节为单位)。这是调用malloc
何时分配的额外内存量,sbrk
以从操作系统获取更多内存。默认为0
。
注
只有在仿真器与GNU C库链接并使用其实现时,该标志才有效malloc
。
基于alloc_util配置分配器的标志
如果将u用作子系统标识符(即<S> = u),则会影响基于alloc_util的所有分配器。 如果B,D,E,F,H,L,R,S或T用作子系统标识符,则只有特定的分配器标识符生效。
+M<S>acul <utilization>|de
放弃运营商使用限制。有效值<utilization>是[0, 100]表示百分比的范围内的整数。当使用率值> 0时,允许分配器实例放弃多块载体。如果de(默认启用)通过而不是a <utilization>,则使用推荐的非零利用率值。所选值取决于分配器类型,可以在ERTS版本之间进行更改。默认为de,但将来可以更改。
当分配器实例中的内存利用率低于所使用的利用率值时,运营商被放弃。一旦承运人被放弃,其中不会有新的分配。当分配器实例获得增加的多块载体需求时,它首先尝试从相同分配器类型的分配器实例中获取被抛弃的载波。如果没有被遗弃的承运人可以被提取,它会创建一个新的空承运人。当一个被遗弃的承运人被取走时,它将作为一个普通的承运人。这个功能对allocation strategy
使用过程有特殊要求。只有战略aoff
,aoffcbf
并且aoffcaobf
支持被遗弃的运营商。
此功能也需要multiple thread specific instances
启用。启用此功能时,如果尚未启用多个线程特定的实例,则启用该aoffcbf
策略,如果当前策略不支持放弃的运营商,则启用该策略。alloc_util
除了temp_alloc
(这是毫无意义的),所有基于框架的分配器都可以启用此功能。
+M<S>as bf|aobf|aoff|aoffcbf|aoffcaobf|gf|af
分配策略。以下策略是有效的:
bf
(最合适)
aobf
(地址顺序最合适)
aoff
(地址顺序优先)
aoffcbf
(地址顺序首先适合载体最适合)
aoffcaobf
(地址顺序第一合适的运营商地址顺序最合适)
gf
(很合适)
af
(合适)
请参阅部分中的分配策略说明The alloc_util Framework
。
+M<S>asbcst <size>
绝对单块载波收缩阈值(以千字节为单位)。当位于单块mseg_alloc
载体中的块收缩时,如果未使用的内存量小于此阈值,则载体保持不变,否则载体会收缩。另见rsbcst
。
+M<S>e true|false
启用分配器<S>...
+M<S>lmbcs <size>
最大(mseg_alloc)多块载体大小(以千字节为单位)。请参阅关于如何确定mseg_alloc多块载体尺寸的说明The alloc_util Framework。在32位Unix风格的操作系统上,此限制不能设置为> 128 MB。
+M<S>mbcgs <ratio>
(mseg _alloc)多块载体成长阶段。 请参阅“alloc_util框架”一节中有关如何确定mseg _alloc多分区载体大小的说明。
+M<S>mbsd <depth>
最大块搜索深度。只有在为分配器选择了合适的策略时,此标志才有效<S>。当使用合适的策略时,空闲块被放置在分离的空闲列表中。每个自由列表包含特定范围内的大小块。最大块搜索深度在搜索满足请求的合适块期间在自由列表中检查要检查的块的最大数量的限制。
+M<S>mmbcs <size>
主多块载波大小。设置分配器的主多块载波的大小。<S>主多块载波通过sys_alloc永远不会被放弃。
+M<S>mmmbc <amount>
最大mseg_alloc多块载波。 分配器<S>通过mseg_alloc分配的多块载体的最大数量。 达到此限制时,将通过sys_alloc分配新的多分区载波。
+M<S>mmsbc <amount>
最大mseg_alloc单块载体。 通过分配器<S>通过mseg_alloc分配的单块载体的最大数量。 达到此限制时,将通过sys_alloc分配新的单分区载波。
+M<S>ramv <bool>
Realloc总是移动。启用后,重新分配操作或多或少会转换为分配,复制,自由顺序。这通常会减少内存碎片,但会降低性能。
+M<S>rmbcmt <ratio>
相对多块载波移动阈值(百分比)。当位于多块载体中的块收缩时,如果返回的内存大小与先前大小相比大小超过此阈值,则会移动该块,否则块将在当前位置收缩。
+M<S>rsbcmt <ratio>
相对单块载波移动阈值(百分比)。当位于单块载波中的块缩小到小于参数值的大小时sbct
,如果未使用的存储器的比率小于该阈值,则该块在单块载波中保持不变,否则将其移入多块载波中。
+M<S>rsbcst <ratio>
相对单块载波收缩阈值(百分比)。当位于单块mseg_alloc
载波中的块收缩时,如果未使用的存储器的比率小于此阈值,则载波保持不变,否则载波会收缩。另见asbcst
。
+M<S>sbct <size>
单块载波门限(以千字节为单位)。大于此阈值的块放置在单块载体中。小于此阈值的块放置在多块载体中。在32位Unix样式的操作系统上,该阈值不能设置> 8 MB。
+M<S>smbcs <size>
最小(mseg_alloc
)多块载体大小(以千字节为单位)。请参阅关于如何确定mseg_alloc
多块载体尺寸的说明The alloc_util Framework
。
+M<S>t true|false
分配器的多个线程特定实例。此选项仅对具有SMP支持的运行时系统有效。具有SMP支持的运行时系统上的缺省行为是NoSchedulers+1
实例。每个调度程序都使用自己的无锁实例,而其他线程使用一个公共实例。
在erts 5.9之前,可以配置比调度程序更少的线程特定实例。然而,这已经不可能了。
用于配置alloc_util的标志
所有基于alloc_util
已经生效。
+Muycs <size>
sys_alloc
载体大小。载波通过sys_alloc
的大小是sys_alloc
载体大小。然而,对于在内存短缺期间分配的主要多块载波和载波,情况并非如此。
+Mummc <amount>
最大的mseg_alloc载体。 放置在不同存储段中的载体的最大数量。 达到此限制时,将新的载体放入从sys_alloc检索的内存中。
+Musac <bool>
允许sys_alloc运营商。 默认为true。 如果设置为false,则sys_alloc运营商永远不会由使用alloc_util框架的分配器创建。
用于literal_alloc的特殊标志
+MIscs <size in MB>
literal_alloc超级载体大小(以MB为单位)。 虚拟地址空间的数量在64位体系结构中的Erlang代码中为字面项保留。 默认为1024(即1 GB),通常就足够了。 该标志在32位架构上被忽略。
exec_alloc的特殊标志
+MXscs <size in MB>
exec_alloc
超级载体大小(以MB为单位)。为特定体系结构(x86_64)上的应用程序使用的本机可执行代码保留的虚拟
地址空间量HiPE
。默认为512
。
仪表标志
+Mim true|false
模拟器保存了当前分配的映射。分配映射可以通过模块检索instrument(3)
。+Mim true
意味着+Mis true
。+Mim true
是相同的标志-instr
在erl(1)
。
+Mis true|false
仿真器保存分配内存的状态。分配状态可以通过模块检索instrument(3)
。
+Mit X
保留以供将来使用。千万不能
使用此标志。
注
当启用仿真器的检测时,仿真器使用更多的内存并运行得更慢。
其他标志
+Mea min|max|r9c|r10b|r11b|config
选项:
min
禁用所有可以禁用的分配器。
max
启用所有分配器(默认)。
r9c|r10b|r11b
配置所有分配器在各自的Erlang / OTP版本中配置。这些最终将被删除。
config
禁用在创建分配器配置时无法启用的功能erts_alloc_config(3)
。
注
该选项仅在运行时使用erts_alloc_config(3)
,不能
在使用创建的配置时使用。
+Mlpm all|no
锁定物理内存。 默认为否,即没有物理内存被锁定。 如果设置为all,运行时系统所做的所有内存映射都将锁定到物理内存中。 如果设置为全部,则如果不支持此功能,用户没有足够的权限,或者用户不被允许锁定足够的物理内存,则运行时系统无法启动。 如果用户限制了锁定内存的数量,则运行系统也会因内存不足而失败。
注记
这里只介绍了一些默认值。有关当前使用的设置和分配器的当前状态的信息,请参阅erlang:system_info(allocator)
和erlang:system_info{allocator, Alloc})。
注
大多数这些标志都是高度依赖于实施的,可以在不事先通知的情况下进行更改或删除。
erts_alloc
没有义务严格使用已传递给它的设置(它甚至可以忽略它们)。
该erts_alloc_config(3)
工具可用于帮助创建erts_alloc
适用于有限数量的运行时方案的配置。
另见
erl(1)
,erlang(3)
,erts_alloc_config(3)
,instrument(3)