[ 
https://issues.apache.org/jira/browse/VELOCITY-817?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16775863#comment-16775863
 ] 

Claude Brisson commented on VELOCITY-817:
-----------------------------------------

Having a huge number of dynamically generated templates is a quite specific use 
case, which is beyond the scope of the provided StringResourceLoader. Specific 
volumetries require specific caching strategies, and it all depends on the life 
cycle of your generated templates.

The StringResourceRepository paradigm is just the wrong tool for your use case.


> Dynamic Templates with Caching
> ------------------------------
>
>                 Key: VELOCITY-817
>                 URL: https://issues.apache.org/jira/browse/VELOCITY-817
>             Project: Velocity
>          Issue Type: Improvement
>          Components: Engine
>    Affects Versions: 1.7
>            Reporter: Mark S
>            Assignee: Claude Brisson
>            Priority: Major
>              Labels: performance
>   Original Estimate: 2h
>  Remaining Estimate: 2h
>
> 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.
> {code:title=Velocity Call Snippet|borderStyle=solid}
> String template = "message.to:  $\{message.to} ";
> StringWriter velocityWriter = new StringWriter();
> velocityEngine.evaluate( velocityContext, velocityWriter, "LOG", template );
> return velocityWriter.toString();
> {code}
> 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.
> +++++++++++++++++++++++++++++++++++++ 
> {code:title=Velocity Engine Setup Snippet|borderStyle=solid}
> 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();
> {code}
> {code:title=Velocity Call Snippet|borderStyle=solid}
> String template = "message.to:  ${message.to} ";
> StringWriter velocityWriter = new StringWriter();
> Template veTemplate = velocityEngine.getTemplate( template );
> veTemplate.merge( velocityContext, velocityWriter );
> return velocityWriter.toString();
> {code}
> {code:title=Velocity Supporting Class Snippet|borderStyle=solid}
> 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 + "]";
>     }
> }
> {code}



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

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

Reply via email to