Choosing Between OCaml Native Code and Bytecode Compilation
Guide to choosing OCaml native code versus bytecode based on performance, size, portability, and debugging needs, with a build and validation example.
07 Oct 2026, 23:19 UTC

Decision and Constraints
When building an OCaml project you must decide whether to produce a native executable with ocamlopt or a bytecode executable with ocamlc (run by ocamlrun). The choice hinges on four practical constraints:
- Target architecture support – native code is tied to the OS/CPU on which it is compiled.
- Runtime size – native binaries embed the runtime and are larger; bytecode relies on a separate interpreter.
- Need for C FFI – both modes support foreign function interfaces, but native code can link directly to C libraries without extra marshalling.
- Build system integration – some build rules (e.g., incremental compilation) behave differently between the two compilers.
Comparison of Supported Options
| Aspect | Native Code (ocamlopt) | Bytecode (ocamlc + ocamlrun) |
|---|---|---|
| Execution speed | ~2‑5× faster for compute‑intensive workloads | Baseline speed; interpreter overhead |
| Binary size | Larger (includes native code and runtime) | Smaller (bytecode only; interpreter shared) |
| Compile time | Longer due to optimisation and code generation | Shorter; emits portable bytecode |
| Portability | Platform‑specific; must be recompiled for each OS/CPU | Portable across any system with a compatible OCaml runtime |
| Debugging | Limited source‑level info; requires ocamldebug with native support | Easier source‑level debugging with ocamldebug |
| Startup latency | Higher (larger executable to load) | Lower for very short‑lived scripts |
Trade‑offs
Prefer native code when:
- The application is a long‑running server or performance‑critical CLI tool.
- You need minimal latency after startup.
- You are willing to maintain separate builds for each target platform.
Prefer bytecode when:
- You distribute scripts or teaching material and want a single binary to run anywhere OCaml is installed.
- Fast iteration during development is more important than peak performance.
- You want simpler debugging workflows.
Concrete Implementation and Validation
To see the differences in practice, compile the following recursive Fibonacci program with both targets, then compare size and execution time.
Sample OCaml Program
let rec fib n =
if n <= 1 then n else fib (n-1) + fib (n-2)
let () =
let n = int_of_string Sys.argv.(1) in
Printf.printf "fib(%d) = %d\n" n (fib n)
Save this as fib.ml.
Build Commands
Run these in a terminal with a standard OCaml installation (≥ 4.14). No special privileges are required.
# Native code build
ocamlopt -o fib.native fib.ml
# Bytecode build
ocamlc -o fib.byte fib.ml
Verification Steps
- Check the resulting file sizes:
ls -lh fib.native fib.byte
- Measure execution time for a modest input (e.g.,
n=40) using thetimeshell builtin:
time ./fib.native 40
time ./fib.byte 40
- Test bytecode portability: copy
fib.byteto another Linux distribution or macOS whereocamlrunis available and run it:
ocamlrun fib.byte 40
- Confirm native non‑portability: attempt to run
fib.nativeon a machine with a different CPU architecture (e.g., ARM binary on x86_64). The execution will fail with a “cannot execute binary file” error.
These steps let you observe the trade‑offs without relying on claimed measurements. Adjust the input n to suit your hardware; larger values increase runtime and make timing differences more visible.
Limitations and Practical Checks
- Native binaries cannot be run on a different OS/CPU without recompilation; ensure your CI builds for each target you intend to support.
- Bytecode execution requires the OCaml runtime (
ocamlrun) to be present; verify its version matches the one used for compilation (ocamlrun -version). - The simple Fibonacci example is compute‑bound; real‑world programs with I/O or FFI may show different ratios. Validate with a representative workload from your project.
By following the table, trade‑off discussion, and verification steps above, you can make an informed decision about whether to target native code or bytecode for your OCaml artifact.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.