How to minimise BEAM startup time?

I am pondering if I should write several CLI tools in Elixir – I am aware the BEAM’s startup time makes this a rather poor choice but I’m still going to finish them quicker compared to coding them in Rust, plus there’s also the integration aspect (one of the tools will merely schedule future jobs for a long-running Elixir server); making sure the proper format is issued from the Rust code to the external job queue might be trivial or it might be a whole-week project. So for now I am not risking it.

The startup time of the BEAM is actually okay-ish for a dynamic language but when you have to invoke it repeatedly it becomes a real problem.


I’ve been looking at erl’s docs but save from disabling distribution – and epmd as well? not sure – so far I am not seeing much of what I can do. Reading and researching is still in progress but I figured I’ll ask the community in the meantime, in case anyone has experience to share.

So, assuming that:

  • I don’t need distributed Erlang features;
  • I am OK with some apps starting later in the boot phase (if possible);
  • I still want to be able to remotely connect to the VM (for my non-CLI one-off apps) but I’d like to see if disabling this will improve startup times;
  • I am also OK with reducing the general responsiveness of the VM (for the CLI tools) by tweaking various scheduler flags (still not very clear on their exact meaning as I am reading erl's docs)

…then what would a command-line starting an Elixir app look like, with all the erl and emulator flags in it?

Additionally, if you have the experience, do let me know of anything and everything you know or have tried – I am willing to analyse the tradeoffs and decide what I should go for.

Of course, eventually I could give this up because it does sound like fitting a square peg into a round hole. But I figure it could be useful to learn some BEAM tweaks.

Thank you.

9 Likes

For the erlc we use these: https://github.com/erlang/otp/blob/master/erts/etc/common/erlc.c#L287

Any other way we have tried have not made a large difference. The large bottleneck is loading the code of the Erlang system which is not an easy thing to make faster.

6 Likes

I probably had the idea that eager starting of the project’s entire supervision tree can be partially made lazy and this could accelerate startup – but this seems misguided.

rebar3 uses the arguments garazdawi mentions, as well as offering an option to not boot it as an escript because of the loading code bottleneck. Run as an escript it loads all the code on boot but when run unpacked it uses interactive mode so that modules are only loaded when they are used

Plus, rebar3 has no supervision tree to start and just carries state as a variable, so recommend doing that unless for some reason you really need supervisors and to start processes on startup.

2 Likes