Re: Question on TemplateCache synchronization
Attila Szegedi <[email protected]>
| Newsgroups | gmane.comp.web.freemarker.user |
|---|---|
| Message-ID | <[email protected]> |
Well, I probably wouldn't touch TemplateLoader as such -- surprisingly
many people have written their own custom loaders. TemplateCache can
provide a reader-to-string "slurping" transformation internally.
Actually, if I were to write a new loader API, what I'd do primarily
is merge the timestamp lookup and retrival, so it's REST friendly,
i.e. remote retrieval over HTTP can be implemented with a single GET
operation using If-Modified-Since header etc.
Anyway, aside from that, I like your idea of having all textual state
of the template backed up by a single string or char sequence. Problem
is, Java APIs are often very inconsistent regarding whether it's more
optimal to use String or char[]. I.e. one thing I did back in the 2.0
or 2.1 day was I changed the backing store for TextBlock from String
to char[], because that way it could invoke Writer.write(char[])
directly. I wanted to avoid invoking Writer.write(String) as it will
copy the String's characters into a character array and then call
write(char[]) so by doing this we avoid copying the string's
characters on each write; here's Writer.write(String str, int off, int
len) from JDK 1.5 source code:
public void write(String str, int off, int len) throws
IOException {
synchronized (lock) {
char cbuf[];
if (len <= writeBufferSize) {
if (writeBuffer == null) {
writeBuffer = new char[writeBufferSize];
}
cbuf = writeBuffer;
} else { // Don't permanently allocate very large buffers.
cbuf = new char[len];
}
str.getChars(off, (off + len), cbuf, 0);
write(cbuf, 0, len);
}
}
So that'd be a case for storing the Template text content as char[].
However, many other elements will need to use a String one way or the
other, so for them doing a new String(char[]) all the time would be
wasteful (not to speak of again copying data). A good way to share one
underlying char[] is to have one String for the full template source,
and obtain all other strings using String.substring() on it. But then
we're again back to using Writer.write(String) for a TextBlock. So
yeah, it's a surprisingly hard problem to address correctly to have
*both* low memory footprint *and* good runtime performance; it's not
something that'd be inherently hard, the hardness comes from
java.lang.String's (justified) immutability requirements *and* lack of
immutable arrays in Java...
Attila.
On 2008.04.11., at 19:54, Jonathan Revusky wrote:
> BTW,
>
> I rewrote Template.java yesterday night to be more memory efficient.
> Finally, you know, what I did, is I just read all the template into a
> String and create a map of lines by running through that string and
> using String.substring(..) calls. That way, since String objects are
> immutable, the substring returned just uses a region of the character
> array in the main TemplateText string.
>
> It doesn't create a whole bunch of new character arrays like the old
> LineTableBuilder hack I wrote back when I implemented the error
> reporting stuff.
>
> The thing is that, finally, I wonder why we bother passing around
> Reader
> objects and so on in this Template API. I think it might just be
> simpler
> to use String just about everywhere we use Reader. Or we could use
> CharSequence for generality maybe.
>
> I mean, if we're going to keep all this text in memory anyway, why not
> just slurp it all into a String anyway and, where the TemplateLoader
> vends a Reader, just have it pass back a String and be done with it. I
> think the whole thing might just end up being a lot simpler and even
> more efficient that way.
>
> JR
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone