You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by Serge Knystautas <sk...@gmail.com> on 2006/02/26 20:36:54 UTC

Avoid reparsing velocity templates

I'm working on a CMS that uses velocity template extensively (many
thousands of templates), and we're trying to figure out how to avoid
reparsing these templates over and over.

First idea... does anyone have experience creating alternate resource
cache implementations?  I've looked at the basic cache impl that's
available, and it seems like I could very easily swap it with an LRU
Map to avoid sucking up a lot of memory... we have perhaps hundreds or
maybe thousands of templates and couldn't keep them all cached in
memory.  That could help reduce reparsing on the most heavily used
templates.

Really though, something like caching the parsed templates (i.e., the
AST nodes) to disk or somehow using bytecode generation or something
to avoid reparsing my templates every time and make this much more
memory friendly... if anyone has any experience or ideas with this,
I'd greatly appreciate it.

--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com

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


Re: Avoid reparsing velocity templates

Posted by Will Glass-Husain <wg...@forio.com>.
Doesn't the source code head (1.5 prerelease) use an LRU cache?

Anyone using this want to comment?

WILL

----- Original Message ----- 
From: "Serge Knystautas" <sk...@gmail.com>
To: "Velocity Developers List" <ve...@jakarta.apache.org>
Sent: Sunday, February 26, 2006 11:36 AM
Subject: Avoid reparsing velocity templates


I'm working on a CMS that uses velocity template extensively (many
thousands of templates), and we're trying to figure out how to avoid
reparsing these templates over and over.

First idea... does anyone have experience creating alternate resource
cache implementations?  I've looked at the basic cache impl that's
available, and it seems like I could very easily swap it with an LRU
Map to avoid sucking up a lot of memory... we have perhaps hundreds or
maybe thousands of templates and couldn't keep them all cached in
memory.  That could help reduce reparsing on the most heavily used
templates.

Really though, something like caching the parsed templates (i.e., the
AST nodes) to disk or somehow using bytecode generation or something
to avoid reparsing my templates every time and make this much more
memory friendly... if anyone has any experience or ideas with this,
I'd greatly appreciate it.

--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com

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


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


Re: Avoid reparsing velocity templates

Posted by Serge Knystautas <sk...@gmail.com>.
On 2/27/06, Jonathan Revusky <re...@wanadoo.es> wrote:
> > Heh, if freemarker can parse Velocity templates, then maybe.  Like I
> > said, I've got thousands of temlates (not to mention users) that would
> > need converting...
>
> Actually, we've got an automatic conversion tool that works fairly well,
> reads in VTL and spits out FTL. A real miracle. The modern equivalent of
> turning water into wine.

Heh, if VTL to FTL transformation is water to wine, then perhaps XML
transformation is parting the Red Sea?  What templating feature is
curing leprocy or blindness?  I have to argue that that would be
mathematical functions that support decimal calculations.

Now if only you had a conversion tool that would change how my users
had been trained. That'll take some real divine power.

> > Yes, it is a fair point as to whether the serializable API would be
> > faster, but I would hope so.  Given the number of pages, I have to
> > turn off memory caching, so every page requires parsing.
>
> What you need, I think, is the MRU cache.

Yeah, gonna throw that in and run some performance tests.  Fortunately
the cache strategy is very easy to swap out... I only wish the parser
pool management was as easy to swap out...

> > My benchmarks calculated 37ms/MB to read a file (just read into a
> > string), 754ms/MB to compile (create a Template object), and 31ms/MB
> > to merge it with a simple context.  Obviously if I can eat into that
> > 700+ms/MB rate by serializing the ASTNodes or something else, then
> > that'd be great.
>
> Maybe the question is how much of the overhead in parsing VTL is in the
> lexical scanning. From what you're saying it seems that not much of it
> is in actually physically reading the file. Offhand (I could be wrong)
> it seems the gain you'd get from a binary storage format is that,
> instead of scanning ahead for #foreach and all the other tokens they are
> stored as a single byte, say.

Ergo, my idea of serialization. :)

> But probably the solution you'll implement will be some kind of MRU
> cache. Or you can just buy a lot more RAM, I guess. :-)

Yeah, unfortunately more RAM will only get me through this year.  With
our growth projections, I'll need to solve this in the fall.

--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com

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


Re: Avoid reparsing velocity templates

