hibernate使用注意事项
erlang:hibernate文档参考这里
erlang:hibernate(Module, Function, Args)
Types:
Module = Function = atom()
Args = [term()]
Puts the calling process into a wait state where its memory allocation has been reduced as much as possible, which is useful if the process does not expect to receive any messages in the near future.
The process will be awaken when a message is sent to it, and control will resume in Module:Function with the arguments given by Args with the call stack emptied, meaning that the process will terminate when that function returns. Thus erlang:hibernate/3 will never return to its caller.
If the process has any message in its message queue, the process will be awaken immediately in the same way as described above.
In more technical terms, what erlang:hibernate/3 does is the following. It discards the call stack for the process. Then it garbage collects the process. After the garbage collection, all live data is in one continuous heap. The heap is then shrunken to the exact same size as the live data which it holds (even if that size is less than the minimum heap size for the process).
If the size of the live data in the process is less than the minimum heap size, the first garbage collection occurring after the process has been awaken will ensure that the heap size is changed to a size not smaller than the minimum heap size.
Note that emptying the call stack means that any surrounding catch is removed and has to be re-inserted after hibernation. One effect of this is that processes started using proc_lib (also indirectly, such as gen_server processes), should use proc_lib:hibernate/3 instead to ensure that the exception handler continues to work when the process wakes up.
请注意最后最后一句话, 由于hibernate把堆栈全部清掉了,在wakeup的时候,如果之前有try catch需要重新构建, 这就是proc_lib考虑周到的地方。
首先我们先看下try catch堆栈的情况,看例子:
$ cat try_stack.erl -module(try_stack). -compile(export_all). loop()-> receive _-> loop() end. x()-> register(x, self()), loop(). y()-> register(y, self()), try loop() catch _:_ ->ok end. start()-> spawn(fun x/0), spawn(fun y/0), ok. $ erlc try_stack.erl $ erl -s try_stack Erlang (BEAM) emulator version 5.6.5 1 [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.6.5 (abort with ^G) 1> BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution A
按下大写的A, 产生crashdump文件,用CrashDumpViewer看到进程的堆栈情况,可以看到下图:
从图中我们知道,try catch 是往堆栈里面都压入了出错时候的返回地址,而普通的函数没有压入任何东西。
确认了这个问题,就很容易理解proc_lib:hibernate的实现了,我们看代码:
%% proc_lib.erl:L192 hibernate(M, F, A) when is_atom(M), is_atom(F), is_list(A) -> erlang:hibernate(?MODULE, wake_up, [M, F, A]). wake_up(M, F, A) when is_atom(M), is_atom(F), is_list(A) -> try apply(M, F, A) catch Class:Reason -> exit_p(Class, Reason) end.
总结:标准库的东西总是会考虑比较周到,我们尽量多用gen_server,proc_lib这样的基础设施。
建议继续学习:
- Erlang match_spec引擎介绍和应用 (阅读:4535)
- whatsapp深度使用Erlang有感 (阅读:4581)
- php-erlang (阅读:4312)
- 详解JDBC与Hibernate区别 (阅读:3537)
- gen_tcp调用进程收到{empty_out_q, Port}消息奇怪行为分析 (阅读:3544)
- Erlang linkin driver用port_control方式时的一些经验分享 (阅读:2968)
- Erlang如何限制节点对集群的访问之net_kernel:allow (阅读:2979)
- ERLANG OTP源码分析 – gen_server (阅读:2859)
- erlang学习手记 (阅读:2697)
- gen_tcp容易误用的一点解释 (阅读:2638)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:Yu Feng 来源: Erlang非业余研究
- 标签: erlang hibernate
- 发布时间:2011-10-04 17:56:48
- [46] 界面设计速成
- [43] Oracle MTS模式下 进程地址与会话信
- [42] IOS安全–浅谈关于IOS加固的几种方法
- [42] android 开发入门
- [42] 视觉调整-设计师 vs. 逻辑
- [40] 图书馆的世界纪录
- [39] 【社会化设计】自我(self)部分――欢迎区
- [39] 如何拿下简短的域名
- [37] 程序员技术练级攻略
- [35] 读书笔记-壹百度:百度十年千倍的29条法则