jola

jola

A question was asked here whether releases use less memory, so checked in a project I’m working on and I was surprised to see almost twice the memory use for the same code. To make sure it wasn’t just my project, I tried with a plain Phoenix app and only the minimal steps to get releases started. This is what I did if you want to reproduce:

mix phx.new hello --no-webpack --no-html --no-ecto
# added {:distillery, "~> 2.0"} to mix.exs
cd hello
mix deps.get
MIX_ENV=prod mix release

Then to compare the memory use I relied on :erlang.memory/0. First using plain mix run in iex.

MIX_ENV=prod iex -S mix run

iex(1)> :erlang.memory 
[
  total: 31407808,
  processes: 7082192,
  processes_used: 7063440,
  system: 24325616,
  atom: 512625,
  atom_used: 504423,
  binary: 97440,
  code: 10298466,
  ets: 929712
]

and then starting the release in the equivalent console

_build/prod/rel/hello/bin/hello console

iex(hello@127.0.0.1)1> :erlang.memory 
[
  total: 55362432,
  processes: 14649704,
  processes_used: 14363384,
  system: 40712728,
  atom: 984241,
  atom_used: 961617,
  binary: 174464,
  code: 21349495,
  ets: 2029176
]

Total reported memory use went from 31MB to 55MB. And you see increases across the board. In my personal project the increase was even more significant, going from 45MB to 90MB.

One thing I guess could be related is that I believe releases preload all code while mix will load modules on demand. But does that really account for the whole difference?

I also want to add a disclaimer: I’m still using releases and I don’t find the memory used to be unreasonable. This is just curiosity!

Showing Posts 1 to 7

michalmuskala

michalmuskala

I think the code loading part will be the major difference - more code means more atoms, more binaries (from literals in those modules) and more ets usage (since information which modules are loaded is held in an ets table by the code_server process). Additionally there might be some more system-level services running like SASL or the release handlers, which could account for the extra process size. Have you tried comparing the outputs of Process.list() on both systems? That could shed some more light on it. Similarly for ets tables you could investigate with :ets.info.

rvirding

rvirding

Creator of Erlang

Check to see which applications have been loaded, there may be more in the release. Also check which applications have been started. IIRC correctly the release will start all applications at start up time.

rodrigues

rodrigues

I’ve had similar numbers here, @jola, using your steps.

Following @rvirding suggestion, I’ve ran this code in each:

Application.started_applications() |> Enum.map(&elem(&1, 0)) |> Enum.sort()

# release
# $ _build/prod/rel/hello/bin/hello console
[:artificery, :asn1, :compiler, :cowboy, :cowlib, :crypto, :distillery, :eex,
 :elixir, :gettext, :hello, :iex, :jason, :kernel, :logger, :mime, :mix,
 :phoenix, :phoenix_pubsub, :plug, :plug_cowboy, :plug_crypto, :public_key,
 :ranch, :runtime_tools, :sasl, :ssl, :stdlib]

# mix
# $ MIX_ENV=prod iex -S mix run
[:artificery, :asn1, :compiler, :cowboy, :cowlib, :crypto, :distillery, :eex,
 :elixir, :gettext, :hello, :hex, :iex, :inets, :jason, :kernel, :logger, :mime,
 :mix, :phoenix, :phoenix_pubsub, :plug, :plug_cowboy, :plug_crypto,
 :public_key, :ranch, :runtime_tools, :ssl, :stdlib]
  • release had extra: sasl
  • mix run had extra: hex, inets

I guess sasl is the likely culprit?

UPDATE: sasl start not relevant to memory. I’ve checked also the loaded applications, and it’s the same as started applications. That’s intriguing :+1:t3:

# :erlang.memory in mix option after start
[
  total: 34951112,
  processes: 13154512,
  processes_used: 13153312,
  system: 21796600,
  atom: 512625,
  atom_used: 505434,
  binary: 206016,
  code: 10368934,
  ets: 942080
]

# :erlang.memory in mix option, after starting sasl
[
  total: 35274176,
  processes: 13233528,
  processes_used: 13230984,
  system: 22040648,
  atom: 520817,
  atom_used: 517966,
  binary: 205984,
  code: 10547076,
  ets: 957688
]

# :erlang.memory in release option
[
  total: 60294456,
  processes: 21970552,
  processes_used: 21847048,
  system: 38323904,
  atom: 992433,
  atom_used: 971447,
  binary: 441208,
  code: 21443760,
  ets: 1992328
]
tristan

tristan

Rebar3 Core Team

Your release is likely starting in embedded mode while mix run is interactive mode. Embedded mode will load all beam modules on start up instead of only when they are used.

See System Principles — Erlang System Documentation v29.0.2

rodrigues

rodrigues

Indeed, using :code.all_loaded(), I saw the release has 663 modules loaded in it that were not loaded in mix run, while the contrary is 25.

jola

jola OP

I tried comparing named processes between the app started through mix and the release and came up with this

# iex(4)> release -- mix
[:alarm_handler, :auth, :erl_epmd, :net_kernel, :net_sup, :release_handler,
 :sasl_safe_sup, :sasl_sup]
# iex(5)> mix -- release
[Hex.Registry.Server, Hex.Server, Hex.State, Hex.Supervisor, Hex.UpdateChecker,
 :hex_fetcher, :httpc_handler_sup, :httpc_hex, :httpc_manager,
:httpc_profile_sup, :httpc_sup, :httpd_sup, :inets_sup]

which seems to show the same differences that @rodrigues found comparing the running applications. Put the output and the code I ran here.

I wonder what the memory use would be when running with mix if you force-load all the modules.

rodrigues

rodrigues

passing --preload-modules to mix run seems to do the job, actually it loads 133 modules more than release, while the modules below are loaded by release but not loaded in mix run, even with preload:

[:sasl_report, :systools_rc, :alarm_handler, :release_handler_1,
 :format_lib_supp, :misc_supp, :systools_make, :sasl, :sasl_report_tty_h,
 :sasl_report_file_h, :erlsrv, :systools_lib, :release_handler, :systools, :rb,
 :rb_format_supp, :systools_relup]

It does increase memory significantly, but release still has more (gist with output).

— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
roeland
Kia ora, We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New
rahultumpala
Hello, I have an Elixir backend that implements a custom protocol over TCP. I want to load test the backend and assess the performance o...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews