Dsxir.Optimizer.Cache (dsxir v0.3.0)

Copy Markdown

Compile-scoped LM cache for optimizers that run a program many times.

An anonymous ETS table is created at the start of with_compile_cache/2 and deleted via try/after on exit (normal or raised). heir: :none ensures owner-process death also reclaims the table. The table is never globally registered; only the tid escapes, passed explicitly to workers.

Used by search-based optimizers to skip duplicate (lm, predictor_state, input) evaluations within a compile. Tenant-safe by construction: each Dsxir.compile/5 call inside a Dsxir.context/2 block gets its own table; nothing crosses tenants.

Summary

Functions

Like get_or_put/3 but reports whether the value was already present.

Lookup key in tid; on miss, call fun.(), store the result, return it. A nil tid always calls fun.() and skips storage.

Hash an input map into a 32-bit integer. Keys are sorted before hashing so map ordering does not change the key.

Hash an LM config keyword list. Keys are sorted so option order is irrelevant; :api_key and :model are included so tenants with different credentials never collide on a shared key.

Hash a predictor's Dsxir.Program.State into a 32-bit integer suitable as part of a cache key. The :demo_strategy field is excluded because by the time the LM is invoked the strategy has already produced concrete demos. Demo order does not affect the hash.

Run fun.(tid) with a fresh ETS cache when enabled? is true; pass nil and skip the cache when false. The table is destroyed on exit, including raises.

Types

key()

@type key() :: term()

tid()

@type tid() :: :ets.tid() | nil

Functions

fetch_or_put(tid, key, fun)

@spec fetch_or_put(tid(), key(), (-> result)) :: {:hit | :miss, result}
when result: var

Like get_or_put/3 but reports whether the value was already present.

Returns {:hit, cached} when key was in tid, {:miss, value} after computing and storing. A nil tid always reports :miss so callers that count cache effectiveness see a consistent shape regardless of whether the cache is enabled.

get_or_put(tid, key, fun)

@spec get_or_put(tid(), key(), (-> result)) :: result when result: var

Lookup key in tid; on miss, call fun.(), store the result, return it. A nil tid always calls fun.() and skips storage.

input_hash(input)

@spec input_hash(map()) :: non_neg_integer()

Hash an input map into a 32-bit integer. Keys are sorted before hashing so map ordering does not change the key.

lm_config_hash(config)

@spec lm_config_hash(keyword()) :: non_neg_integer()

Hash an LM config keyword list. Keys are sorted so option order is irrelevant; :api_key and :model are included so tenants with different credentials never collide on a shared key.

predictor_state_hash(state)

@spec predictor_state_hash(Dsxir.Program.State.t()) :: non_neg_integer()

Hash a predictor's Dsxir.Program.State into a 32-bit integer suitable as part of a cache key. The :demo_strategy field is excluded because by the time the LM is invoked the strategy has already produced concrete demos. Demo order does not affect the hash.

with_compile_cache(bool, fun)

@spec with_compile_cache(boolean(), (tid() -> result)) :: result when result: var

Run fun.(tid) with a fresh ETS cache when enabled? is true; pass nil and skip the cache when false. The table is destroyed on exit, including raises.