Dynamic Templates

2012-02-09 Thread Mark-12345

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 B

Re: Dynamic Templates

2012-02-09 Thread Nathan Bubna
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
 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(

Re: Dynamic Templates

2012-02-09 Thread Mark-12345

More than happy to create an improvement request.  See below:

https://issues.apache.org/jira/browse/VELOCITY-817



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
 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.

-- 
View this message in context: 
http://old.nabble.com/Dynamic-Templates-tp33297076p33298309.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