Posted by Jonathan Revusky <re...@wanadoo.es>.
Serge Knystautas wrote:
> On 2/26/06, Jonathan Revusky <re...@wanadoo.es> wrote:
> 
>>Serge Knystautas wrote:
>>
>>>I'm working on a CMS that uses velocity template extensively (many
>>>thousands of templates), and we're trying to figure out how to avoid
>>>reparsing these templates over and over.
>>
>>Have you actually determined that this is a bottleneck in your application?
> 
> 
> Yes.  Why would I ask otherwise? :)

It wouldn't be logical, but in my experience, many people are willing to 
spend quite a bit of time and energy speculating about the performance 
implications of whatever without any proof that it's a real-world 
bottleneck.

> 
>>Well, you could look at FreeMarker. :-) I think we have a pretty good
>>MRU template caching implementation. I don't know too much about it, it
>>was written by Attila Szegedi, not me. It's probably pretty good. Attila
>>is a pretty thorough guy. This stuff is quite well tested. It's been
>>part of our stable release for several years.
> 
> 
> Heh, if freemarker can parse Velocity templates, then maybe.  Like I
> said, I've got thousands of temlates (not to mention users) that would
> need converting...

Actually, we've got an automatic conversion tool that works fairly well, 
reads in VTL and spits out FTL. A real miracle. The modern equivalent of 
turning water into wine.

> 
> Besides Velocity is extremely flexible and trivial to stick a
> memory-based LRU template cache.  JDK 1.4 provides an LRU map, so I
> can create that with a cap instead of the default hashtable, and I've
> got an impl that I would hope is as reliable as what Attila
> implemented.
> 
> But my real goal is to cache without using memory...
> 
> 
>>>Really though, something like caching the parsed templates (i.e., the
>>>AST nodes) to disk
>>
>>Well, you're talking about storing the AST in some format on disk, but
>>there is already a way of storing a VTL AST on disk and that is the way
>>it is stored already, as a .vtl file. I mean, it is not obvious to me
>>offhand why re-instantiating the AST from the disk in your scenario is
>>going to be that much more efficient than just reparsing the template
>>from its canonical VTL format.
>>
>>I mean, at the end of the day, you're just reading the template (in some
>>format) off the disk again. Okay, you could have a binary format for
>>storage that is a bit more efficient than the VTL text format, but how
>>much difference would it make?
>>
>>In terms of overall Velocity development, how much value added could
>>their be?
> 
> 
> Yes, it is a fair point as to whether the serializable API would be
> faster, but I would hope so.  Given the number of pages, I have to
> turn off memory caching, so every page requires parsing.

What you need, I think, is the MRU cache.

> 
> My benchmarks calculated 37ms/MB to read a file (just read into a
> string), 754ms/MB to compile (create a Template object), and 31ms/MB
> to merge it with a simple context.  Obviously if I can eat into that
> 700+ms/MB rate by serializing the ASTNodes or something else, then
> that'd be great.

Maybe the question is how much of the overhead in parsing VTL is in the 
lexical scanning. From what you're saying it seems that not much of it 
is in actually physically reading the file. Offhand (I could be wrong) 
it seems the gain you'd get from a binary storage format is that, 
instead of scanning ahead for #foreach and all the other tokens they are 
stored as a single byte, say.

But probably the solution you'll implement will be some kind of MRU 
cache. Or you can just buy a lot more RAM, I guess. :-)

Jonathan Revusky
--
lead developer, FreeMarker project, http://freemarker.org/


> 
> And beyond serialization, if Velocity templates could get translated
> into bytecode, then we've changed velocity from interpreted to
> compiled templating, much like what Resin is doing with PHP
> (http://wiki.caucho.com/Quercus).  I'm not expecting someone else
> write it...  Just wondering if it seemed at all feasible and/or
> querying for other people who have dealt with this.
> 
> --
> Serge Knystautas
> Lokitech >> software . strategy . design >> http://www.lokitech.com
> p. 301.656.5501
> e. sergek@lokitech.com


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


Re: Avoid reparsing velocity templates

Posted by "Henning P. Schmiedehausen" <hp...@intermeta.de>.
"Serge Knystautas" <sk...@gmail.com> writes:

>The problem I see is that every extends SimpleNode, which holds
>references to RuntimeServices and Parser, neither of which are really
>serializable.  The RuntimeServices seems manageable since you can init

The main problem here is our entwined JavaCC dependency that cannot be
untied. I tried doing this in Dec and ended up breaking the
interface. We won't change that in the 1.x cycle. In the (vaporware)
2.x, I'm thinking about using a different parser generator. antlr
comes to mind. Oh, if I only had time... :-)

	Best regards
		Henning

