C库缓存
erts_alloc框架
库摘要工具
Erlang运行时系统内部内存分配器库。性能
描述spa
erts_alloc是一个Erlang运行时系统内部内存分配器库。 erts_alloc为Erlang运行时系统提供了许多内存分配器。操作系统
分配器命令行
存在如下分配器:线程
temp_alloc对象
用于临时分配的分配器。进程
eheap_alloc
用于Erlang堆数据(例如Erlang进程堆)的分配器。
binary_alloc
用于Erlang二进制数据的分配器。
ets_alloc
用于ets数据的分配器。
driver_alloc
用于驱动程序数据的分配器。
literal_alloc
用于Erlang代码中常数项的分配器。
sl_alloc
用于预期寿命短的内存块的分配器。
ll_alloc
用于预期寿命长的内存块的分配器,例如,Erlang代码。
fix_alloc
一种快速分配器,用于某些经常使用的固定大小的数据类型。
exec_alloc
HiPE应用程序用于本机可执行代码的分配器。
std_alloc
未用于经过上述任何其余分配器分配的大多数内存块的分配器。
sys_alloc
一般,这是特定操做系统上使用的默认malloc实现。
mseg_alloc
内存段分配器。其余分配器使用它来分配内存段,而且仅在具备mmap系统调用的系统上可用。被释放的内存段在销毁以前会在段缓存中保留一段时间。分配段后,将尽量使用缓存的段,而不是建立新的段。这样能够减小进行系统调用的次数。
sys_alloc,literal_alloc和temp_alloc始终启用,不能禁用。 exec_alloc仅在须要时可用,不能禁用。 若是可用,而且启用了使用它的分配器,则始终启用mseg_alloc。 全部其余分配器均可以启用或禁用。 默认状况下,全部分配器都是启用的。 禁用分配器后,将使用sys_alloc代替禁用的分配器。
erts_alloc库的主要思想是将不一样使用的内存块分离到不一样的内存区域,以减小内存碎片。 与为那些不那么频繁分配的内存块相比,经过花更少的精力找到适合于频繁分配的内存块的性能,能够实现性能提高。
alloc_util框架
在内部,称为alloc_util的框架用于实现分配器。 sys_alloc和mseg_alloc不使用此框架,所以如下内容不适用于它们。
分配器管理多个区域,这些区域称为载体,在其中放置了内存块。 载体能够放在单独的内存段中(经过mseg_alloc分配),也能够放在堆段中(经过sys_alloc分配)。
一般,分配器建立“主多块载体”。 主多块载体永远不会释放。 主多块载体的大小由参数mmbcs的值肯定。
经过mseg_alloc分配的多块载体的大小取决于如下参数:
若是nc是分配器管理的当前多块载体数(不包括主多块载体),则当nc<=mbcgs时,此分配器分配的下一个mseg_alloc多块载体的大小约为smbcs + nc *(lmbcs-smbcs)/ mbcgs,nc> mbcgs时,为lmbcs。 可是,若是参数sbct的值大于参数lmbcs的值,则分配器可能必须建立大于参数lmbcs的值的多块载体。 经过mseg_alloc分配的单块载体大小为整页。
经过sys_alloc分配的载体大小取决于sys_alloc载体大小(ycs)参数的值。 载体的大小是知足请求的参数ycs的值的最小倍数。
空闲块的合并始终当即执行。 使用自由块中的边界标记(页眉和页脚),这使得合并的时间复杂度恒定。
可使用参数as配置分配器用于多块载波的内存分配策略。 可使用如下策略:
Best fit
策略:查找知足请求块大小的最小块。
实现:使用平衡的二进制搜索树。 时间复杂度与log N成正比,其中N是空闲块的大小数。
Address order best fit
策略:查找知足请求块大小的最小块。 若是找到多个块,则选择地址最低的那个。
实现:使用平衡的二进制搜索树。 时间复杂度与log N成正比,其中N是空闲块的数量。
Address order first fit
策略:查找地址知足要求的块大小最低的块。
实现:使用平衡的二进制搜索树。 时间复杂度与log N成正比,其中N是空闲块的数量。
Address order first fit carrier best fit
策略:找到地址最低且可知足请求的块大小的载体,而后使用“最适合”策略在该载体内找到一个块。
实现:使用平衡的二进制搜索树。 时间复杂度与log N成正比,其中N是空闲块的数量。
Address order first fit carrier address order best fit
策略:找到可知足请求块大小的最低地址的载体,而后使用“地址顺序最适合”策略在该载体中找到一个块。
实现:使用平衡的二进制搜索树。 时间复杂度与log N成正比,其中N是空闲块的数量。
Age order first fit carrier address order first fit
策略:找到能够知足请求的块大小的最先的载体,而后使用“地址顺序优先”策略在该载体中找到一个块。
实现:使用平衡的二进制搜索树。 时间复杂度与log N成正比,其中N是空闲块的数量。
Age order first fit carrier best fit
策略:找到能够知足请求的块大小的最先的载体,而后使用“最适合”策略在该载体中找到一个块。
实现:使用平衡的二进制搜索树。 时间复杂度与log N成正比,其中N是空闲块的数量。
Age order first fit carrier address order best fit
策略:找到能够知足请求的块大小的最先的载体,而后使用“地址顺序最适合”策略在该载体中找到一个块。
实现:使用平衡的二进制搜索树。 时间复杂度与log N成正比,其中N是空闲块的数量。
Good fit
策略:尝试找到最合适的,但要在有限的搜索中找到最合适的。
实现:该实现使用最大块搜索深度(在每一个列表中)的隔离的空闲列表来快速找到合适的对象。 当最大块搜索深度较小时(默认为3),此实现的时间复杂度是恒定的。 可使用参数mbsd配置最大块搜索深度。
A fit
策略:不要寻找合适的位置,仅检查一个空闲块以查看其是否知足要求。 此策略仅用于临时分配。
实现:检查空闲列表中的第一个块。 若是知足请求,则使用该请求,不然建立新的载体。 该实现具备恒定的时间复杂度。
从ERTS 5.6.1开始,仿真器拒绝在temp_alloc以外的其余分配器上使用此策略。 这是由于它只会给其余分配器带来问题。
除了上述普通分配器以外,一些预分配器还用于某些特定的数据类型。 运行系统启动时,这些预分配器会为某些数据类型预分配固定数量的内存。 只要有预分配的内存可用,就可使用它。 当没有可用的预分配内存时,将在普通分配器中分配内存。 这些预分配器一般比普通分配器快得多,但只能知足有限数量的请求。
影响erts_alloc的系统标志
警告:仅在肯定本身在作什么时才使用这些标志。 不合适的设置可能会致使严重的性能降低,甚至在运行期间的任什么时候间致使系统崩溃。
内存分配器系统标志具备如下语法:+ M <S> <P> <V>,其中<S>是标识子系统的字母,<P>是参数,而<V>是要使用的值。 能够将这些标志做为命令行参数传递给Erlang仿真器(erl(1))。
影响特定分配器的系统标志的大写字母为<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。 当使用超级载体且此标志为true时,mseg_alloc仅在超级载体中建立载体。 请注意,alloc_util框架能够建立sys_alloc载体,所以,若是要在超级载体中建立全部载体,则但愿经过传递+ Musac false来禁用sys_alloc载体的使用。 当该标志为false时,当超级载体已满时,mseg_alloc尝试在超级载体以外建立载体。
注意:并不是全部系统都支持将此标志设置为false。 该标志而后被忽略。
+MMscrfsd <amount>
设置超级载体保留的自由段描述符。 默认值为65536。此参数肯定为超级载体使用的空闲段描述符保留的内存量。 若是系统用完了空闲段描述符的保留内存,则将使用其余内存。 可是,这可能会致使碎片问题,所以您要确保这种状况永远不会发生。 能够从调用erlang:system_info({allocator,mseg_alloc})的结果的erts_mmap元组部分中检索使用的最大空闲段描述符数量。
+MMscrpm true|false
设置超级载体保留物理内存标志。 默认为true。 当此标志为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>
Top pad大小(以千字节为单位)。 这是当调用sbrk从操做系统获取更多内存时,malloc分配的额外内存量。 预设为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(默认启用)而不是<utilization>,则使用建议的非零利用率值。选择的值取决于分配器类型,而且能够在ERTS版本之间进行更改。默认为de,可是未来能够更改。
当分配器实例中的内存利用率低于所使用的利用率值时,将放弃载体。一旦放弃了载体,便不会在其中进行新的分配。当分配器实例得到增长的多块载体需求时,它首先尝试从相同分配器类型的分配器实例中获取废弃的载体。若是没法获取任何废弃的载体,则会建立一个新的空载体。提取废弃的载体后,它将充当普通载体。此功能对使用的分配策略有特殊要求。仅策略aoff,aoffcbf,aoffcaobf,ageffcaoffm,ageffcbf和ageffcaobf支持废弃的载体。
此功能还须要启用多个线程特定的实例。启用此功能时,若是还没有启用多个特定于线程的实例,则启用该功能;若是当前策略不支持废弃的载体,则启用aoffcbf策略。能够在全部基于alloc_util框架的分配器上启用此功能,但temp_alloc除外(这将毫无心义)。
+M<S>acfml <bytes>
放弃无载体最小限制。 有效的<bytes>是表示块大小限制的正整数。 载体中最大的空闲块必须至少为字节大,以便放弃该载体。 默认值为零,但未来能够更改。
另请参阅acul。
+M<S>acnl <amount>
放弃载体数量限制。 有效的<amount>是一个正整数,表明每一个分配器实例的最大被放弃载体数。 默认值为1000,实际上将禁用该限制,可是之后能够更改。
另请参阅acul。
+M<S>as bf|aobf|aoff|aoffcbf|aoffcaobf|ageffcaoff|ageffcbf|ageffcaobf|gf|af
分配策略。 如下策略是有效的:
请参阅“ alloc_util框架”一节中的分配策略说明。
+M<S>asbcst <size>
绝对单个块载体收缩阈值(以千字节为单位)。 当缩小mseg_alloc单个块载体中的某个块时,若是未使用的内存量小于此阈值,则该载体保持不变,不然缩小该载体。 另请参见rsbcst。
+M<S>atags true|false
在每一个分配的块中添加一个小标签,其中包含有关其内容和分配人的基本信息。 使用仪器模块检查此信息。
启用时,运行时开销是每一个分配一个字。 未来可能会随时更改。
对于binary_alloc和driver_alloc,默认值为true;对于其余分配器类型,默认值为false。
+M<S>e true|false
启用分配器<S>。
+M<S>lmbcs <size>
最大(mseg_alloc)多块载体大小(以千字节为单位)。 请参阅“ alloc_util框架”部分中有关如何肯定mseg_alloc多块载体的大小的说明。 在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>
从新分配老是移动。 启用后,从新分配操做或多或少会转换为分配,复制,自由序列。 这一般能够减小内存碎片,但会下降性能。
+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)多块载体大小(以千字节为单位)。 请参阅“ alloc_util框架”部分中有关如何肯定mseg_alloc多块载体的大小的说明。
+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,则分配器决不会使用alloc_util框架建立sys_alloc载体。
literal_alloc的特殊标志
+MIscs <size in MB>
literal_alloc超级载体大小(以MB为单位)。 在64位体系结构上为Erlang代码中的字面量保留的虚拟地址空间量。 默认为1024(即1 GB),一般就足够了。 该标志在32位体系结构上被忽略。
仪表标志
+M<S>atags
在每一个分配的块中添加一个小标签,其中包含有关其内容和分配人的基本信息。 请参阅+ M <S>标记以获取更完整的描述。
+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,则运行时系统进行的全部内存映射都将锁定到物理内存中。 若是设置为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)