pybevy_bytecodevm
A high-performance bytecode virtual machine for executing lazy mathematical expressions on ECS component fields in batch operations.
Overview
pybevy_bytecodevm is a stack-based bytecode compiler and interpreter designed for minimal overhead execution of mathematical expressions across large numbers of entities in the Bevy ECS. It powers PyBevy's View API, enabling 30-50x performance improvements over traditional Python Query iteration.
Features
- Stack-based VM: Simple, cache-friendly bytecode execution (~2-5ns per operation)
- Expression AST: Parse Python expressions into an optimizable intermediate representation
- Bytecode Compilation: Convert expression trees to linear bytecode with constant folding
- Type Support: Multiple field types (f32, f64, i32, i64, u32, u64, bool) with f64 internal precision
- Rich Operations: Arithmetic, trigonometric, comparison, logical, and random operations
- Deterministic Random: Per-entity seeded randomness for reproducible simulations
- Reduction Mode: Evaluate expressions without storing results (for filtering/aggregation)
Architecture
Python Expression → RustExpr AST → Compiler → CompiledBytecode → VM Execution
Components
RustExpr(expr.rs): Abstract Syntax Tree representing mathematical expressionsCompiler(bytecode.rs): Converts AST to optimized bytecode with constant poolVM(bytecode.rs): Executes bytecode on entity component dataCompiledBytecode(bytecode.rs): Compiled bytecode ready for execution
Performance
The bytecode VM is optimized for:
- Cache locality: Linear bytecode array (no tree traversal)
- Minimal overhead: Simple stack operations with no recursion
- Parallel execution: Read-only bytecode perfect for
par_iter_mut - Pre-resolved offsets: Component field locations computed at compile time
Example Usage
Compiling an Expression
use ;
// Expression: pos.x = pos.x + vel.x * dt
let mut compiler = new;
// Build expression AST
let expr = Add;
// Compile to bytecode
expr.compile;
compiler.optimize; // Apply peephole optimizations
let bytecode = compiler.finalize;
Executing Bytecode
use VM;
let mut vm = VMnew;
// field_ptrs: one pointer per field registered with the compiler,
// pointing to the field's memory for this entity.
// entity_index: the entity's index, used for deterministic random seeding.
let mut pos_x: f32 = 100.0;
let mut vel_x: f32 = 5.0;
let field_ptrs: & = &;
let entity_index: usize = 42;
unsafe
// pos_x is now updated in-place
Reduction Mode
// Evaluate an expression and return the result without storing.
// Useful for filtering or aggregation.
let mut health: f32 = 30.0;
let field_ptrs: & = &;
let entity_index: usize = 7;
let result = unsafe ;
// result contains the final stack value (e.g. a boolean comparison result as 0.0/1.0)
Bytecode Example
Expression: pos.x = pos.x + vel.x * dt
Bytecode:
PushField(0) // Push pos.x
PushField(1) // Push vel.x
PushConst(0) // Push dt from constant pool
Mul // vel.x * dt
Add // pos.x + (vel.x * dt)
StoreField(0) // Store to pos.x
Supported Operations
Arithmetic
- Add, Sub, Mul, Div, Pow, Neg, Mod
Trigonometric
- Sin, Cos, Tan, Asin, Acos, Atan
Numeric
- Sqrt, Abs, Floor, Ceil, Round, Min, Max, Clamp
- Exp, Ln, Log10, Log2, Sign, Fract, Lerp
Comparison
- Eq, Ne, Lt, Le, Gt, Ge
Logical
- And, Or, Not
Conditional
- Where (ternary operator:
where(condition, true_value, false_value))
Random
- Random (deterministic per-entity [0.0, 1.0))
- RandomRange (deterministic per-entity [min, max))
Optimizations
The compiler applies peephole optimizations including:
- Constant folding:
5.0 + 3.0→8.0at compile time - Constant deduplication: Shared constant pool with bit-exact matching
Integration with PyBevy
This crate is used internally by PyBevy's View API:
# Python code
=
=
=
# Compiles to bytecode and executes via VM
= + *
Safety
The VM uses unsafe for direct memory access to component fields. Callers must ensure:
- All field pointers are valid and properly aligned
- Field pointers remain valid for the duration of execution
- No concurrent mutations to the same memory
These safety requirements are guaranteed by Bevy's ECS query system.
Testing
Run the test suite:
The crate includes comprehensive tests for:
- Arithmetic operations
- Trigonometric functions
- Comparison operators
- Logical operators
- Conditional selection
- Constant folding optimization
- Field storage and retrieval