Slim: 367.2 i/s (fastest)
ERB: 298.8 i/s
Phlex: 279.4 i/s (pure Ruby!)
Ruby2html templates: 118.4 i/s (2.36x slower than Phlex)
Ruby2html components:119.4 i/s
-
Direct Instantiation vs Template Handling
- Phlex:
render PhlexView.new(data)- direct class instantiation - Ruby2html: Rails template handler →
instance_exec→ context setup - Impact: Template handling adds overhead
- Phlex:
-
No Instance Variable Copying
- Phlex: Data passed as constructor argument
- Ruby2html: Copies all instance variables from controller context
- Impact: Even with our optimizations, copying still has cost
-
Buffer Management
- Phlex: Highly optimized string buffer with minimal allocations
- Ruby2html: Creates new Render instance per request, pre-allocates buffers
- Impact: Phlex's buffer reuse is more efficient
-
Method Call Overhead
- Phlex: Optimized internal method dispatch
- Ruby2html: Block calls for every tag,
method_missingdelegation - Impact: Higher method call overhead
-
String Interpolation
- Ruby2html template: Uses
plainmethod for every interpolated string - Phlex: Direct string handling in blocks
- Impact: Extra method calls in Ruby2html
- Ruby2html template: Uses
We implemented 7 major C-level optimizations:
- ✅ C Tag Generation - 2-3x faster tag operations
- ✅ SIMD HTML Escaping (SSE4.2) - 3-10x faster for clean strings
- ✅ Cached Instance Variables - Reduced per-render overhead
- ✅ Direct Hash Iteration - Eliminated array allocations
- ✅ Lookup Table Escaping - Branch-free character lookups
- ✅ Type Optimization - size_t, unsigned types
- ✅ Compiler Hints - const, restrict, inline, loop unrolling
Result: 2-4x faster than original, but still 2.36x slower than Phlex
We optimized the wrong layer:
- ✅ Optimized: Tag generation, escaping, attributes (micro-level)
- ❌ Not optimized: Template handling, instance variables, method dispatch (macro-level)
Analogy: We made the engine faster, but Phlex has a lighter car.
- Minimal Abstraction: Direct Ruby code, no template parsing
- Zero Context Overhead: No instance variable copying
- Optimized for Common Case: Fast path for trusted content
- Smart Buffer Management: Reuses buffers efficiently
- Rails Template Integration: Can't avoid template handler overhead
- View Context Coupling: Must work with controller instance variables
- Escaping by Default: Conservative (secure) but slower
- Block-Based DSL: More flexible but higher overhead
When to use Ruby2html:
- Need
.html.rbtemplate files (Rails conventions) - Want automatic HTML escaping (security-first)
- Prefer template-based architecture
When to use Phlex:
- Maximum performance is critical
- Component-based architecture preferred
- Can manage content escaping manually
- Bypass Template Handler - Direct component rendering like Phlex
- Eliminate Instance Variable Copying - Pass data explicitly
- Optimize
plainMethod - Inline or eliminate extra calls - Buffer Pooling - Reuse buffers across requests
- JIT Compilation - Cache compiled templates
Our C optimizations are excellent for the code they optimize, achieving:
- 2-4x improvement over original Ruby2html
- Branch-free operations
- SIMD acceleration
- Minimal allocations
However, Phlex is faster because of superior architecture, not better optimizations:
- No template overhead
- No context copying
- Minimal method calls
- Optimized for the common case
Key Lesson: Architecture matters more than micro-optimizations. A well-designed pure Ruby solution (Phlex) can beat a heavily optimized solution with architectural overhead (Ruby2html + C extensions).