Differences from Standard BEAM
Relevant source files
The following files were used as context for generating this wiki page:
AtomVM is a ground-up implementation of the Bogdan Erlang Abstract Machine (BEAM) specifically designed for resource-constrained IoT devices, such as the ESP32 and STM32 microcontrollers. While it aims for compatibility with standard Erlang/OTP BEAM, significant architectural and functional differences exist to accommodate the limitations of embedded environments, where memory may be as low as 128KB.
The primary design philosophy of AtomVM prioritizes minimizing memory consumption and heap fragmentation over raw performance. Unlike the standard BEAM which is built for massive scalability on server-class hardware, AtomVM is optimized to provide a functional subset of Erlang and Elixir features on tiny systems.
Sources: doc/src/welcome-to-atomvm.md:14-25, doc/src/welcome-to-atomvm.md:65-71
Core VM Limitations
AtomVM omits several key features of the standard BEAM to maintain a small footprint.
Integer Precision and Overflows
Standard BEAM supports arbitrary-precision integers. In contrast, AtomVM supports integers up to 256-bit with a separate sign flag (meaning INTEGER_MAX = -INTEGER_MIN). Operations exceeding this capacity result in an overflow error, whereas standard BEAM would simply grow the integer size.
Sources: doc/src/differences-with-beam.md:39-65
Binary and Bit Syntax
AtomVM supports binaries and binary pattern matching, but its bit syntax is limited. It does not support "bitstrings" (binaries where the number of bits is not a multiple of 8).
Sources: doc/src/differences-with-beam.md:92-101
Code Management
- Code Reloading: AtomVM does not currently support hot code reloading, a hallmark feature of standard BEAM.
- Onload: The
-onloadattribute, frequently used in BEAM for NIF initialization, is not implemented.
Sources: doc/src/differences-with-beam.md:103-106, doc/src/differences-with-beam.md:142-144
Memory Management and Scheduling
The following diagram illustrates how AtomVM processes (Contexts) are managed within the GlobalContext compared to the complex multi-threaded schedulers of standard BEAM.
The diagram shows the simplified process ring structures used by AtomVM to track process states and dispatch them to scheduler threads.
Sources: doc/src/atomvm-internals.md:104-125, doc/src/atomvm-internals.md:214-225
| Feature | Standard BEAM | AtomVM |
|---|---|---|
| Garbage Collection | Generational, tuned for throughput | Frequent, aggressive reclamation |
| Heap Strategy | Flexible growth | Very aggressive growth and fragmentation control |
| SMP Support | Highly optimized for many cores | One scheduler per core, simplified locking |
| Dirty Schedulers | Supported for long-running NIFs | Not implemented; NIFs must return quickly |
Sources: doc/src/differences-with-beam.md:123-132, doc/src/differences-with-beam.md:146-148
Binary Distribution and Loading
AtomVM introduces a specialized aggregation format called Packbeam (.avm) to facilitate code deployment on flash-based systems.
Packbeam vs. Standard BEAM Files
Standard BEAM loads individual .beam files from the filesystem. AtomVM aggregates these into a single .avm file to minimize filesystem overhead on microcontrollers.
The workflow from source to deployment, highlighting the aggregation into the Packbeam format.
Sources: doc/src/packbeam-format.md:11-20, doc/src/getting-started-guide.md:200-205
AVM File Constraints
- Compressed Literals: AtomVM requires literals in BEAM files to be uncompressed because the runtime lacks
zlibsupport to minimize memory and CPU cycles. Standard BEAM typically compresses theLitTchunk. - Stripped Chunks: AtomVM strips non-essential chunks (like debug info) from BEAM files, retaining only
AtU8,Code,ExpT,LocT,ImpT,LitU,FunT,StrT, andLitT.
Sources: doc/src/packbeam-format.md:65-88, doc/src/atomvm-tooling.md:146-155
Standard Library and OTP Differences
The AtomVM standard library is a "limited but functional subset" of Erlang/OTP.
- OTP Frameworks:
gen_server,gen_statem,supervisor,proc_lib, andsysare implemented as lightweight subsets. Many advanced OTP features are absent to save space. - Identification: Code can distinguish the environment using
erlang:system_info(machine). Standard BEAM returns"BEAM", while AtomVM returns"ATOM". - Exceptions: Exception messages and stacktraces are less detailed. For instance, a
function_clauseerror in AtomVM does not include the arguments that failed to match.
Sources: doc/src/differences-with-beam.md:20-25, doc/src/differences-with-beam.md:31-33, doc/src/differences-with-beam.md:162-165
Native Interfaces: NIFs and Ports
While AtomVM supports NIFs and Ports, they differ from standard BEAM in their linking and execution:
- Static Linking: Most embedded environments do not support dynamic loading. NIFs and Ports must be linked into the AtomVM binary at compile time.
- Execution: Ports are executed directly by the schedulers. Both NIFs and Ports are expected to be "well-behaved" and return quickly to avoid blocking the single-threaded or low-core schedulers.
- Wasm/Browser Nuances: In the WebAssembly port, NIFs like
emscripten:run_script/2handle the dispatching of JavaScript to the main browser thread from worker-based scheduler threads.
Sources: doc/src/differences-with-beam.md:138-150, doc/src/atomvm-internals.md:447-458
Conclusion
AtomVM is not a drop-in replacement for the standard BEAM but a specialized subset. Its differences—specifically in integer handling, memory management, and code packaging—are intentional trade-offs required to bring the Erlang concurrency model to microcontrollers with strictly limited resources. Developers must adapt standard OTP patterns to fit within the constraints of the AtomVM environment.