<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/not-all-bytes-are-equal-tvaxewpbu" -->

---
title: Not all bytes are equal | daily.dev
description: Popcorn, a library for running Elixir's OTP/BEAM VM in the browser, cut its uncompressed asset size from 25.9 MB to 10.7 MB. The Wasm VM binary shrank from...
canonical: https://daily.dev/posts/not-all-bytes-are-equal-tvaxewpbu
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Not all bytes are equal | daily.dev
og:description: Popcorn, a library for running Elixir's OTP/BEAM VM in the browser, cut its uncompressed asset size from 25.9 MB to 10.7 MB. The Wasm VM binary shrank from...
og:url: https://daily.dev/posts/not-all-bytes-are-equal-tvaxewpbu
og:image: https://api.daily.dev/og/posts/TvAXEWpBu.png
og:image:alt: Not all bytes are equal
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Not all bytes are equal

**[Software Mansion](https://daily.dev/sources/swmansion)** · 13 min read · 0 upvotes · 0 comments

## Summary

Popcorn, a library for running Elixir's OTP/BEAM VM in the browser, cut its uncompressed asset size from 25.9 MB to 10.7 MB. The Wasm VM binary shrank from 3.25 MB to 2.44 MB using Emscripten's -Oz flag, link-time optimization, and removing unneeded OTP features like Zstd and native sockets. Stripping debug chunks from stdlib .beam files reduced them from 21.4 MB to 7.7 MB, and removing the Type chunk brought them to 7.5 MB. Switching checksums from MD5 to XXH3 and running exactly eight Web Workers helped cut boot time from 460 ms to roughly 340 ms, with the size optimizations contributing the earlier gains.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://swmansion.com/blog/popcorn-not-all-bytes-are-equal>

## Questions this post answers

### How did Popcorn reduce the size of its WebAssembly build of Erlang OTP/BEAM?

Popcorn cut total uncompressed assets from 25.9 MB to 10.7 MB. The Wasm VM binary dropped from 3.25 MB to 2.44 MB using Emscripten's -Oz flag with link-time optimization, removing features like Zstd compression, native sockets, and distribution support, and fixing a bug where :beam_lib.strip/1 double-compressed modules. Stdlib .beam files shrank from 21.4 MB to 7.5 MB by stripping debug chunks and the Type chunk.

_Anyone shrinking a Wasm or BEAM build can compare these binary-size techniques on daily.dev._

### What compiler flag reduces WebAssembly binary size when using Emscripten?

The -Oz flag tells the compiler to optimize for size more aggressively than -Os, and for Emscripten it also enables Wasm-specific optimizations affecting the glue JavaScript. Combined with link-time optimization and fewer Emscripten APIs, this reduced a Wasm binary and its JS glue by 435 kB total, with the JS glue itself shrinking from 307 kB to 72 kB.

_Developers tuning Wasm bundle size can keep tabs on Emscripten optimization tricks like this via daily.dev._

### How can I speed up checksum calculation when loading Erlang BEAM modules at startup?

Replacing MD5 with the XXH3 hash algorithm cut module checksumming time from 20 ms to under one millisecond in a browser-based BEAM VM. MD5 remains the default in standard OTP because it's deeply embedded in the term serialization format, but switching breaks distribution compatibility between nodes using different hash algorithms.

_Teams optimizing Erlang or Elixir startup performance can track low-level BEAM tuning tips on daily.dev._

## Similar posts on daily.dev

- [This Wasm interpreter fits in a QR code](https://daily.dev/posts/this-wasm-interpreter-fits-in-a-qr-code-9joneseox) · Lobsters · 21 upvotes · 0 comments
- [C\# now beats Rust on WASM size](https://daily.dev/posts/c-now-beats-rust-on-wasm-size-3bq5xteh9) · Hacker News · 22 upvotes · 1 comments

---

Tags: [#elixir](https://daily.dev/tags/elixir), [#webassembly](https://daily.dev/tags/webassembly)

[View this post on daily.dev](https://daily.dev/posts/not-all-bytes-are-equal-tvaxewpbu)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Not all bytes are equal","url":"https://daily.dev/posts/not-all-bytes-are-equal-tvaxewpbu","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/not-all-bytes-are-equal-tvaxewpbu"},"datePublished":"2026-10-27T14:58:30.757Z","dateModified":"2026-10-27T15:04:12.895Z","description":"Popcorn, a library for running Elixir's OTP/BEAM VM in the browser, cut its uncompressed asset size from 25.9 MB to 10.7 MB. The Wasm VM binary shrank from...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/b2041e0e7cec4fe1408aaacb9f068d8d?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/b2041e0e7cec4fe1408aaacb9f068d8d?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Software Mansion","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Software Mansion","logo":"https://media.daily.dev/image/upload/s--sOx0vaVZ--/f_auto,q_auto/v1785654908/logos/swmansion?_a=BAMAMicg0","url":"https://daily.dev/sources/swmansion"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/not-all-bytes-are-equal-tvaxewpbu","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"elixir,webassembly","timeRequired":"PT13M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Software Mansion","item":"https://daily.dev/sources/swmansion"},{"@type":"ListItem","position":3,"name":"Not all bytes are equal"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/not-all-bytes-are-equal-tvaxewpbu#faq","mainEntity":[{"@type":"Question","name":"How did Popcorn reduce the size of its WebAssembly build of Erlang OTP/BEAM?","acceptedAnswer":{"@type":"Answer","text":"Popcorn cut total uncompressed assets from 25.9 MB to 10.7 MB. The Wasm VM binary dropped from 3.25 MB to 2.44 MB using Emscripten's -Oz flag with link-time optimization, removing features like Zstd compression, native sockets, and distribution support, and fixing a bug where :beam_lib.strip/1 double-compressed modules. Stdlib .beam files shrank from 21.4 MB to 7.5 MB by stripping debug chunks and the Type chunk. Anyone shrinking a Wasm or BEAM build can compare these binary-size techniques on daily.dev."}},{"@type":"Question","name":"What compiler flag reduces WebAssembly binary size when using Emscripten?","acceptedAnswer":{"@type":"Answer","text":"The -Oz flag tells the compiler to optimize for size more aggressively than -Os, and for Emscripten it also enables Wasm-specific optimizations affecting the glue JavaScript. Combined with link-time optimization and fewer Emscripten APIs, this reduced a Wasm binary and its JS glue by 435 kB total, with the JS glue itself shrinking from 307 kB to 72 kB. Developers tuning Wasm bundle size can keep tabs on Emscripten optimization tricks like this via daily.dev."}},{"@type":"Question","name":"How can I speed up checksum calculation when loading Erlang BEAM modules at startup?","acceptedAnswer":{"@type":"Answer","text":"Replacing MD5 with the XXH3 hash algorithm cut module checksumming time from 20 ms to under one millisecond in a browser-based BEAM VM. MD5 remains the default in standard OTP because it's deeply embedded in the term serialization format, but switching breaks distribution compatibility between nodes using different hash algorithms. Teams optimizing Erlang or Elixir startup performance can track low-level BEAM tuning tips on daily.dev."}}]}
```

