erllama_scheduler (erllama v0.1.0)

View Source

Memory-pressure-driven cache eviction.

Periodically polls a pluggable pressure source (erllama_pressure) and, when the used/total ratio crosses high_watermark, asks the cache to evict slabs until the ratio would drop below low_watermark. The eviction call is erllama_cache:evict_bytes/2 with a target of (high - low) * Total bytes; the cache may free less if no evictable slabs remain.

Tier policy: by default the scheduler evicts only ram and ram_file slabs. Disk-tier slabs are left in place — disk is the cheap tier, and the deployment usually wants to keep as much warm state as possible there. Disk eviction happens via the cache's own per-tier quota or via an explicit erllama_cache:gc/0 call. Override with evict_tiers => all (or a custom list) to include disk in scheduler-driven eviction.

Disabled by default. Enable via the erllama app environment:

{erllama, [
  {scheduler, #{
    enabled         => true,
    pressure_source => system,    %% noop | system | nvidia_smi | {module, M}
    interval_ms     => 5000,
    high_watermark  => 0.85,
    low_watermark   => 0.75,
    min_evict_bytes => 1048576,   %% don't bother with sub-MB targets
    evict_tiers     => [ram, ram_file]
  }}
]}

The scheduler always starts (so it can be enabled at runtime via enable/1), but its timer only fires when enabled = true.

Summary

Types

config()

-type config() ::
          #{enabled => boolean(),
            pressure_source => erllama_pressure:source(),
            interval_ms => pos_integer(),
            high_watermark => float(),
            low_watermark => float(),
            min_evict_bytes => non_neg_integer(),
            evict_tiers => all | [erllama_cache:tier()]}.

state()

-type state() ::
          #state{enabled :: boolean(),
                 pressure_source :: erllama_pressure:source(),
                 interval_ms :: pos_integer(),
                 high_watermark :: float(),
                 low_watermark :: float(),
                 min_evict_bytes :: non_neg_integer(),
                 evict_tiers :: all | [erllama_cache:tier()],
                 timer_ref :: reference() | undefined,
                 last_used :: non_neg_integer(),
                 last_total :: non_neg_integer(),
                 last_evicted_bytes :: non_neg_integer(),
                 last_evicted_at :: integer() | undefined,
                 sampled_at :: integer() | undefined}.

Functions

enable(Bool)

-spec enable(boolean()) -> ok.

force_check()

-spec force_check() ->
                     {evicted, non_neg_integer(), non_neg_integer()} |
                     {skipped, below_watermark | disabled | nothing_to_evict}.

Force a check now (sample + maybe evict). Returns the eviction result if one was triggered, {skipped, Reason} otherwise.

handle_call/3

handle_cast(Msg, S)

handle_info/2

init/1

-spec init([config()]) -> {ok, state()} | {stop, term()}.

sample()

-spec sample() -> erllama_pressure:reading().

set_pressure_source(Source)

-spec set_pressure_source(erllama_pressure:source()) -> ok.

set_thresholds/2

-spec set_thresholds(float(), float()) -> ok | {error, term()}.

start_link()

-spec start_link() -> {ok, pid()} | {error, term()}.

start_link(Config)

-spec start_link(config()) -> {ok, pid()} | {error, term()}.

status()

-spec status() -> map().

terminate(Reason, S)

validate_config(Cfg)