CompilerCache

Build StatusHex pm

LRU cache for compiling expressions into functions.

Using CompilerCache, it is easy to create custom expressions that perform well.

Instead of relying on using Code.eval_quoted, the CompilerCache system compiles given ASTs into modules.

The compilation cache has a fixed maximum size, and uses a fixed pool of module names as not to exhaust the BEAM vm's atom table.

Usage

Creating a compilation cache is as simple as use CompilerCache and implementing the create_ast/1 function:

defmodule MyExpressionCache do
  use CompilerCache
  def create_ast(expr) do
    {:ok, ast} = Code.string_to_quoted(expr)
    {ast, []}
  end
end

The create_ast/2 function must return an {ast, opts} tuple. The opts are the same as those given to Code.eval_quoted/3.

This cache can then be called like this:

{:ok, _} = MyExpressionCache.start_link()
iex> MyExpressionCache.execute("1 + 1", nil)
2
iex> MyExpressionCache.execute("2 * input", 3)
6

The input argument is always called 'input'. There is just one input argument - use a tuple and pattern matching to use multiple arguments. To use a different variable name, use the :input_name config option in the use statement.

After N cache misses (default: 1, so the second time the same expression is called), expressions are cached into a module on the background by the compiler process. This speeds up consecutive executions considerable (~10x speedups are not unheard of).

Cached expressions (modules) are unloaded when they have not been used after max_ttl milliseconds (default: 1000).

The number of cached expressions can be limited by setting the cache_size option, which defaults to 10_000.

Full documentation: https://hexdocs.pm/compiler_cache/

Installation

The package is available on hex.pm and can be installed like this:

  1. Add compiler_cache to your list of dependencies in mix.exs:
```elixir
def deps do
  [{:compiler_cache, "~> 1.0"}]
end
```
  1. Ensure compiler_cache is started before your application:
```elixir
def application do
  [applications: [:compiler_cache]]
end
```
  1. Implement your compiler by using use CompilerCache and implementing create_ast/1, then put it in your supervisor tree:

    worker(MyExpressionCache, [])