Nebulex v2.0.0-rc.0 Nebulex.Adapters.Local View Source
Adapter module for Local Generational Cache; inspired by epocxy.
Generational caching using an ets table (or multiple ones when used with
:shards
) for each generation of cached data. Accesses hit the newer
generation first, and migrate from the older generation to the newer
generation when retrieved from the stale table. When a new generation
is started, the oldest one is deleted. This is a form of mass garbage
collection which avoids using timers and expiration of individual
cached elements.
This implementation of generation cache uses only two generations
(which is more than enough) also referred like the newer
and
the older
.
Features
- Configurable backend (
ets
or:shards
). - Expiration – A status based on TTL (Time To Live) option. To maintain cache performance, expired entries may not be immediately flushed or evicted, they are expired or evicted on-demand, when the key is read.
- Eviction – Generational Garbage Collection.
- Sharding – For intensive workloads, the Cache may also be partitioned
(by using
:shards
backend and specifying the:partitions
option). - Support for transactions via Erlang global name registration facility.
Options
This adapter supports the following options and all of them can be given via the cache configuration:
:backend
- Defines the backend or storage to be used for the adapter. Supported backends are::ets
and:shards
. Defaults to:ets
.:read_concurrency
- Since this adapter uses ETS tables internally, this option is used when a new table is created. See:ets.new/2
. Defaults totrue
.:write_concurrency
- Since this adapter uses ETS tables internally, this option is used when a new table is created. See:ets.new/2
. Defaults totrue
.:compressed
- This option is used when a new ETS table is created and it defines whether or not it includes X as an option. See:ets.new/2
. Defaults tofalse
.:backend_type
- This option defines the type of ETS to be used (Defaults to:set
). However, it is highly recommended to keep the default value, since there are commands not supported (unexpected exception may be raised) for types like:bag
or: duplicate_bag
. Please see the ETS docs for more information.:partitions
- The number of partitions in the Cache. This option is only available for:shards
backend. Defaults toSystem.schedulers_online()
.:gc_interval
- Interval time in milliseconds to garbage collection to run, delete the oldest generation and create a new one. If this option is not set, garbage collection is never executed, so new generations must be created explicitly, e.g.:Generation.new_generation(cache_name, [])
.:max_size
- Max number of cached entries (cache limit). If it is not set (nil
), the check to release memory is not performed (the default).:allocated_memory
- Max size in bytes allocated for a cache generation. If this option is set and the configured value is reached, a new cache generation is created so the oldest is deleted and force releasing memory space. If it is not set (nil
), the cleanup check to release memory is not performed (the default).:gc_cleanup_min_timeout
- The min timeout in milliseconds for triggering the next cleanup and memory check. This will be the timeout to use when the max allocated memory is reached. Defaults to30_000
.:gc_cleanup_max_timeout
- The max timeout in milliseconds for triggering the next cleanup and memory check. This is the timeout used when the cache starts or the consumed memory is0
. Defaults to300_000
.
Example
Nebulex.Cache
is the wrapper around the cache. We can define a
local cache as follows:
defmodule MyApp.LocalCache do
use Nebulex.Cache,
otp_app: :my_app,
adapter: Nebulex.Adapters.Local
end
Where the configuration for the cache must be in your application
environment, usually defined in your config/config.exs
:
config :my_app, MyApp.LocalCache,
backend: :shards,
gc_interval: 86_400_000,
max_size: 200_000,
allocated_memory: 2_000_000_000,
gc_cleanup_min_timeout: 10_000,
gc_cleanup_max_timeout: 600_000
For intensive workloads, the Cache may also be partitioned (by using :shards
backend and specifying the :partitions
option). If partitioning is required
then a good default is to set the number of partitions to the number of
schedulers available (the default):
config :my_app, MyApp.LocalCache,
backend: :shards,
gc_interval: 86_400_000,
max_size: 200_000,
allocated_memory: 2_000_000_000,
gc_cleanup_min_timeout: 10_000,
gc_cleanup_max_timeout: 600_000,
partitions: System.schedulers_online()
For more information about the usage, check out Nebulex.Cache
.
Queryable API
The adapter supports as query parameter the following values:
query
-nil | :unexpired | :expired | :ets.match_spec()
Internally, an entry is represented by the tuple {key, val, vsn, exp}
,
which means the match pattern within the :ets.match_spec()
must be
something like {:"$1", :"$2", :"$3", :"$4"}
. In order to make query
building easier, you can use Ex2ms
library.
Examples
# built-in queries
MyCache.all()
MyCache.all(:unexpired)
MyCache.all(:expired)
# using a custom match spec (all values > 10)
spec = [{{:"$1", :"$2", :_, :_}, [{:>, :"$2", 10}], [{{:"$1", :"$2"}}]}]
MyCache.all(spec)
# using Ex2ms
import Ex2ms
spec =
fun do
{key, value, _version, _expire_at} when value > 10 -> {key, value}
end
MyCache.all(spec)
The :return
option applies only for built-in queries, such as:
nil | :unexpired | :expired
, if you are using a custom :ets.match_spec()
,
the return value depends on it.
The same applies to the stream
function.