Zamin Docs

Performance

Zamin is designed for speed. This page covers the VM architecture, benchmark comparisons, optimization techniques, and practical tips for writing performant Zamin code.

Overview

Zamin's runtime is built around three key components:

  • Bytecode Compilation - Source code is compiled to compact bytecode before execution. The compiler performs constant folding, dead code elimination, and peephole optimizations at compile time.
  • Register-Based VM - The virtual machine executes bytecode using a register-based instruction set, reducing memory traffic compared to stack-based designs.
  • Mark-and-Sweep Garbage Collector - A generational, non-moving GC with incremental collection phases minimizes pause times while keeping memory overhead low.

Benchmarks vs Python 3

Real-world benchmarks comparing Zamin and Python 3 on the same machine using time for wall-clock measurement. Lower is better.

BenchmarkZaminPython 3Ratio
Recursive fib(32)1.51s0.35s4.3x
Integer loop (5M ops)0.47s0.53s0.9x
String concat (100K)3.14s0.23s13.4x
List push (500K)0.13s0.09s1.5x

Zamin excels at tight integer loops — often matching or exceeding CPython — but is slower on string and list operations due to bytecode interpreter overhead.

Optimization Impact

The peephole optimizer and specialized integer opcodes provide significant speedups on core VM primitives:

OptimizationImpact
Raw byte dispatch15-25% faster instruction dispatch vs function pointer table
Specialized integer opcodesAvoids boxing and type-checks in hot integer loops
Constant foldingEliminates runtime evaluation of constant expressions
Jump threadingCollapses chains of unconditional jumps
Dead code eliminationRemoves unreachable branches after return/throw

Optimization Techniques

Raw Byte Dispatch

The VM main loop uses a raw byte dispatch (computed gotos on GCC/Clang, switch-based fallback) instead of a function-pointer dispatch table. This eliminates an indirect call per instruction, giving a consistent 15-25% improvement across all workloads.

Specialized Integer Opcodes

Frequently used integer operations have dedicated opcodes that avoid the generic operand dispatch. For example, OP_ADD_INT_IMM adds a small constant to an integer register without boxing or type checking, and OP_LOAD_INT_CONST loads a compile-time constant directly into a register.

Peephole Optimizer

The bytecode compiler runs a peephole optimizer that performs:

  • Constant folding - Compile-time evaluation of constant expressions
  • Dead code elimination - Removal of unreachable branches and unused assignments
  • Strength reduction - Replacing expensive operations with cheaper equivalents (e.g., x * 2 becomes x << 1)
  • Jump chaining - Collapsing chains of unconditional jumps into a single target
  • Opcode merging - Combining sequences like load-then-store into a single fused operation

Performance Tips

  • Use f-strings for concatenation - "Hello {name}" is faster than "Hello " + name because it avoids intermediate string allocations.
  • Pre-allocate lists - Use list.new(capacity) when you know the final size to avoid repeated reallocations.
  • Prefer local variables - Local variable access is ~10x faster than global variable access in the VM.
  • Use iterators over index loops - Iterator-based loops avoid bounds checking on each iteration.
  • Avoid repeated allocation in loops - Move invariant computations outside the loop body. Create strings and lists once and reuse them.
  • Use zamin build for production - Building a standalone binary enables additional AOT optimizations that the interpreter cannot perform.
  • Profile before optimizing - Use zamin run --disassemble to inspect bytecode and identify hotspots.
Edit this page on GitHub Last updated: July 2026