Viendo el código generado de Twig se me ocurrieron varias cosas para mejorar el rendimiento. En primer lugar hay una serie de funciones que se llaman muchísimo y que se podrían implementar como extensión nativa aumentando sustancialmente el rendimiento sin hacer nada.

Luego hay otra cosa que son los contextos. En Twig los contextos se simulan con un array y array_merge. Los cambios de contexto son muy costosos por este motivo y se hace demasiado amenudo. El tiempo perdido con dos bucles anidados es excesivo. Yo personalmente replantearía ciertas cosas a nivel de rendimiento en Twig.

Esta tarde tenía un rato y he hecho una clase que permitiría simular contextos anidados sin necesidad de merges implementando la interfaz ArrayAccess.

Nuevamente como el código es fácil que salga mal lo subo a pastebin: http://pastebin.com/xzRj4hR8</div>

<?php  

error_reporting(E_ALL | E_STRICT);  

class Context implements ArrayAccess {  
    /**  
     * @var Context  
     */  
    protected $parent;  

    /**  
     * @var ArrayObject  
     */  
    protected $current;  

    public function __construct($items = array(), Context $parent = NULL) {  
        $this->current = new ArrayObject((array)$items);  
        $this->parent = $parent;  
    }  

    protected function &getRef($index) {  
        $ref = &$this->current[$index];  
        if (!isset($ref) && ($this->parent !== NULL)) {  
            $ref = &$this->parent->getRef($index);  
        }  
        return $ref;  
    }  

    public function offsetExists($index) {  
        $ref = &$this->getRef($index);  
        return isset($ref);  
    }  

    public function &offsetGet($index) {  
        return $this->getRef($index);  
    }  

    public function offsetSet($index, $newval) {  
        $ref = &$this->getRef($index);  
        $ref = $newval;  
    }  

    public function offsetUnset($index) {  
        $ref = &$this->getRef($index);  
        unset($ref);  
    }  

    public function enter($items = array()) {  
        return new static($items, $this);  
    }  

    public function leave() {  
        return $this->parent;  
    }  
}  

$context = new Context(array('a' => -10, 'b' => -20, 'c' => -30));  
$context = $context->enter(array('a' => 10, 'b' => 20));  
printf("%d\n", ++$context['a']);  
printf("%d\n", ++$context['c']);  

$context = $context->leave();  
printf("%d\n", ++$context['a']);  
printf("%d\n", ++$context['c']);  

$context['c'] = 6;  

printf("%d\n", $context['c']);