-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen          INTERMETA GmbH
hps@intermeta.de        +49 9131 50 654 0   http://www.intermeta.de/

RedHat Certified Engineer -- Jakarta Turbine Development  -- hero for hire
   Linux, Java, perl, Solaris -- Consulting, Training, Development

Social behaviour: Bavarians can be extremely egalitarian and folksy.
                                    -- http://en.wikipedia.org/wiki/Bavaria
Most Franconians do not like to be called Bavarians.
                                    -- http://en.wikipedia.org/wiki/Franconia

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


Re: Avoid reparsing velocity templates

Posted by Serge Knystautas <sk...@gmail.com>.
On 2/27/06, Will Glass-Husain <wg...@forio.com> wrote:
> I took a quick look at the code.  Seems like we can remove the need to
> include a reference to Parser in ASTDirective by passing in a direct
> reference to the directive instead.

Cool!

> By "init the top node" method, I assume you mean we would require the user
> to call init(RuntimeServices) after deserializing?

Yes, the cache implementation would do it (if that's what you mean by user).

--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com

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


Re: Avoid reparsing velocity templates

Posted by Will Glass-Husain <wg...@forio.com>.
I took a quick look at the code.  Seems like we can remove the need to 
include a reference to Parser in ASTDirective by passing in a direct 
reference to the directive instead.

By "init the top node" method, I assume you mean we would require the user 
to call init(RuntimeServices) after deserializing?

WILL

----- Original Message ----- 
From: "Serge Knystautas" <sk...@gmail.com>
To: "Velocity Developers List" <ve...@jakarta.apache.org>
Sent: Sunday, February 26, 2006 8:11 PM
Subject: Re: Avoid reparsing velocity templates


On 2/26/06, Llewellyn Falco <is...@setgame.com> wrote:
> if everything isn't serializable, checkout the code and make it 
> serialiable
> shouldn't take very long, doubt even 15 minutes to add implements
> serializable to the nessicary classes.

The problem I see is that every extends SimpleNode, which holds
references to RuntimeServices and Parser, neither of which are really
serializable.  The RuntimeServices seems manageable since you can init
the top node and it will descend and set the variable everywhere else
(hopefully that's all init does).  Parser is a bit harder to extract,
but really only because of one place... ASTDirective uses it in the
init method.

> out of curioustity  700 ms / mb ?  i've never seen a template so big....

I had 4 sized templates (tiny 102b, medium 4kb, large 60kb, huge
243kb) of the same Velocity script repeated, ran them thousands of
times, then adjusted the units to express it as duration per MB.
Yeah, not really that big. :)

--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com

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


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


Re: Avoid reparsing velocity templates

Posted by Serge Knystautas <sk...@gmail.com>.
On 2/26/06, Llewellyn Falco <is...@setgame.com> wrote:
> if everything isn't serializable, checkout the code and make it serialiable
> shouldn't take very long, doubt even 15 minutes to add implements
> serializable to the nessicary classes.

The problem I see is that every extends SimpleNode, which holds
references to RuntimeServices and Parser, neither of which are really
serializable.  The RuntimeServices seems manageable since you can init
the top node and it will descend and set the variable everywhere else
(hopefully that's all init does).  Parser is a bit harder to extract,
but really only because of one place... ASTDirective uses it in the
init method.

> out of curioustity  700 ms / mb ?  i've never seen a template so big....

I had 4 sized templates (tiny 102b, medium 4kb, large 60kb, huge
243kb) of the same Velocity script repeated, ran them thousands of
times, then adjusted the units to express it as duration per MB. 
Yeah, not really that big. :)

--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com

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


Re: Avoid reparsing velocity templates

Posted by "Henning P. Schmiedehausen" <hp...@intermeta.de>.
"Llewellyn Falco" <is...@setgame.com> writes:

>out of curioustity  700 ms / mb ?  i've never seen a template so big.... 

:-) I've written an application that renders >500 page PDF documents
containing pictures, tables and text by piping Velocity output into
FOP. Average template size was 40 MB...

	Best regards
		Henning

-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen          INTERMETA GmbH
hps@intermeta.de        +49 9131 50 654 0   http://www.intermeta.de/

RedHat Certified Engineer -- Jakarta Turbine Development  -- hero for hire
   Linux, Java, perl, Solaris -- Consulting, Training, Development

Social behaviour: Bavarians can be extremely egalitarian and folksy.
                                    -- http://en.wikipedia.org/wiki/Bavaria
