Repository navigation
Add a hibernate_after supervisor option - #39
Merged
Merged
Conversation
A DurableServer process never hibernated, so an idle server kept its heap at its high-water mark: in one production deployment an idle server held about 1 MB, of which 54 KB survived a GC. DurableServer.Supervisor now accepts :hibernate_after, either one positive integer for every module or a map of module => ms. Every child the supervisor starts, including restarts and rehoming, passes it to GenServer.start_link, so an idle server hibernates and its heap shrinks to live data. Default nil keeps the current behaviour.
A server's idle behaviour belongs to its module, which travels with it however the supervisor starts it. use DurableServer, hibernate_after: ms sets it for that module and hibernate_after: false opts out; the supervisor's :hibernate_after is now one integer used as the default for modules that set nothing. The per-module map on the supervisor is gone.
function_exported?/3 is false for a module that is not loaded yet, so a server type whose module had not been loaded on that node got no hibernate_after on its first start. Load the module before reading it.
Per-module settings already live on the supervisor mount (max_children, sticky_placement), so hibernate_after moves there too and the use option goes away: an integer for every module, or a map of Module => ms with an optional :default for modules not listed. The lookup is by module name, so it no longer needs the module loaded.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A DurableServer process never hibernates, so an idle server keeps its heap at its high-water mark. In one production deployment, an idle server held about 1.06 MB, of which 54 KB survived a GC (live state: 38 KB). With thousands of mostly idle servers per node, that's gigabytes held for nothing.
Change
DurableServer.Supervisoraccepts:hibernate_afteron the mount, next to the other per-module settings:Module => msapplies to the listed modules. A:defaultkey covers modules not listed; without it, unlisted modules don't hibernate.nil(default): no change from today.The supervisor starts every child through one child spec with its config, including
start_child, restart claims, rehoming and preloaded boot. SoDurableServer.start_link/1looks up its module and passeshibernate_after:toGenServer.start_link/3. The lookup is by module name, so it works whether or not the module is loaded yet. Invalid values are rejected when the supervisor starts.Tests
:defaultcovers unlisted modules.The "does hibernate" tests fail without the
start_linkchange. On OTP 28, a hibernated gen_server reportsgen_server:loop_hibernate/4; the tests accept that and the oldererlang:hibernate/3.