Erlang process structure -- refc binary
Erlang 的process 是虚拟机层面的进程,每个Erlang process 都包括一个 pcb(process control block), 一个stack 以及私有heap .
这部分的姿势, 在各种论文中都有提到. 网上也有各种各样的解读,包括但不仅限于:
1, http://fengchj.com/?p=2255
2, http://blog.csdn.net/mycwq/article/details/26613275
那么, 从现有的资料,可以看出,正因为在Erlang 虚拟机内部,每个进程(process)都有自己的PCB,自己的stack和自己的私有heap(注意,现在的Erlang还不支持shared heap). Erlang的 GC 并不是"stop whe whole world",只是针对于每一个进程而言的.
Each process’ heap is garbage collected independently. Thus when one scheduler is collecting garbage for a process, other schedulers can keep executing other processes.
但是,并不是所有的数据都是private heap 的, 同样也有一些数据, 是存放在shared 区域的.
In addition, binaries larger than 64 bytes are stored in a common heap shared by all processes. ETS tables are also stored in a common heap.
binaries larger than 64 bytes, 也就是大家常说到的refc binaries, 这部分的解读网上也有很多, 举个栗子:
1, http://blog.csdn.net/zhongruixian/article/details/9450361
这个时候, Erlang的GC,就有可能遇到一些问题了,因为Erlang 虚拟机对待这部分shared memory 的GC,是采取引用计数器的.
然后,看一段完整的小程序:
-module(refc_binary_test). -export ([start/0,
handle_big_binary/1]). start() ->
Me = erlang:self(),
erlang:spawn(?MODULE, handle_big_binary, [Me]),
receive
{ok, C} ->
io:format("----- get_bin_address C : ~p~n", [test:get_bin_address(C)]),
io:format("------- handled ~p~n", [erts_debug:get_internal_state({binary_info, C})]),
timer:sleep(1000000),
C;
_ ->
error
after 10000 ->
error
end. handle_big_binary(Me) ->
A = binary:copy(<<1>>, 1024*1024),
io:format("----- get_bin_address A : ~p~n", [test:get_bin_address(A)]),
io:format("------- resource ~p~n", [erts_debug:get_internal_state({binary_info, A})]),
<<B:1/binary, _/binary>> = A,
io:format("----- get_bin_address B : ~p~n", [test:get_bin_address(B)]),
erlang:send(Me, {ok, B}).
熟悉Ejabberd 的人,对这一模式应该不会陌生, handle_big_binary/1 的execute 进程可以映射到ejabberd 中的ejabberd_receiver module, start/0 可以看做是ejabberd 中的c2s 进程. ok, 和TCP socket 直接关联的进程会解析socket 数据, 解析完成后, 交给实际处理进程.
> refc_binary_test:start().
----- get_bin_address A : "bin: size=1048576, ptr=0x18fc0040"
------- resource {refc_binary,,{binary,},}
----- get_bin_address B : "bin: size=1, ptr=0x18fc0040"
----- get_bin_address C : "bin: size=1, ptr=0x18fc0040"
------- handled {refc_binary,,{binary,},}
那么, 这个时候, 可以看到 变量 C 还占据这'{binary,1048576}' 的数据(1048576 是binary 的orig_size),即便是handle_big_binary 的进程在send/2 之后就已经结束生命. 然后, 可以放大一下这个小问题:
> [proc_lib:spawn(refc_binary_test, start, []) || _ <- lists:seq(, )].
然后就会看到, beam.smp 进程已经占用了超过了1G的内存:(.
那,how fix ?
在binary module 中,referenced_byte_size/1 func:
If a binary references a larger binary (often described as being a sub-binary), it can be useful to get the size of the actual referenced binary. This function can be used in a program to trigger the use of copy/1. By copying a binary, one might dereference the original, possibly large, binary which a smaller binary is a reference to.
store(Binary, GBSet) ->
NewBin =
case binary:referenced_byte_size(Binary) of
Large when Large > 2 * byte_size(Binary) ->
binary:copy(Binary);
_ ->
Binary
end,
gb_sets:insert(NewBin,GBSet).
然后, 在看binary:copy/1 的function 描述:
This function will always create a new binary, even if N = 1. By using copy/1 on a binary referencing a larger binary, one might free up the larger binary for garbage collection.
这个时候再去refc_binary_test:start(). 就不会出现上面的问题了.
总结:
1, refc binary 的存储使用的是shared memory;
2, 对于refc binary 的GC 策略是引用计数器;
3, refc binary 的内存分配是连续的.
Erlang process structure -- refc binary的更多相关文章
- a simple erlang process pool analysis
a simple erlang process pool analysis 这是一个简单的erlang进程池分析,是learn you some erlang for Great Good 里面的一个 ...
- Erlang Process input queue
http://www.cnblogs.com/me-sa/archive/2011/11/05/erlang0012.html Erlang进程有自己的消息队列来保存接收到的消息,新接收到的消息放在队 ...
- 【oracle学习笔记02】Oracle Architecture —— Process Structure
Oracle中有三类进程: 1 User Process 2 Server Process Server Process is a program that directly interacts wi ...
- Erlang库 -- 有意思的库汇总
抄自这里 首先,库存在的目的大致可分为:1.提供便利2.尽可能解决一些痛点 首先,我们先明确一下Erlang编程语言的一些痛点(伪痛点):1,单进程问题Erlang虚拟机属于抢占式调度,抢占式调度有很 ...
- Erlang数据类型的表示和实现(5)——binary
binary 是 Erlang 中一个具有特色的数据结构,用于处理大块的“原始的”字节块.如果没有 binary 这种数据类型,在 Erlang 中处理字节流的话可能还需要像列表或元组这样的数据结构. ...
- Erlang 虚拟机内的内存管理(Lukas Larsson演讲听写稿)
Erlang核心开发者Lukas Larsson在2014年3月份Erlang Factory上的一个演讲详细介绍了Erlang内存体系的原理以及调优案例: http://www.erlang-fac ...
- erlang二进制
在Erlang中写处理二进制数据的代码是洋溢着幸福感的,它对于二进制强大的表现力甚至能让你忘掉了它种种不便,今天我们说说Erlang的二进制数据处理. Erlang中bit string代表无类型的内 ...
- 转载:【原译】Erlang构建和匹配二进制数据(Efficiency Guide)
转自:http://www.cnblogs.com/futuredo/archive/2012/10/19/2727204.html Constructing and matching binarie ...
- erlang二进制数据垃圾回收机制
erlang二进制数据在内存中有两种存在形式,当数据大小不到 64 bytes,就直接存在进程堆内.假设超过了64 bytes.就被保存到进程外的共享堆里,能够给节点内全部进程共享. erlang有两 ...
随机推荐
- JQuery实现锚点平滑滚动
一般使用锚点来跳转到页面指定位置的时候,会生硬地立即跳转到指定位置,但是有些时候我们想要平滑地过渡到指定的位置,那么可以使用JQuery简单的实现这个效果: 比如,这里我们将通过点击<a> ...
- POJ3278_Catch that cow
一个简单的bfs题. 用结构体的目的在于保存bfs到达此处时走的步数. 不多言,上AC代码: //18:18 #include<iostream> #include<cstdio&g ...
- JS+Canvas的棋盘游戏和Java的动态结合
二维数组的题做了有几个了,感觉很有趣,随后想到想做一个五子棋的游戏. 因为前端知识匮乏,但感觉只是Java中去用二维数组做的话还是不太难的. 首先生成15*15的棋盘,(先不考虑前后端交互),其后Ha ...
- JAVA基础之复识一
JAVA不单是一门计算机编程语言,而且还是一种基于WEB的全方位软件开发技术, java特定运行平台及关键特点 java开发工具包的安装,配置与应用 java语言的基本概念 java面向对象编程 ja ...
- hdu 4549 M斐波那契数列 矩阵快速幂+欧拉定理
M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Problem ...
- RHEL6.5恢复root密码
1.开机上下键停留在如下界面,键盘输入小写e: 2.选择如下选项,并输入小写e: 3.输入1,回车进入单用户模式: 4.键盘输入小写b,进行启动: 5.进入到单用户模式: 6.修改root用户密码,并 ...
- Java Spring-Bean
2017-11-06 18:59:30 Bean初始化和销毁方法 配置初始化和销毁的方法:* init-method=”setup”* destroy-method=”teardown”执行销毁的时候 ...
- git关于 LF 与 CRLF
问题描述: 今天在idea上配置好了git操作到push,目测都没遇到什么问题. 但是再次点击提交按钮的时候,仍然提示我所有的文件都是需要提交的(我的主题中蓝色显示) 然而本地并无改动,在提交窗口得到 ...
- sshpass使用
sshpass的使用方法 应用范围:可以在命令行直接使用密码来进行远程连接和远程拉取文件. 使用前提:对于未连接过的主机.而又不输入yes进行确认,需要进行sshd服务的优化: # vim /etc/ ...
- 个人知识管理系统Version1.0开发记录(08)
切入点 前面,我们已经搭建好了web端的一种基本结构,需要进一步定位的主要问题有三点: 1.界面的选择和确定,用extjs做的初步样式,进一步改动为jqueryUI/html,再进一步改变为HTML5 ...