Most Franconians do not like to be called Bavarians.
                                    -- http://en.wikipedia.org/wiki/Franconia

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


Re: Avoid reparsing velocity templates

Posted by Llewellyn Falco <is...@setgame.com>.
Actually, this is a rather interesting point.
imagine if everything was serializable. then you could easily create a 
function


getTemplate(resourceName)
{
  fileName = resourceName + resource.getTimeModified();
if (fileName.exist())
{
    deserialize
}
else
{
getTemplateOldFashionWay();
serializeToFile();
}
return template;
}


if everything isn't serializable, checkout the code and make it serialiable 
shouldn't take very long, doubt even 15 minutes to add implements 
serializable to the nessicary classes.

cached, no memory.


llewellyn.

out of curioustity  700 ms / mb ?  i've never seen a template so big.... 


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


Re: Avoid reparsing velocity templates

Posted by Geir Magnusson Jr <ge...@pobox.com>.

Serge Knystautas wrote:

> 
> Besides Velocity is extremely flexible and trivial to stick a
> memory-based LRU template cache.  JDK 1.4 provides an LRU map, so I
> can create that with a cap instead of the default hashtable, and I've
> got an impl that I would hope is as reliable as what Attila
> implemented.

It should be trivial.  The thing is designed to be pluggable for this 
reason.

> 
> But my real goal is to cache without using memory...

And compute w/o cycles!

The holy grail of computing.

> 
>>> Really though, something like caching the parsed templates (i.e., the
>>> AST nodes) to disk
>> Well, you're talking about storing the AST in some format on disk, but
>> there is already a way of storing a VTL AST on disk and that is the way
>> it is stored already, as a .vtl file. I mean, it is not obvious to me
>> offhand why re-instantiating the AST from the disk in your scenario is
>> going to be that much more efficient than just reparsing the template
>> from its canonical VTL format.
>>
>> I mean, at the end of the day, you're just reading the template (in some
>> format) off the disk again. Okay, you could have a binary format for
>> storage that is a bit more efficient than the VTL text format, but how
>> much difference would it make?
>>
>> In terms of overall Velocity development, how much value added could
>> their be?
> 
> Yes, it is a fair point as to whether the serializable API would be
> faster, but I would hope so.  Given the number of pages, I have to
> turn off memory caching, so every page requires parsing.
> 
> My benchmarks calculated 37ms/MB to read a file (just read into a
> string), 754ms/MB to compile (create a Template object), and 31ms/MB
> to merge it with a simple context.  Obviously if I can eat into that
> 700+ms/MB rate by serializing the ASTNodes or something else, then
> that'd be great.

There should be no reason why not. (Thinking, thinking...)  I've oft 
wanted to modify the VelocityEngine and add something like

Template t = compileTemplate(Reader r)

and also maybe a helper to serialize and de-serialize a Template instance.


> 
> And beyond serialization, if Velocity templates could get translated
> into bytecode, then we've changed velocity from interpreted to
> compiled templating, much like what Resin is doing with PHP
> (http://wiki.caucho.com/Quercus).  I'm not expecting someone else
> write it...  Just wondering if it seemed at all feasible and/or
> querying for other people who have dealt with this.

We thought about that years ago, and came to the conclusion that absent 
some kind of dynamic optimization like a JIT (which I'd argue you could 
do now), that you wouldn't get much.

The code in each node in the AST needs to be executed, and already is 
bytecode.  So I never saw what you'd be able to wring out of it, other 
than save the method calls where one node in a AST invokes it's children.

Maybe a JIT would help. Dunno.

geir



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


Re: Avoid reparsing velocity templates

Posted by Serge Knystautas <sk...@gmail.com>.
On 2/26/06, Jonathan Revusky <re...@wanadoo.es> wrote:
> Serge Knystautas wrote:
> > I'm working on a CMS that uses velocity template extensively (many
> > thousands of templates), and we're trying to figure out how to avoid
> > reparsing these templates over and over.
>
> Have you actually determined that this is a bottleneck in your application?

Yes.  Why would I ask otherwise? :)

> Well, you could look at FreeMarker. :-) I think we have a pretty good
> MRU template caching implementation. I don't know too much about it, it
> was written by Attila Szegedi, not me. It's probably pretty good. Attila
> is a pretty thorough guy. This stuff is quite well tested. It's been
> part of our stable release for several years.

