I did some quite extensive profiling to identify performance bottlenecks in Velocity 1.5.
Using Maven 2, JUnitPerf and JRat I was able to identify these methods as top bottlenecks:
org.apache.velocity.util.introspection ClassMap - findMethod(String,Object)
org.apache.velocity.util.introspection IntrospectorBase - getMethod(Class,String,Object)
org.apache.velocity.runtime.parser.node SimpleNode - literal()
org.apache.velocity.runtime.parser.node SimpleNode - render(InternalContextAdapter,Writer)
org.apache.commons.collections ExtendedProperties - getBoolean(String,boolean)
org.apache.velocity.runtime.parser.node ASTReference - render(InternalContextAdapter,Writer)
The first two eat over 50% of the CPU with many threads. See attached screenshots.
Interestingly enough the synchronized
org.apache.velocity.runtime RuntimeInstance getTemplate(String,String)
isn't a big problem when templates are cached. However, if all resources are not cached it becomes a serious performance bottleneck. ResourceCacheImpl also uses a synchronized map which slows things down.
I think these bottlenecks could be at least made less worse by reducing synchronization by using ConcurrentHashMap and StringBuilder that ship with JDK 1.5. I'm investigating what kind of benefits could be achieved with those.