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有两 ...
随机推荐
- python中模块导入问题(已解决)
想在python中导入request包: 无此模块,于是先安装requests包: 但是提示"Requirement already satisfied".在提示的相应目录里,找到 ...
- 【eclipse】查看jar乱码问题解决
- (转载)Ubuntu 16.04+1080Ti机器学习基本环境配置
转载自:https://blog.csdn.net/mahonesun/article/details/80808930 一.设置网络 机器有两张网卡,将当前正在使用的"有线连接1" ...
- 使用 while 循环
与 for 循环不同,while 循环会一直运行,直到给定条件不满足为止.例如,下面的 while 循环从 x=0 开始.每次循环都会检查 x<=10 是否成立.如果成立,就执行循环内部的表达式 ...
- BeginInit与EndInit的实践总结
在项目中,遇到这种情况,总结随便如下: 初始化时:添加操作,BeginInit{flag=true} 警情是一条条加入的,全部都加入后,图表再一次性生成 EndInit{flag=false} ...
- Tornado源码分析 --- Redirect重定向
“重定向”简单介绍: “重定向”指的是HTTP重定向,是HTTP协议的一种机制.当client向server发送一个请求,要求获取一个资源时,在server接收到这个请求后发现请求的这个资源实际存放在 ...
- Appium 自动化测试(3)--Appium框架与流程介绍
Appium介绍 Appium是一个移动端的自动化框架,可用于测试原生应用,移动网页应用和混合型应用,且是跨平台的.可用于IOS和Android以及firefox的操作系统.原生的应用是指用andro ...
- 移动APP测试要点总结
***微信扫一扫,关注“python测试开发圈”,了解更多测试教程!***
- C++常考面试题
1 new/delete 与 malloc/free的区别 运算符是语言自身的特性,有固定的语义,编译器知道意味着什么,由编译器解释语义,生成相应的代码. 库函数是依赖于库的,一定程度上独立于语言的. ...
- Python3 字符串(七)
字符串是 Python 中最常用的数据类型.我们可以使用引号( ' 或 " )来创建字符串. 创建字符串很简单,只要为变量分配一个值即可. python中单引号和双引号使用完全相同. 使用三 ...