diff options
author | Raimo Niskanen <[email protected]> | 2016-04-26 16:49:47 +0200 |
---|---|---|
committer | Raimo Niskanen <[email protected]> | 2016-04-27 09:01:00 +0200 |
commit | 471a50ef1391f6399664f8b992da7a67c32c8b86 (patch) | |
tree | d68e1a3ab621ee15b39422dd1452a3e5270c2edc /system/doc/design_principles | |
parent | 7d000278728f5f8940d02fe9798735820baa79e5 (diff) | |
download | otp-471a50ef1391f6399664f8b992da7a67c32c8b86.tar.gz otp-471a50ef1391f6399664f8b992da7a67c32c8b86.tar.bz2 otp-471a50ef1391f6399664f8b992da7a67c32c8b86.zip |
Fix hibernation subtlety
Diffstat (limited to 'system/doc/design_principles')
-rw-r--r-- | system/doc/design_principles/statem.xml | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/system/doc/design_principles/statem.xml b/system/doc/design_principles/statem.xml index a4b8fb06a0..ca0fce55e2 100644 --- a/system/doc/design_principles/statem.xml +++ b/system/doc/design_principles/statem.xml @@ -1448,4 +1448,75 @@ format_status(Opt, [_PDict,State,Data]) -> </p> </section> +<!-- =================================================================== --> + + <section> + <title>Hibernation</title> + <p> + If you have many servers in one node + and they have some state(s) in their lifetime in which + the servers can be expected to idle for a while, + and the amount of heap memory all these servers need + is a problem; then it is possible to minimize + the memory footprint of a server by hibernating it through + <seealso marker="stdlib:proc_lib#hibernate/3"> + <c>proc_lib:hibernate/3</c>. + </seealso> + </p> + <note> + <p> + To hibernate a process is rather costly. See + <seealso marker="erts:erlang#hibernate/3"> + <c>erlang:hibernate/3</c>. + </seealso> + It is in general not something you want to do + after every event. + </p> + </note> + <p> + We can in this example hibernate in the <c>{open,_}</c> state + since what normally happens in that state is that + the state timeout after a while + triggers a transition to <c>{locked,_}</c>: + </p> + <code type="erl"><![CDATA[ +... +handle_event( + EventType, EventContent, + {open,LockButton}, #{timer := Timer} = Data) -> + case {EventType,EventContent} of + {internal,enter} -> + Tref = erlang:start_timer(10000, self(), lock), + do_unlock(), + {keep_state,Data#{timer := Tref},[hibernate]}; +... + ]]></code> + <p> + The + <seealso marker="stdlib:gen_statem#type-hibernate"> + <c>[hibernate]</c> + </seealso> + action list on the last line + when entering the <c>{open,_}</c> state is the only change. + If any event arrives in the <c>{open,_},</c> state we + do not bother to re-hibernate, so the server stays + awake after any event. + </p> + <p> + To change that we would need to insert + the <c>hibernate</c> action in more places, + for example for the state independent <c>set_lock_button</c> + and <c>code_length</c> operations that then would have to + be aware of using <c>hibernate</c> while in the + <c>{open,_}</c> state which would clutter the code. + </p> + <p> + This server probably does not use an amount of + heap memory worth hibernating for. + To gain anything from hibernation your server would + have to actually produce some garbage during callback execution, + for which this example server may serve as a bad example. + </p> + </section> + </chapter> |