diff --git a/BENCHMARKING.md b/BENCHMARKING.md
new file mode 100644
index 0000000..0dfdc7e
--- /dev/null
+++ b/BENCHMARKING.md
@@ -0,0 +1,88 @@
+# Memory Allocation Analysis for Zero-Allocation Rendering
+
+This guide explains how to use the memory profiling tools provided to identify and optimize memory allocation hotspots in the Twig template engine.
+
+## Running the Memory Analysis
+
+To run a comprehensive memory analysis and generate reports:
+
+```bash
+./scripts/analyze_memory.sh
+```
+
+This script will:
+1. Run benchmarks with memory allocation tracking
+2. Generate heap allocation profiles
+3. Analyze the profiles to identify allocation hotspots
+4. Create a comprehensive report in the `reports/` directory
+
+## Interpreting the Results
+
+The analysis generates several files:
+
+- `reports/memory_optimization_report.md` - Main report with allocation analysis and recommendations
+- `reports/benchmark_results.txt` - Raw benchmark results with memory statistics
+- `reports/top_allocations.txt` - Top memory allocation sources from pprof
+- `reports/heap.prof` - Heap allocation profile that can be analyzed with `go tool pprof`
+- `reports/simple_profile.txt`, `reports/medium_profile.txt`, `reports/complex_profile.txt` - Profile results by template complexity
+
+## Using Individual Profiling Tools
+
+### Running Benchmarks with Memory Stats
+
+```bash
+go test -run=^$ -bench=. -benchmem ./memory_profile_test.go
+```
+
+This command runs all benchmarks and reports allocations per operation.
+
+### Generating a Heap Profile
+
+```bash
+go test -run=^$ -bench=BenchmarkRenderComplexTemplate -benchmem -memprofile=heap.prof ./memory_profile_test.go
+```
+
+### Analyzing the Heap Profile
+
+```bash
+go tool pprof -alloc_space heap.prof
+```
+
+Common pprof commands:
+- `top` - Show top allocation sources
+- `list FunctionName` - Show line-by-line allocations in a function
+- `web` - Open a web visualization of the profile
+
+### Using the Profiling Tool
+
+For targeted profiling of specific template complexity:
+
+```bash
+go run cmd/profile/main.go -complexity=3 -iterations=1000 -memprofile=complex.prof
+```
+
+Options:
+- `-complexity` - Template complexity level (1=simple, 2=medium, 3=complex)
+- `-iterations` - Number of template renders to perform
+- `-memprofile` - Output file for memory profile
+- `-cpuprofile` - Output file for CPU profile (optional)
+
+## Zero-Allocation Implementation Strategy
+
+Based on the profile results, implement optimizations in this order:
+
+1. **Object Pooling** - Implement pools for all temporary objects
+2. **String Operations** - Optimize string handling to avoid allocations
+3. **Context Management** - Improve context creation, cloning, and cleanup
+4. **Expression Evaluation** - Minimize allocations in expression execution
+5. **Buffer Management** - Reuse output buffers with proper pooling
+
+## Testing Your Optimizations
+
+After each optimization, run the memory benchmarks again to verify the reduction in allocations:
+
+```bash
+go test -run=^$ -bench=BenchmarkRender -benchmem ./memory_profile_test.go
+```
+
+The goal is to see zero (or minimal) allocations per operation in the `allocs/op` column.
\ No newline at end of file
diff --git a/cmd/profile/main.go b/cmd/profile/main.go
new file mode 100644
index 0000000..89d7a92
--- /dev/null
+++ b/cmd/profile/main.go
@@ -0,0 +1,302 @@
+// Package main provides a simple utility to run memory profiling on the Twig template engine
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "runtime"
+ "runtime/pprof"
+ "strconv"
+ "time"
+
+ "github.com/semihalev/twig"
+)
+
+func main() {
+ // Command-line flags
+ cpuProfile := flag.String("cpuprofile", "", "write cpu profile to file")
+ memProfile := flag.String("memprofile", "", "write memory profile to file")
+ complexityLevel := flag.Int("complexity", 2, "template complexity level (1-3)")
+ iterations := flag.Int("iterations", 1000, "number of template renders to perform")
+ flag.Parse()
+
+ // CPU profiling if requested
+ if *cpuProfile != "" {
+ f, err := os.Create(*cpuProfile)
+ if err != nil {
+ log.Fatal("could not create CPU profile: ", err)
+ }
+ defer f.Close()
+ if err := pprof.StartCPUProfile(f); err != nil {
+ log.Fatal("could not start CPU profile: ", err)
+ }
+ defer pprof.StopCPUProfile()
+ }
+
+ // Run the appropriate benchmark based on complexity level
+ var totalTime time.Duration
+ var totalAllocBytes uint64
+ var numGC uint32
+
+ // Record memory stats before
+ var memStatsBefore runtime.MemStats
+ runtime.ReadMemStats(&memStatsBefore)
+
+ switch *complexityLevel {
+ case 1:
+ totalTime = runSimpleTemplateBenchmark(*iterations)
+ case 2:
+ totalTime = runMediumTemplateBenchmark(*iterations)
+ case 3:
+ totalTime = runComplexTemplateBenchmark(*iterations)
+ default:
+ log.Fatalf("Invalid complexity level: %d (must be 1-3)", *complexityLevel)
+ }
+
+ // Record memory stats after
+ var memStatsAfter runtime.MemStats
+ runtime.ReadMemStats(&memStatsAfter)
+
+ // Calculate allocation statistics
+ totalAllocBytes = memStatsAfter.TotalAlloc - memStatsBefore.TotalAlloc
+ numGC = memStatsAfter.NumGC - memStatsBefore.NumGC
+
+ // Report results
+ fmt.Printf("=== Twig Memory Profiling Results ===\n")
+ fmt.Printf("Complexity Level: %d\n", *complexityLevel)
+ fmt.Printf("Total Iterations: %d\n", *iterations)
+ fmt.Printf("Total Time: %v\n", totalTime)
+ fmt.Printf("Time per Iteration: %v\n", totalTime/time.Duration(*iterations))
+ fmt.Printf("Total Memory Allocated: %d bytes\n", totalAllocBytes)
+ fmt.Printf("Memory per Iteration: %d bytes\n", totalAllocBytes/uint64(*iterations))
+ fmt.Printf("Number of GCs: %d\n", numGC)
+
+ // Memory profiling if requested
+ if *memProfile != "" {
+ f, err := os.Create(*memProfile)
+ if err != nil {
+ log.Fatal("could not create memory profile: ", err)
+ }
+ defer f.Close()
+ runtime.GC() // Get up-to-date statistics
+ if err := pprof.WriteHeapProfile(f); err != nil {
+ log.Fatal("could not write memory profile: ", err)
+ }
+ }
+}
+
+// runSimpleTemplateBenchmark runs a benchmark with a simple template
+func runSimpleTemplateBenchmark(iterations int) time.Duration {
+ engine := twig.New()
+ err := engine.RegisterString("simple", "Hello, {{ name }}!")
+ if err != nil {
+ log.Fatalf("Error registering template: %v", err)
+ }
+
+ context := map[string]interface{}{
+ "name": "World",
+ }
+
+ startTime := time.Now()
+ for i := 0; i < iterations; i++ {
+ var buf bytes.Buffer
+ template, _ := engine.Load("simple")
+ err := template.RenderTo(&buf, context)
+ if err != nil {
+ log.Fatalf("Error rendering template: %v", err)
+ }
+ }
+ return time.Since(startTime)
+}
+
+// runMediumTemplateBenchmark runs a benchmark with a medium complexity template
+func runMediumTemplateBenchmark(iterations int) time.Duration {
+ engine := twig.New()
+ templateContent := `
+
+
{{ user.name }}
+
Age: {{ user.age }}
+ {% if user.bio %}
+
{{ user.bio|capitalize }}
+ {% else %}
+
No bio available
+ {% endif %}
+
+ {% for skill in user.skills %}
+ - {{ skill.name }} ({{ skill.level }})
+ {% endfor %}
+
+
+`
+ err := engine.RegisterString("medium", templateContent)
+ if err != nil {
+ log.Fatalf("Error registering template: %v", err)
+ }
+
+ context := map[string]interface{}{
+ "user": map[string]interface{}{
+ "name": "John Doe",
+ "age": 30,
+ "bio": "web developer and open source enthusiast",
+ "skills": []map[string]interface{}{
+ {"name": "Go", "level": "Advanced"},
+ {"name": "JavaScript", "level": "Intermediate"},
+ {"name": "CSS", "level": "Beginner"},
+ {"name": "HTML", "level": "Advanced"},
+ },
+ },
+ }
+
+ startTime := time.Now()
+ for i := 0; i < iterations; i++ {
+ var buf bytes.Buffer
+ template, _ := engine.Load("medium")
+ err := template.RenderTo(&buf, context)
+ if err != nil {
+ log.Fatalf("Error rendering template: %v", err)
+ }
+ }
+ return time.Since(startTime)
+}
+
+// runComplexTemplateBenchmark runs a benchmark with a complex template
+func runComplexTemplateBenchmark(iterations int) time.Duration {
+ engine := twig.New()
+
+ // Base template
+ baseTemplate := `
+
+
+
+ {% block title %}Default Title{% endblock %}
+ {% block styles %}
+
+ {% endblock %}
+
+
+ {% block header %}Default Header{% endblock %}
+ {% block content %}Default Content{% endblock %}
+
+
+
+`
+ err := engine.RegisterString("base", baseTemplate)
+ if err != nil {
+ log.Fatalf("Error registering template: %v", err)
+ }
+
+ // Macro template
+ macroTemplate := `
+{% macro renderProduct(product) %}
+
+
{{ product.name }}
+
{{ product.description|capitalize }}
+
{{ product.price|format("$%.2f") }}
+ {% if product.tags %}
+
+ {% for tag in product.tags %}
+ {{ tag }}
+ {% endfor %}
+
+ {% endif %}
+
+{% endmacro %}
+`
+ err = engine.RegisterString("macros", macroTemplate)
+ if err != nil {
+ log.Fatalf("Error registering template: %v", err)
+ }
+
+ // Page template
+ pageTemplate := `
+{% extends "base" %}
+{% import "macros" as components %}
+
+{% block title %}{{ page.title }} - {{ parent() }}{% endblock %}
+
+{% block styles %}
+ {{ parent() }}
+
+{% endblock %}
+
+{% block header %}
+ {{ page.title }}
+
+{% endblock %}
+
+{% block content %}
+
+
Product List ({{ products|length }} items)
+
+ {% for product in products %}
+ {{ components.renderProduct(product) }}
+ {% endfor %}
+
+ {% set total = 0 %}
+ {% for product in products %}
+ {% set total = total + product.price %}
+ {% endfor %}
+
+
+
Total products: {{ products|length }}
+
Average price: {{ (total / products|length)|format("$%.2f") }}
+
Price range: {{ products|map(p => p.price)|sort|first|format("$%.2f") }} - {{ products|map(p => p.price)|sort|last|format("$%.2f") }}
+
+
+{% endblock %}
+`
+ err = engine.RegisterString("page", pageTemplate)
+ if err != nil {
+ log.Fatalf("Error registering template: %v", err)
+ }
+
+ // Create a complex context with various data types
+ products := make([]map[string]interface{}, 20)
+ for i := 0; i < 20; i++ {
+ products[i] = map[string]interface{}{
+ "id": i + 1,
+ "name": "Product " + strconv.Itoa(i+1),
+ "description": "This is product " + strconv.Itoa(i+1) + " with detailed information.",
+ "price": 15.0 + float64(i)*1.5,
+ "tags": []string{"tag1", "tag2", "tag3"}[0:1+(i%3)],
+ }
+ }
+
+ context := map[string]interface{}{
+ "page": map[string]interface{}{
+ "title": "Product Catalog",
+ },
+ "navigation": []map[string]interface{}{
+ {"url": "/", "text": "Home"},
+ {"url": "/products", "text": "Products"},
+ {"url": "/about", "text": "About"},
+ {"url": "/contact", "text": "Contact"},
+ },
+ "products": products,
+ }
+
+ startTime := time.Now()
+ for i := 0; i < iterations; i++ {
+ var buf bytes.Buffer
+ template, _ := engine.Load("page")
+ err := template.RenderTo(&buf, context)
+ if err != nil {
+ log.Fatalf("Error rendering template: %v", err)
+ }
+ }
+ return time.Since(startTime)
+}
\ No newline at end of file
diff --git a/memory_analysis.go b/memory_analysis.go
new file mode 100644
index 0000000..8195da5
--- /dev/null
+++ b/memory_analysis.go
@@ -0,0 +1,138 @@
+// This file contains a utility function to generate a memory allocation report
+package twig
+
+import (
+ "fmt"
+ "os"
+ "runtime/pprof"
+ "sort"
+ "strings"
+)
+
+// RunMemoryAnalysis runs a comprehensive memory analysis on the template engine
+// and generates a report of allocation hotspots.
+func RunMemoryAnalysis() error {
+ // Create a memory profile output file
+ f, err := os.Create("twig_memory.pprof")
+ if err != nil {
+ return fmt.Errorf("failed to create memory profile: %v", err)
+ }
+ defer f.Close()
+
+ // Write a memory profile with detailed allocation info
+ if err := pprof.WriteHeapProfile(f); err != nil {
+ return fmt.Errorf("failed to write memory profile: %v", err)
+ }
+
+ // Generate a report based on the memory profile
+ reportFile, err := os.Create("twig_memory_report.txt")
+ if err != nil {
+ return fmt.Errorf("failed to create report file: %v", err)
+ }
+ defer reportFile.Close()
+
+ // Header information
+ fmt.Fprintf(reportFile, "# TWIG MEMORY ALLOCATION REPORT\n\n")
+ fmt.Fprintf(reportFile, "This report shows memory allocation hotspots in the Twig template engine.\n")
+ fmt.Fprintf(reportFile, "Optimizing these areas will help achieve a zero-allocation rendering path.\n\n")
+
+ // Instructions for viewing the profile
+ fmt.Fprintf(reportFile, "## How to View the Profile\n\n")
+ fmt.Fprintf(reportFile, "Run this command to analyze the memory profile:\n")
+ fmt.Fprintf(reportFile, "```\ngo tool pprof -alloc_space twig_memory.pprof\n```\n\n")
+ fmt.Fprintf(reportFile, "Common commands in the pprof interface:\n")
+ fmt.Fprintf(reportFile, "- `top`: Shows the top allocation sources\n")
+ fmt.Fprintf(reportFile, "- `list FunctionName`: Shows line-by-line allocations in a function\n")
+ fmt.Fprintf(reportFile, "- `web`: Opens a web browser with a visualization of the profile\n\n")
+
+ // Benchmarking instructions
+ fmt.Fprintf(reportFile, "## Benchmark Results\n\n")
+ fmt.Fprintf(reportFile, "Run this command to see allocation statistics:\n")
+ fmt.Fprintf(reportFile, "```\ngo test -run=^$ -bench=. -benchmem ./memory_profile_test.go\n```\n\n")
+
+ // Generate tables for common allocation sources
+ generateAllocationTables(reportFile)
+
+ // Recommendation section
+ fmt.Fprintf(reportFile, "## Optimization Recommendations\n\n")
+ fmt.Fprintf(reportFile, "Based on common patterns in template engines, consider these areas for optimization:\n\n")
+
+ recommendations := []string{
+ "**Context Creation**: Pool and reuse RenderContext objects",
+ "**String Concatenation**: Replace with direct WriteString to output buffers",
+ "**Expression Evaluation**: Eliminate intermediate allocations during evaluation",
+ "**Filter Chain Evaluation**: Reuse filter result objects",
+ "**Map Creation**: Pre-size maps and reuse map objects where possible",
+ "**String Conversions**: Use allocation-free ToString implementations for common types",
+ "**Buffer Management**: Pool and reuse output buffers",
+ "**Node Creation**: Extend the node pool to cover all node types",
+ "**Slice Allocations**: Pre-allocate slices with expected capacity",
+ }
+
+ for _, rec := range recommendations {
+ fmt.Fprintf(reportFile, "- %s\n", rec)
+ }
+
+ // Implementation strategy
+ fmt.Fprintf(reportFile, "\n## Implementation Strategy\n\n")
+ fmt.Fprintf(reportFile, "1. **Start with high-impact areas**: Focus on the top allocation sources first\n")
+ fmt.Fprintf(reportFile, "2. **Implement pools for all temporary objects**: Especially RenderContext objects\n")
+ fmt.Fprintf(reportFile, "3. **Optimize string operations**: String handling is often a major source of allocations\n")
+ fmt.Fprintf(reportFile, "4. **Review all map/slice creations**: Pre-size collections where possible\n")
+ fmt.Fprintf(reportFile, "5. **Incremental testing**: Benchmark after each optimization to measure impact\n\n")
+
+ fmt.Fprintf(reportFile, "## Final Notes\n\n")
+ fmt.Fprintf(reportFile, "Remember that some allocations are unavoidable, especially for dynamic templates.\n")
+ fmt.Fprintf(reportFile, "The goal is to eliminate allocations in the core rendering path, prioritizing the\n")
+ fmt.Fprintf(reportFile, "most frequent operations for maximum performance impact.\n")
+
+ return nil
+}
+
+// Helper function to generate allocation tables for common sources
+func generateAllocationTables(w *os.File) {
+ // String Handling Table
+ fmt.Fprintf(w, "### String Operations\n\n")
+ fmt.Fprintf(w, "| Operation | Allocation Issue | Optimization |\n")
+ fmt.Fprintf(w, "|-----------|-----------------|-------------|\n")
+ stringOps := [][]string{
+ {"String Concatenation", "Creates new strings", "Use WriteString to buffer"},
+ {"Substring Operations", "Creates new strings", "Reuse byte slices when possible"},
+ {"String Conversion", "Boxing/unboxing", "Specialized ToString methods"},
+ {"Format/Replace", "Creates intermediate strings", "Write directly to output buffer"},
+ }
+ for _, op := range stringOps {
+ fmt.Fprintf(w, "| %s | %s | %s |\n", op[0], op[1], op[2])
+ }
+ fmt.Fprintf(w, "\n")
+
+ // Context Operations Table
+ fmt.Fprintf(w, "### Context Operations\n\n")
+ fmt.Fprintf(w, "| Operation | Allocation Issue | Optimization |\n")
+ fmt.Fprintf(w, "|-----------|-----------------|-------------|\n")
+ contextOps := [][]string{
+ {"Context Creation", "New map allocations", "Pool and reuse context objects"},
+ {"Context Cloning", "Copying maps", "Selective copying or copy-on-write"},
+ {"Variable Lookup", "Interface conversions", "Type-specialized getters"},
+ {"Context Merging", "Map copies for scope", "Prototype or linked contexts"},
+ }
+ for _, op := range contextOps {
+ fmt.Fprintf(w, "| %s | %s | %s |\n", op[0], op[1], op[2])
+ }
+ fmt.Fprintf(w, "\n")
+
+ // Node Operations Table
+ fmt.Fprintf(w, "### Node Operations\n\n")
+ fmt.Fprintf(w, "| Node Type | Allocation Issue | Optimization |\n")
+ fmt.Fprintf(w, "|-----------|-----------------|-------------|\n")
+ nodeOps := [][]string{
+ {"Expression Nodes", "New node for each evaluation", "Pool and reuse node objects"},
+ {"Filter Nodes", "Chained filter allocations", "Intermediate result pooling"},
+ {"Loop Nodes", "Iterator allocations", "Reuse loop context and iterators"},
+ {"Block Nodes", "Block context allocations", "Pool block contexts"},
+ }
+ for _, op := range nodeOps {
+ fmt.Fprintf(w, "| %s | %s | %s |\n", op[0], op[1], op[2])
+ }
+ fmt.Fprintf(w, "\n")
+}
\ No newline at end of file
diff --git a/memory_profile_test.go b/memory_profile_test.go
new file mode 100644
index 0000000..a8d0736
--- /dev/null
+++ b/memory_profile_test.go
@@ -0,0 +1,368 @@
+package twig
+
+import (
+ "bytes"
+ "testing"
+)
+
+// BenchmarkRenderSimpleTemplate benchmarks rendering a simple template with just variables
+func BenchmarkRenderSimpleTemplate(b *testing.B) {
+ engine := New()
+ err := engine.RegisterString("simple", "Hello, {{ name }}!")
+ if err != nil {
+ b.Fatalf("Error registering template: %v", err)
+ }
+
+ context := map[string]interface{}{
+ "name": "World",
+ }
+
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ var buf bytes.Buffer
+ template, _ := engine.Load("simple")
+ _ = template.RenderTo(&buf, context)
+ }
+}
+
+// BenchmarkRenderComplexTemplate benchmarks rendering a template with conditionals, loops, and filters
+func BenchmarkRenderComplexTemplate(b *testing.B) {
+ engine := New()
+ templateContent := `
+
+
{{ title|upper }}
+ {% if showHeader %}
+
+ {% endif %}
+
+ {% for item in items %}
+ - {{ item.name }} - {{ item.price|format("$%.2f") }}
+ {% endfor %}
+
+ {% set total = 0 %}
+ {% for item in items %}
+ {% set total = total + item.price %}
+ {% endfor %}
+
Total: {{ total|format("$%.2f") }}
+
+`
+ err := engine.RegisterString("complex", templateContent)
+ if err != nil {
+ b.Fatalf("Error registering template: %v", err)
+ }
+
+ context := map[string]interface{}{
+ "title": "Product List",
+ "showHeader": true,
+ "user": map[string]interface{}{
+ "name": "John",
+ },
+ "items": []map[string]interface{}{
+ {"name": "Item 1", "price": 10.5},
+ {"name": "Item 2", "price": 15.0},
+ {"name": "Item 3", "price": 8.75},
+ {"name": "Item 4", "price": 12.25},
+ {"name": "Item 5", "price": 9.99},
+ },
+ }
+
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ var buf bytes.Buffer
+ template, _ := engine.Load("complex")
+ _ = template.RenderTo(&buf, context)
+ }
+}
+
+// BenchmarkRenderMacros benchmarks rendering a template with macro definitions and calls
+func BenchmarkRenderMacros(b *testing.B) {
+ engine := New()
+ templateContent := `
+{% macro input(name, value='', type='text') %}
+
+{% endmacro %}
+
+{% macro form(action, method='post') %}
+
+{% endmacro %}
+
+{{ _self.form('/login') }}
+`
+ err := engine.RegisterString("macros", templateContent)
+ if err != nil {
+ b.Fatalf("Error registering template: %v", err)
+ }
+
+ context := map[string]interface{}{
+ "user": map[string]interface{}{
+ "username": "johndoe",
+ },
+ }
+
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ var buf bytes.Buffer
+ template, _ := engine.Load("macros")
+ _ = template.RenderTo(&buf, context)
+ }
+}
+
+// BenchmarkRenderInheritance benchmarks rendering a template with inheritance
+func BenchmarkRenderInheritance(b *testing.B) {
+ engine := New()
+
+ // Base template
+ baseTemplate := `
+
+
+
+ {% block title %}Default Title{% endblock %}
+
+
+ {% block header %}Default Header{% endblock %}
+ {% block content %}Default Content{% endblock %}
+
+
+
+`
+ err := engine.RegisterString("base", baseTemplate)
+ if err != nil {
+ b.Fatalf("Error registering template: %v", err)
+ }
+
+ // Child template
+ childTemplate := `
+{% extends "base" %}
+
+{% block title %}{{ pageTitle }} - {{ parent() }}{% endblock %}
+
+{% block header %}
+ {{ pageTitle }}
+ {{ parent() }}
+{% endblock %}
+
+{% block content %}
+ {% for item in items %}
+ {{ item }}
+ {% endfor %}
+{% endblock %}
+`
+ err = engine.RegisterString("child", childTemplate)
+ if err != nil {
+ b.Fatalf("Error registering template: %v", err)
+ }
+
+ context := map[string]interface{}{
+ "pageTitle": "Products Page",
+ "items": []string{
+ "Product 1",
+ "Product 2",
+ "Product 3",
+ },
+ }
+
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ var buf bytes.Buffer
+ template, _ := engine.Load("child")
+ _ = template.RenderTo(&buf, context)
+ }
+}
+
+// BenchmarkRenderFilters benchmarks heavy use of filter chains
+func BenchmarkRenderFilters(b *testing.B) {
+ engine := New()
+ templateContent := `
+{% set text = "Hello, this is some example text for filtering!" %}
+
+{{ text|upper|trim }}
+{{ text|lower|replace("example", "sample")|capitalize }}
+{{ text|split(" ")|join("-")|upper }}
+{{ text|length }}
+{{ '2023-05-15'|date("Y-m-d") }}
+{{ 123.456|number_format(2, ".", ",") }}
+{{ ['a', 'b', 'c']|join(", ")|upper }}
+{{ text|slice(7, 10)|capitalize }}
+{{ text|replace({"example": "great", "text": "content"}) }}
+{{ text|default("No text provided")|upper }}
+`
+ err := engine.RegisterString("filters", templateContent)
+ if err != nil {
+ b.Fatalf("Error registering template: %v", err)
+ }
+
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ var buf bytes.Buffer
+ template, _ := engine.Load("filters")
+ _ = template.RenderTo(&buf, nil)
+ }
+}
+
+// BenchmarkRenderWithLargeContext benchmarks rendering with a large context
+func BenchmarkRenderWithLargeContext(b *testing.B) {
+ engine := New()
+ templateContent := `
+
+{% for user in users %}
+ - {{ user.id }}: {{ user.name }} ({{ user.email }})
+
+ {% for role in user.roles %}
+ - {{ role }}
+ {% endfor %}
+
+
+{% endfor %}
+
+`
+ err := engine.RegisterString("large_context", templateContent)
+ if err != nil {
+ b.Fatalf("Error registering template: %v", err)
+ }
+
+ // Create a large context with 100 users
+ users := make([]map[string]interface{}, 100)
+ for i := 0; i < 100; i++ {
+ users[i] = map[string]interface{}{
+ "id": i + 1,
+ "name": "User " + string(rune(65+i%26)),
+ "email": "user" + string(rune(65+i%26)) + "@example.com",
+ "roles": []string{"User", "Editor", "Admin", "Viewer"}[0:1+(i%4)],
+ }
+ }
+
+ context := map[string]interface{}{
+ "users": users,
+ }
+
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ var buf bytes.Buffer
+ template, _ := engine.Load("large_context")
+ _ = template.RenderTo(&buf, context)
+ }
+}
+
+// BenchmarkContextCloning benchmarks the RenderContext cloning operation
+func BenchmarkContextCloning(b *testing.B) {
+ engine := New()
+
+ // Create a base context with some data
+ baseContext := NewRenderContext(engine.environment, map[string]interface{}{
+ "user": map[string]interface{}{
+ "id": 123,
+ "name": "John Doe",
+ "roles": []string{
+ "admin", "editor", "user",
+ },
+ },
+ "settings": map[string]interface{}{
+ "theme": "dark",
+ "notifications": true,
+ "language": "en",
+ },
+ "items": []map[string]interface{}{
+ {"id": 1, "name": "Item 1"},
+ {"id": 2, "name": "Item 2"},
+ {"id": 3, "name": "Item 3"},
+ },
+ }, engine)
+
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ // Create a clone of the context
+ clonedCtx := baseContext.Clone()
+ clonedCtx.Release() // Return to pool after use
+ }
+
+ baseContext.Release() // Clean up
+}
+
+// BenchmarkExpressionEvaluation benchmarks various expression evaluations
+func BenchmarkExpressionEvaluation(b *testing.B) {
+ engine := New()
+
+ // Register a simple template with different expression types
+ templateContent := `
+{{ 1 + 2 * 3 }}
+{{ "Hello " ~ name ~ "!" }}
+{{ items[0] }}
+{{ user.name }}
+{{ items|length > 3 ? "Many items" : "Few items" }}
+{{ range(1, 10)|join(", ") }}
+`
+ err := engine.RegisterString("expressions", templateContent)
+ if err != nil {
+ b.Fatalf("Error registering template: %v", err)
+ }
+
+ context := map[string]interface{}{
+ "name": "World",
+ "user": map[string]interface{}{
+ "name": "John",
+ "age": 30,
+ },
+ "items": []string{"a", "b", "c", "d", "e"},
+ }
+
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ var buf bytes.Buffer
+ template, _ := engine.Load("expressions")
+ _ = template.RenderTo(&buf, context)
+ }
+}
+
+// BenchmarkStringOperations benchmarks string manipulation operations
+func BenchmarkStringOperations(b *testing.B) {
+ engine := New()
+
+ // Register a template with various string operations
+ templateContent := `
+{{ " Hello, World! "|trim }}
+{{ text|replace("o", "0") }}
+{{ text|upper }}
+{{ text|lower }}
+{{ text|capitalize }}
+{{ text|slice(7, 5) }}
+{{ text|split(", ")|join("-") }}
+{{ "%s, %s!"|format("Hello", "World") }}
+`
+ err := engine.RegisterString("string_ops", templateContent)
+ if err != nil {
+ b.Fatalf("Error registering template: %v", err)
+ }
+
+ context := map[string]interface{}{
+ "text": "Hello, World!",
+ }
+
+ b.ReportAllocs()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ var buf bytes.Buffer
+ template, _ := engine.Load("string_ops")
+ _ = template.RenderTo(&buf, context)
+ }
+}
\ No newline at end of file
diff --git a/scripts/analyze_memory.sh b/scripts/analyze_memory.sh
new file mode 100755
index 0000000..d024f20
--- /dev/null
+++ b/scripts/analyze_memory.sh
@@ -0,0 +1,160 @@
+#!/bin/bash
+
+# Create output directory
+mkdir -p reports
+
+echo "=== Running Memory Allocation Analysis for Twig Template Engine ==="
+echo ""
+
+# Run standard benchmarks with memory statistics
+echo "Step 1: Running benchmarks with memory allocation reporting..."
+go test -run=^$ -bench=BenchmarkRender -benchmem ./memory_profile_test.go | tee reports/benchmark_results.txt
+
+# Generate allocation profile
+echo ""
+echo "Step 2: Generating heap allocation profile..."
+go test -run=^$ -bench=BenchmarkRenderComplexTemplate -benchmem -memprofile=reports/heap.prof ./memory_profile_test.go
+
+# Run heap profile analysis and save top allocations
+echo ""
+echo "Step 3: Analyzing allocation profile..."
+go tool pprof -text -alloc_space reports/heap.prof > reports/top_allocations.txt
+
+echo ""
+echo "Step 4: Generating detailed memory profile report..."
+# Run with different template complexities
+echo " - Profiling simple templates..."
+go run cmd/profile/main.go -complexity=1 -iterations=1000 -memprofile=reports/simple.prof > reports/simple_profile.txt
+
+echo " - Profiling medium templates..."
+go run cmd/profile/main.go -complexity=2 -iterations=1000 -memprofile=reports/medium.prof > reports/medium_profile.txt
+
+echo " - Profiling complex templates..."
+go run cmd/profile/main.go -complexity=3 -iterations=1000 -memprofile=reports/complex.prof > reports/complex_profile.txt
+
+# Generate flamegraph (requires go-torch if available)
+if command -v go-torch &> /dev/null
+then
+ echo ""
+ echo "Step 5: Generating flamegraph visualization..."
+ go-torch -alloc_space reports/heap.prof -file reports/allocations_flamegraph.svg
+fi
+
+# Compile the comprehensive report
+echo ""
+echo "Step 6: Compiling final report..."
+
+cat > reports/memory_optimization_report.md << 'EOF'
+# Twig Template Engine Memory Optimization Report
+
+## Summary
+
+This report analyzes memory allocation patterns in the Twig template engine to identify areas for implementing a zero-allocation rendering path.
+
+## Benchmark Results
+
+```
+EOF
+
+cat reports/benchmark_results.txt >> reports/memory_optimization_report.md
+
+cat >> reports/memory_optimization_report.md << 'EOF'
+```
+
+## Top Allocation Sources
+
+The following are the top functions allocating memory during template rendering:
+
+```
+EOF
+
+head -20 reports/top_allocations.txt >> reports/memory_optimization_report.md
+
+cat >> reports/memory_optimization_report.md << 'EOF'
+```
+
+## Memory Profile by Template Complexity
+
+### Simple Templates
+
+EOF
+
+grep -A 10 "Memory" reports/simple_profile.txt >> reports/memory_optimization_report.md
+
+cat >> reports/memory_optimization_report.md << 'EOF'
+
+### Medium Templates
+
+EOF
+
+grep -A 10 "Memory" reports/medium_profile.txt >> reports/memory_optimization_report.md
+
+cat >> reports/memory_optimization_report.md << 'EOF'
+
+### Complex Templates
+
+EOF
+
+grep -A 10 "Memory" reports/complex_profile.txt >> reports/memory_optimization_report.md
+
+cat >> reports/memory_optimization_report.md << 'EOF'
+
+## Key Allocation Hotspots
+
+Based on the profiling data, these areas should be prioritized for optimization:
+
+1. **String Operations** - String concatenation, substring operations, and conversions
+2. **Context Creation** - Creating and copying RenderContext objects
+3. **Map Allocations** - Temporary maps created during rendering
+4. **Slice Allocations** - Dynamic arrays for node collections
+5. **Expression Evaluation** - Temporary objects created during expression processing
+6. **Buffer Management** - Output buffer allocations
+7. **Function/Filter Calls** - Parameter passing and result handling
+
+## Optimization Strategies
+
+### String Operations
+
+- Replace string concatenation with direct writes to io.Writer
+- Use pooled byte buffers instead of creating new strings
+- Implement specialized ToString methods to avoid allocations for common types
+
+### Context Handling
+
+- Implement pooling for RenderContext objects
+- Create a linked-context mechanism instead of copying values
+- Preallocate and reuse context maps
+
+### Map and Slice Allocations
+
+- Preallocate maps and slices with known capacities
+- Reuse map and slice objects from pools
+- Avoid unnecessary copying of collections
+
+### Expression Evaluation
+
+- Pool expression evaluation result objects
+- Optimize common expression patterns with specialized handlers
+- Reduce intermediate allocations in expression trees
+
+### Implementation Plan
+
+1. Start with the highest allocation areas first
+2. Implement object pooling for all major components
+3. Create specialized non-allocating paths for common operations
+4. Revise string handling to minimize allocations
+5. Optimize hot spots in critical rendering code paths
+
+## Next Steps
+
+1. Implement object pools for all identified allocation sources
+2. Create benchmarks to validate each optimization
+3. Develop specialized string handling utilities
+4. Optimize context handling and cloning
+5. Enhance expression evaluation to minimize allocations
+
+EOF
+
+echo ""
+echo "Report generation complete. See reports/memory_optimization_report.md for results."
+echo ""
\ No newline at end of file