技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 算法 --> hibernate使用注意事项

hibernate使用注意事项

浏览:3152次  出处信息
    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这样的基础设施。

建议继续学习:

  1. Erlang match_spec引擎介绍和应用    (阅读:4449)
  2. whatsapp深度使用Erlang有感    (阅读:4423)
  3. php-erlang    (阅读:4250)
  4. 详解JDBC与Hibernate区别    (阅读:3485)
  5. gen_tcp调用进程收到{empty_out_q, Port}消息奇怪行为分析    (阅读:3489)
  6. Erlang linkin driver用port_control方式时的一些经验分享    (阅读:2913)
  7. Erlang如何限制节点对集群的访问之net_kernel:allow    (阅读:2840)
  8. ERLANG OTP源码分析 – gen_server    (阅读:2825)
  9. erlang学习手记    (阅读:2656)
  10. gen_tcp容易误用的一点解释    (阅读:2575)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1