Formular - A tiny DSL engine / code evaluator (configuration as code)

I played with Sand as @mat-hek shared and it does what I wanted. Not implying by the name, under the scene, Sand runs the code with Code.eval_quoted/3 too. Only in a separated process which can be limited in reductions & memory usage. I think that is the right way to go.

Also, I did some benchmarks, and the result was surprising at first glance.

Code:

code = """
  squares = %{3 => 9, 4 => 16, 5 => 25}
  squares[3]
"""

ast = Code.string_to_quoted!(code)

Benchee.run(%{
  eval: fn -> {:ok, 9} = Formular.eval(code, []) end,
  eval_ast: fn -> {:ok, 9} = Formular.eval(ast, []) end,
  sand_run: fn -> {:ok, 9, _} = Sand.run(code) end,
  sand_run_without_cpu_memory_monitoring: fn ->
    {9, _} = Sand.run_without_cpu_memory_monitoring(code)
  end
})

(Sand doesn’t accept AST at this moment)

Result:

Name                                             ips        average  deviation         median         99th %
sand_run_without_cpu_memory_monitoring       23.91 K       41.82 μs    ±20.35%       39.04 μs       70.77 μs
sand_run                                      3.50 K      285.99 μs    ±28.04%      269.01 μs      509.55 μs
eval_ast                                      3.35 K      298.88 μs     ±9.51%      293.91 μs      437.12 μs
eval                                          3.09 K      323.70 μs     ±9.67%      317.00 μs      467.09 μs

Comparison: 
sand_run_without_cpu_memory_monitoring       23.91 K
sand_run                                      3.50 K - 6.84x slower +244.18 μs
eval_ast                                      3.35 K - 7.15x slower +257.06 μs
eval                                          3.09 K - 7.74x slower +281.88 μs

I figured out the reason after some research and it is very interesting. I’m excited about the work ahead.

Thank you @hauleth , really appreciate it. I know the next direction now.

1 Like