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.