Instead of using eval to run the ERB-generated code, I use eval to define a function which has the generated code as a body. This function is then called to render the template. The advantage of this approach is that parsing of the code is done only once during the eval of the function definition, instead of each time the template is rendered. I've measured a 25% increase in rendering speed with this approach.
Instead of using the whole template code as an index into the template cache, the absolute path for the template file is used. The function name itself is constructed from the path. If no file is given, I construct an artifical name using a global counter and use the template code as an index. As a consequence, lookup speed for cached templates is improved too, as computing the hash of the file name should generally be much faster than computing the hash of the whole template code.
However, in order to get local assigns working, one needs to use instance variables and corresponding accessors for all the keys in local_assigns, as there is no way to pass local variables to an eval (I actually had a long discussion with matz about this issue on the ruby mailing list. I think it is a ruby defect that ...code... is not equivalent to ...eval "code"... in all environments).
As a consequence of the design, one cannot use the same local variable name for different things along a single template call chain. Needs to be documented.