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的更多相关文章

  1. a simple erlang process pool analysis

    a simple erlang process pool analysis 这是一个简单的erlang进程池分析,是learn you some erlang for Great Good 里面的一个 ...

  2. Erlang Process input queue

    http://www.cnblogs.com/me-sa/archive/2011/11/05/erlang0012.html Erlang进程有自己的消息队列来保存接收到的消息,新接收到的消息放在队 ...

  3. 【oracle学习笔记02】Oracle Architecture —— Process Structure

    Oracle中有三类进程: 1 User Process 2 Server Process Server Process is a program that directly interacts wi ...

  4. Erlang库 -- 有意思的库汇总

    抄自这里 首先,库存在的目的大致可分为:1.提供便利2.尽可能解决一些痛点 首先,我们先明确一下Erlang编程语言的一些痛点(伪痛点):1,单进程问题Erlang虚拟机属于抢占式调度,抢占式调度有很 ...

  5. Erlang数据类型的表示和实现(5)——binary

    binary 是 Erlang 中一个具有特色的数据结构,用于处理大块的“原始的”字节块.如果没有 binary 这种数据类型,在 Erlang 中处理字节流的话可能还需要像列表或元组这样的数据结构. ...

  6. Erlang 虚拟机内的内存管理(Lukas Larsson演讲听写稿)

    Erlang核心开发者Lukas Larsson在2014年3月份Erlang Factory上的一个演讲详细介绍了Erlang内存体系的原理以及调优案例: http://www.erlang-fac ...

  7. erlang二进制

    在Erlang中写处理二进制数据的代码是洋溢着幸福感的,它对于二进制强大的表现力甚至能让你忘掉了它种种不便,今天我们说说Erlang的二进制数据处理. Erlang中bit string代表无类型的内 ...

  8. 转载:【原译】Erlang构建和匹配二进制数据(Efficiency Guide)

    转自:http://www.cnblogs.com/futuredo/archive/2012/10/19/2727204.html Constructing and matching binarie ...

  9. erlang二进制数据垃圾回收机制

    erlang二进制数据在内存中有两种存在形式,当数据大小不到 64 bytes,就直接存在进程堆内.假设超过了64 bytes.就被保存到进程外的共享堆里,能够给节点内全部进程共享. erlang有两 ...

随机推荐

  1. ubuntu如何使zsh替换bash

    答:  1.安装zsh sudo apt-get install zsh 2.zsh替换bash sudo chsh -s `which zsh` 3.重启 (注:重启后打开一个终端会自动进入zsh的 ...

  2. 一些常用的JavaScript正则表达式

    1.正数,最多n位小数 /^(([1-9]\d*(\.\d{1,n})?)|(0\.\d{1,n}))$/ 2.手机号码 /^1[34578]\d{9}$/

  3. [BZOJ1257][CQOI2007]余数之和

    题目大意 给你 \(n, k\),计算 $ \sum_{i=1}^n k \bmod i$ 解析 注意到 $ k\bmod i=k-[k/i] \times i$ 则上式等于 $ n \times k ...

  4. POJ 2115 C Looooops(模线性方程)

    http://poj.org/problem?id=2115 题意: 给你一个变量,变量初始值a,终止值b,每循环一遍加c,问一共循环几遍终止,结果mod2^k.如果无法终止则输出FOREVER. 思 ...

  5. 一年25个里程碑!免疫疗法“战胜”癌症,靠的是实力(5篇Science、6篇Nature )--转载

    近几年,免疫疗法的成功使癌症治疗进入了新的时代.无论是科研界,还是商业界,都丝毫没有掩饰对这一领域的热情.2016年,Cell杂志公布的年度十大最佳论文中,免疫疗法占两席.事实上,这两项成果只是去年癌 ...

  6. C++中ceil、floor和round的区别

    Math类中提供了三个与取整有关的方法:ceil,floor,round,这些方法的作用于它们的英文名称的含义相对应 1.ceil的英文意义是天花板,该方法就表示向上取整,Math.ceil(11.3 ...

  7. kissy初体验-waterfall

    目录: 1. 功能介绍 2. waterfall样例展示 3. 使用说明 4. 遇到过的问题 5. 总结 1. 功能介绍 现在越来越多的网站开始瀑布流方式布局,瀑布流式布局(百度百科:瀑布流),是比较 ...

  8. RabbitMQ 消息传递的可靠性

    生产者保证消息可靠投递 消费者保证消息可靠消费 RabbitMQ持久化 参考:https://blog.csdn.net/RobertoHuang/article/details/79605185

  9. hdu1846巴什博弈

    巴什博弈:只有一堆n个物品,两个人轮流从这堆物品中取物, 规定每次至少取一个,最多取m个.最后取光者得胜. 结论:只要不能整除,那么必然是先手取胜,否则后手取胜. #include<map> ...

  10. bzoj-3195-状压dp

    3195: [Jxoi2012]奇怪的道路 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 600  Solved: 395[Submit][Statu ...