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有两 ...
随机推荐
- 205315Java实验二实验报告
实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验步骤 (一)单元测试 用程序解决问题时,要会写三种码: ...
- Android移动软件开发总结
目录 Android实验参考目录 常用知识点总结 服务绑定bind Service ThreadService使用总结 Service用法总结 Broadcast Receiver用法 Intent使 ...
- UVa 1662 Brackets Removal
https://vjudge.net/problem/UVA-1662 题意: 给出一个序列,判断序列中哪些括号是可以去掉的,只可以改变符号.输出括号最少的序列. 思路: 感觉这道题目就是写起来繁琐了 ...
- linux 系统忘记登录密码
linux6/6.5再启动时,按e ->在输入行最后面 输入空格 再输入single ->启动设置密码即可 单用户模式 在centos7需要 按e -> 然后滚动列表,找到ro(ro ...
- Codeforces Round #401 (Div. 2) A,B,C,D,E
A. Shell Game time limit per test 0.5 seconds memory limit per test 256 megabytes input standard inp ...
- shell 使用ping测试网络
能ping通返回1,不能返回0 ping -c 192.168.1.1 | grep '0 received' | wc -l
- eclipse下maven springMVC 整合 mybatis
参考文档:http://blog.csdn.net/zhshulin/article/details/37956105 1.搭建maven工程,具体参见我另一篇博客:http://www.cnbl ...
- $state和$rootScope.$on($stateChangeStart)
这两者的区别:请看博客:http://stackoverflow.com/questions/32680292/angularjs-state-and-rootscope-onstatechanges ...
- 101. Symmetric Tree -- 判断树结构是否对称
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For e ...
- iOS UI-应用管理(使用Cell模板)
一.Model // // BWApp.h // IOS_0112_应用管理 // // Created by ma c on 16/1/12. // Copyright (c) 2016年 博文科技 ...