fhunleth

fhunleth

Co-author of Nerves

Minimizing OTP release size

I realize that most people aren’t overly concerned with OTP release sizes. I hadn’t been, but an issue came up where over-the-air updates over an LTE connection actually starts costing money. The OTP release on my device occupies about 55% of the space, not counting beam.smp. I was looking at the application sizes in a release. Here’s a sampling of the top sizes (in KB) I’m seeing:

$ du -ks * | sort -rn
4652    elixir-1.7.4
4012    stdlib-3.6
1792    kernel-6.1
1736    compiler-7.2.7
1136    ssl-9.0.3
1028    asn1-5.0.7
912    public_key-1.6.3
900    mix-1.7.4
880    ssh-4.7.1
780    distillery-2.0.10
372    sasl-3.2.1
312    iex-1.7.4
308    runtime_tools-1.13.1
204    crypto-4.3.3
200    socket-0.3.13
184    x509-0.5.0-dev
148    nerves_network-0.3.7
144    logger-1.7.4
136    nerves_runtime-0.8.0
128    system_registry-0.8.0

I’ve configured Distillery to strip debug out of the .beam files. That helped, but not as much as I hoped. As you can see, Elixir and stdlib are still over 4 MB and there are quite a few decent size ones after that. If those could be reduced, that would be a decent win for me. Has anyone tried doing this? Any ideas?

Thanks!

First Post!

michalmuskala

michalmuskala

I’m pretty sure the majority of the size of Elixir will be the Unicode modules. The new compiler in OTP 22 might be actually better at compiling things like that, which might reduce the size somewhat. The issue is even bigger since now the Erlang’s stdlib contains another copy of unicode too.

One more thing you could try is compiling everything without line info (the option to compiler is no_line_info). This might create more opportunities for compiler passes that merge similar code together if they only differ by a line number, but that’s kind of a long shot.

Most Liked

fhunleth

fhunleth

Co-author of Nerves

Here’s the update:

  1. I made distillery a runtime: false dependency. This also removes the need for mix to be in the release. This dropped the size by 4.5%, but it felt good to not include the build tools. I’ll obviously need to reconsider if we start using the config providers
  2. Stripping the .beam files trimmed the firmware by 35%! Everything (Linux kernel, beam.smp, drivers, wifi firmware, bootloaders, and the OTP release) are now in a 15.2 MB package.
  3. @mobileoverlord had to make some PRs to Distillery and Shoehorn, so these numbers aren’t easy to reproduce yet. They also include unreleased updates to nerves_system_br.

I’m not out of the woods with size, but I’m going to savor this improvement over the Thanksgiving holiday here. I also want to see if I can live with the stripped beams.

Here are some stats:

After stripping the beams:

$ du -ks * | sort -nr
1632   elixir-1.7.4
1160   stdlib-3.6
668     kernel-6.1
512     compiler-7.2.7
356     asn1-5.0.7
312     ssl-9.0.3
284     ssh-4.7.1
264     public_key-1.6.3
160     iex-1.7.4
152     runtime_tools-1.13.1
148     sasl-3.2.1
132     crypto-4.3.3
104     socket-0.3.13
100     nerves_runtime-0.8.0

Post strip, here’s example contents of a .beam file (this one is the current winner on size in the Elixir app)

iex(9)> :beam_lib.info('/srv/erlang/lib/elixir-1.7.4/ebin/Elixir.Base')  
[
  file: '/srv/erlang/lib/elixir-1.7.4/ebin/Elixir.Base.beam',
  module: Base,
  chunks: [
    {'Line', 20, 636},
    {'AtU8', 664, 1642},
    {'Code', 2316, 230760},
    {'StrT', 233084, 45},
    {'ImpT', 233140, 232},
    {'ExpT', 233380, 400},
    {'LitT', 233788, 218}
  ]
]

I would assume that means that line number info is still present, but it looks too small to worry about.

jola

jola

Specifically the strip_debug_info is an option for Distillery Configuring Distillery - Distillery Documentation.

Would be cool with an article discussing the ways to reduce size.

LostKobrakai

LostKobrakai

I’m wondering if incremental updates would help you as well. I often update my releases not by uploading the whole thing, but by using rsync to just upload what’s changed.

Where Next?

Popular in Questions Top

rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40165 209
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 42716 114
New

We're in Beta

About us Mission Statement