Heh, if freemarker can parse Velocity templates, then maybe.  Like I
said, I've got thousands of temlates (not to mention users) that would
need converting...

Besides Velocity is extremely flexible and trivial to stick a
memory-based LRU template cache.  JDK 1.4 provides an LRU map, so I
can create that with a cap instead of the default hashtable, and I've
got an impl that I would hope is as reliable as what Attila
implemented.

But my real goal is to cache without using memory...

> > Really though, something like caching the parsed templates (i.e., the
> > AST nodes) to disk
>
> Well, you're talking about storing the AST in some format on disk, but
> there is already a way of storing a VTL AST on disk and that is the way
> it is stored already, as a .vtl file. I mean, it is not obvious to me
> offhand why re-instantiating the AST from the disk in your scenario is
> going to be that much more efficient than just reparsing the template
> from its canonical VTL format.
>
> I mean, at the end of the day, you're just reading the template (in some
> format) off the disk again. Okay, you could have a binary format for
> storage that is a bit more efficient than the VTL text format, but how
> much difference would it make?
>
> In terms of overall Velocity development, how much value added could
> their be?

Yes, it is a fair point as to whether the serializable API would be
faster, but I would hope so.  Given the number of pages, I have to
turn off memory caching, so every page requires parsing.

My benchmarks calculated 37ms/MB to read a file (just read into a
string), 754ms/MB to compile (create a Template object), and 31ms/MB
to merge it with a simple context.  Obviously if I can eat into that
700+ms/MB rate by serializing the ASTNodes or something else, then
that'd be great.

And beyond serialization, if Velocity templates could get translated
into bytecode, then we've changed velocity from interpreted to
compiled templating, much like what Resin is doing with PHP
(http://wiki.caucho.com/Quercus).  I'm not expecting someone else
write it...  Just wondering if it seemed at all feasible and/or
querying for other people who have dealt with this.

--
Serge Knystautas
Lokitech >> software . strategy . design >> http://www.lokitech.com
p. 301.656.5501
e. sergek@lokitech.com

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


Re: Avoid reparsing velocity templates

Posted by Jonathan Revusky <re...@wanadoo.es>.
Serge Knystautas wrote:
> I'm working on a CMS that uses velocity template extensively (many
> thousands of templates), and we're trying to figure out how to avoid
> reparsing these templates over and over.

Have you actually determined that this is a bottleneck in your application?

> 
> First idea... does anyone have experience creating alternate resource
> cache implementations?  I've looked at the basic cache impl that's
> available, and it seems like I could very easily swap it with an LRU
> Map to avoid sucking up a lot of memory... we have perhaps hundreds or
> maybe thousands of templates and couldn't keep them all cached in
> memory.  That could help reduce reparsing on the most heavily used
> templates.

Well, you could look at FreeMarker. :-) I think we have a pretty good 
MRU template caching implementation. I don't know too much about it, it 
was written by Attila Szegedi, not me. It's probably pretty good. Attila 
is a pretty thorough guy. This stuff is quite well tested. It's been 
part of our stable release for several years.

> 
> Really though, something like caching the parsed templates (i.e., the
> AST nodes) to disk 

Well, you're talking about storing the AST in some format on disk, but 
there is already a way of storing a VTL AST on disk and that is the way 
it is stored already, as a .vtl file. I mean, it is not obvious to me 
offhand why re-instantiating the AST from the disk in your scenario is 
going to be that much more efficient than just reparsing the template 
from its canonical VTL format.

I mean, at the end of the day, you're just reading the template (in some 
format) off the disk again. Okay, you could have a binary format for 
storage that is a bit more efficient than the VTL text format, but how 
much difference would it make?

In terms of overall Velocity development, how much value added could 
their be?

> or somehow using bytecode generation or something
> to avoid reparsing my templates every time and make this much more
> memory friendly... if anyone has any experience or ideas with this,
> I'd greatly appreciate it.

It's not likely that something like this would produce much value-added 
to hardly any users. I'm only speculating but it seems unlikely that 
whoever is involved in Velocity development would want to invest much 
effort in this. After all, there are glaring problems in Velocity, like 
whitespace handling, lame macro system, deficient error reporting, that 
have not been adequately addressed in years. Surely they'd want to 
address some of these things first.

Jonathan Revusky
--
lead developer, FreeMarker project, http://freemarker.org/

> 
> --
> Serge Knystautas
> Lokitech >> software . strategy . design >> http://www.lokitech.com
> p. 301.656.5501
> e. sergek@lokitech.com


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