Would you consider submitting this via
https://issues.apache.org/jira/browse/VELOCITY?

That would allow us to possibly incorporate improvements from your
code into future versions.

On Thu, Feb 9, 2012 at 2:47 PM, Mark-12345
<marks1900-pos...@yahoo.com.au> wrote:
>
> I thought I would share the following code with the Apache Velocity
> community.
>
>
> Problem Description:  I wanted to use Dynamic Templates though I found the
> following had massive performance implications.
>
> -- Velocity Call Snippet --
> String template = "message.to:  ${message.to} ";
> StringWriter velocityWriter = new StringWriter();
> velocityEngine.evaluate( velocityContext, velocityWriter, "LOG", template );
> return velocityWriter.toString();
> -- Velocity Call Snippet --
>
>
> As such, I needed an alternate solution and guessed that if I could cache
> the Velocity templates used I could see big performance gains.
>
> I initially looked to the
> org.apache.velocity.runtime.resource.loader.StringResourceLoader class to
> solve my problems.   The StringResourceLoader class requires an instance of
> the StringResourceRepository class, and the only implementation of
> StringResourceRepository is StringResourceRepositoryImpl.  Unfortunately,
> since the number of unique templates will grow over time, in time the
> StringResourceRepositoryImpl.resources Map will cause an out of memory
> error.
>
> Why doesn't StringResourceRepositoryImpl use a cache with a maximum size?
> Is a cache even needed as the Velocity ResourceCacheImpl will cache
> Templates?
>
> +++++++++++++++++++++++++++++++++++++
> In the end I settled on the following solution.  From my tests using YourKit
> Java Profiler I invoked the static Velocity wrapping method 100,000 times,
> and discovered a performance difference of around 75 fold (146,937ms vs
> 1,981ms).
>
> Below is my solution.  Feedback appreciated.
>
> +++++++++++++++++++++++++++++++++++++
>
>
> Regards,
> Mark
>
> -- Velocity Engine Setup Snippet --
> Properties p = new Properties();
>
> p.setProperty( RuntimeConstants.INPUT_ENCODING, DEFAULT_ENCODING );
> p.setProperty( RuntimeConstants.OUTPUT_ENCODING, DEFAULT_ENCODING );
>
> p.setProperty( RuntimeConstants.RESOURCE_MANAGER_CLASS,
>       "org.apache.velocity.runtime.resource.ResourceManagerImpl" );
> p.setProperty( RuntimeConstants.RESOURCE_MANAGER_CACHE_CLASS,
>       "org.apache.velocity.runtime.resource.ResourceCacheImpl" );
> p.setProperty( RuntimeConstants.RESOURCE_MANAGER_DEFAULTCACHE_SIZE, "100" );
>
> p.setProperty( RuntimeConstants.RESOURCE_LOADER, "string" );
> p.setProperty( "string.resource.loader.class",
>       "custom.SimpleStringResourceLoader" );
> p.setProperty( "string.resource.loader.encoding", DEFAULT_ENCODING );
> p.setProperty( "string.resource.loader.cache", Boolean.TRUE.toString() );
> p.setProperty( "string.resource.loader.modificationCheckInterval", "-1" );
>
> VelocityEngine engine = new VelocityEngine( p );
> engine.init();
> -- Velocity Engine Setup Snippet --
>
> -- Velocity Call Snippet --
> String template = "message.to:  ${message.to} ";
> StringWriter velocityWriter = new StringWriter();
> Template veTemplate = velocityEngine.getTemplate( template );
> veTemplate.merge( velocityContext, velocityWriter );
> return velocityWriter.toString();
> -- Velocity Call Snippet --
>
>
>
>
> -- Velocity Supporting Class Snippet --
>
> package custom;
>
> import java.io.ByteArrayInputStream;
> import java.io.InputStream;
> import java.io.UnsupportedEncodingException;
> import java.util.concurrent.atomic.AtomicLong;
>
> import org.apache.commons.collections.ExtendedProperties;
> import org.apache.velocity.exception.VelocityException;
> import org.apache.velocity.runtime.resource.Resource;
> import org.apache.velocity.runtime.resource.loader.ResourceLoader;
> import org.apache.velocity.runtime.resource.util.StringResource;
>
> public class SimpleStringResourceLoader extends ResourceLoader
> {
>
>    protected static int classMetricsLevel;
>    protected static AtomicLong totalClassInstancesCreatedCount;
>    protected static AtomicLong totalStringsGeneratedCount;
>
>    static {
>        classMetricsLevel = 1;
>        totalClassInstancesCreatedCount = new AtomicLong();
>        totalStringsGeneratedCount = new AtomicLong();
>    }
>
>
>    protected String encoding;
>
>
>    public SimpleStringResourceLoader()
>    {
>
>        if ( classMetricsLevel > 0 )
>        {
>            totalClassInstancesCreatedCount.incrementAndGet();
>        }
>
>        this.encoding = "UTF-8";
>    }
>
>    @Override
>    public void init( ExtendedProperties paramExtendedProperties )
>    {
>        String paramEncoding = paramExtendedProperties.getString( "encoding"
> );
>
>        if ( null != encoding && encoding.trim().length() > 0 )
>        {
>            this.encoding = paramEncoding;
>        }
>    }
>
>    @Override
>    public InputStream getResourceStream( String contents )
>    {
>        if ( classMetricsLevel > 1 )
>        {
>            totalStringsGeneratedCount.incrementAndGet();
>        }
>
>        StringResource resource = new StringResource( contents, encoding );
>
>        byte[] byteArray = null;
>        try
>        {
>            byteArray = resource.getBody().getBytes( resource.getEncoding()
> );
>            return new ByteArrayInputStream( byteArray );
>        }
>        catch ( UnsupportedEncodingException ue )
>        {
>            throw new VelocityException( "Failed to convert contents to
> String "
>                    + resource.getEncoding(), ue );
>        }
>
>    }
>
>    @SuppressWarnings( "unused" )
>    @Override
>    public boolean isSourceModified( Resource paramResource )
>    {
>        return false;
>    }
>
>    @SuppressWarnings( "unused" )
>    @Override
>    public long getLastModified( Resource paramResource )
>    {
>        return 0;
>    }
>
>
>    public String getEncoding()
>    {
>        return encoding;
>    }
>
>    public void setEncoding( String encoding )
>    {
>        this.encoding = encoding;
>    }
>
>
>    public static int getClassMetricsLevel()
>    {
>        return classMetricsLevel;
>    }
>
>    public static void setClassMetricsLevel( int classMetricsLevel )
>    {
>        SimpleStringResourceLoader.classMetricsLevel = classMetricsLevel;
>    }
>
>    public static void setTotalClassInstancesCreatedCount( long counterValue
> )
>    {
>
> SimpleStringResourceLoader.totalClassInstancesCreatedCount.getAndSet(
> counterValue );
>    }
>
>    public static long getTotalClassInstancesCreatedCount()
>    {
>        return
> SimpleStringResourceLoader.totalClassInstancesCreatedCount.get();
>    }
>
>
>    public static void setTotalStringsGeneratedCount( long counterValue )
>    {
>        SimpleStringResourceLoader.totalStringsGeneratedCount.getAndSet(
> counterValue );
>    }
>
>    public static long getTotalStringsGeneratedCount()
>    {
>        return SimpleStringResourceLoader.totalStringsGeneratedCount.get();
>    }
>
>    @Override
>    public String toString()
>    {
>        return "SimpleStringResourceLoader [encoding=" + encoding + "]";
>    }
>
> }
>
> -- Velocity Supporting Class Snippet --
>
> --
> View this message in context: 
> http://old.nabble.com/Dynamic-Templates-tp33297076p33297076.html
> Sent from the Velocity - User mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org
> For additional commands, e-mail: user-h...@velocity.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscr...@velocity.apache.org
For additional commands, e-mail: user-h...@velocity.apache.org

Reply via email to