Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make literals chunk uncompressed on Erlang/OTP 28 #8967

Open
josevalim opened this issue Oct 21, 2024 · 6 comments · May be fixed by #8988
Open

Make literals chunk uncompressed on Erlang/OTP 28 #8967

josevalim opened this issue Oct 21, 2024 · 6 comments · May be fixed by #8988
Assignees
Labels
bug Issue is reported as a bug team:VM Assigned to OTP team VM

Comments

@josevalim
Copy link
Contributor

josevalim commented Oct 21, 2024

If compression is important, it can be enabled for the whole .beam.

See #8940 (comment).

Also, to quote @pguyot from that thread:

For what it's worth, not having compressed chunks allows more easily to mmap beams and read from there. AtomVM runs on microcontrollers that can map part of the flash to the address space, either at fixed offset (Pico with XIP) or with some address translation (ESP32 families). These microcontrollers use some cache for this but it's well optimized including in regards to interruptions and multicore.

@josevalim josevalim added the bug Issue is reported as a bug label Oct 21, 2024
@IngelaAndin IngelaAndin added the team:VM Assigned to OTP team VM label Oct 22, 2024
@bjorng bjorng self-assigned this Oct 22, 2024
@bjorng
Copy link
Contributor

bjorng commented Oct 22, 2024

Thanks for the suggestion! I've asked the OTP team for feedback on this idea.

@bjorng
Copy link
Contributor

bjorng commented Oct 22, 2024

Here is a WIP branch that no longer compresses the literal chunk:

https://github.com/bjorng/otp/tree/bjorn/uncompressed-literals/GH-8967/rfc

I have calculated the total size of all stripped BEAM files in OTP with and without this branch. Note that an undocumented feature of the beam_lib:strip functions is that the resulting BEAM file is compressed as well as stripped.

  • Before: 9009382
  • After: 8926893
  • Difference: 82489 (0.9 percent)

@josevalim Do you have any benchmark to test whether this change would make any difference in load times?

@pguyot You will still have to convert all literals from the external term format to the external. Do you think that not having to uncompress the literal chunk will noticeably decrease load times?

@josevalim
Copy link
Contributor Author

josevalim commented Oct 22, 2024

Here is something I used the last time around:

defmodule Run do
  def run([path]) do
    entries =
      for beam <- Path.wildcard(Path.join(path, "**/*.beam")) do
        module = beam |> Path.basename() |> Path.rootname() |> String.to_atom()
        {module, File.read!(beam)}
      end

    IO.puts("Loading #{length(entries)}")

    :timer.tc(:lists, :foreach, [
      entries,
      fn {module, binary} -> :erlang.prepare_loading(module, binary) end
    ])
    |> elem(0)
    |> IO.inspect()

    :timer.tc(:lists, :foreach, [
      entries,
      fn {module, binary} -> :erlang.prepare_loading(module, binary) end
    ])
    |> elem(0)
    |> IO.inspect()
  end
end

Run.run(System.argv())

Which you can call as elixir script.exs path/to/rootdir. I will get all .beam files within the given path and print the measurements for preparing all of them. The first one is for warmup. I couldn't measure any difference before.

@pguyot
Copy link
Contributor

pguyot commented Oct 22, 2024

@pguyot You will still have to convert all literals from the external term format to the external. Do you think that not having to uncompress the literal chunk will noticeably decrease load times?

True. If the literals are compressed (LITT), AtomVM uncompresses them when the module is loaded, allocating a copy in RAM. If they are not compressed (LITU chunk that PackBeam tool creates on the desktop), AtomVM just maps them, allocating no additional RAM at all. Then when a literal is referenced, it is copied on heap, except for binaries (which we can do as long as modules are not unloaded in AtomVM).

Regarding the load times, I guess this question was not for AtomVM. Not having to uncompress the literal chunks reduces the load time as we just mmap it as opposed to allocating and inflating it, but we're not measuring this on microcontrollers.

@bjorng
Copy link
Contributor

bjorng commented Oct 23, 2024

Thanks!

I couldn't find any difference in load times.

I also calculated the size of the untouched BEAM files (that is, with all chunks present).

  • Before: 46171884
  • After: 47351240
  • Difference: 1179356 (1 percent)

That slight size increase seems acceptable to me.

Therefore, it seems to me that the positive aspects of this change slightly outweigh the negative aspects.

bjorng added a commit to bjorng/otp that referenced this issue Oct 25, 2024
See erlang#8967 and erlang#8940 for a discussion why this is useful.

This commit also makes it possible to read out the literal chunk
decoded like so:

    beam_lib:chunks(Beam, [literals])

Closes erlang#8967
bjorng added a commit to bjorng/otp that referenced this issue Oct 25, 2024
See erlang#8967 and erlang#8940 for a discussion about why this is useful.

This commit also makes it possible to read out the literal chunk
decoded like so:

    beam_lib:chunks(Beam, [literals])

Closes erlang#8967
bjorng added a commit to bjorng/otp that referenced this issue Oct 25, 2024
See erlang#8967 and erlang#8940 for a discussion about why this is useful.

This commit also makes it possible to read out the literal chunk
decoded like so:

    beam_lib:chunks(Beam, [literals])

Closes erlang#8967
@bjorng bjorng linked a pull request Oct 25, 2024 that will close this issue
@bjorng
Copy link
Contributor

bjorng commented Oct 25, 2024

I've finished the implementation and published a pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue is reported as a bug team:VM Assigned to OTP team VM
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants