You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Rickard Öberg <ri...@xpedio.com> on 2001/05/21 15:59:57 UTC

Jasper performance/3.3 tag pooling

Hi!

Ok, so now I've tested the Jasper performance with the 3.3 tag pooling
fix. The test was performed with a medium complexity page using lots of
iterative custom tags in a hierarchical fashion (i.e. tags within tags).

Results:
The page ran slower, and above all the response time varied greatly
(between 250ms and 460ms, whereas without tag pooling we got between
230ms and 340ms).

Looking at the generated code, I'm not particularly surprised: it uses
(it seems) a real shared tag pool, so using tags will execute code that
needs
to be synchronized. 

This is a bad design. Basically, any gains you get from reusing tags are
lost due to the overhead and general performance decrease you get by
using hashtables+"synchronized".

I've looked at pages generated by other more efficient JSP compilers
(e.g. Resin), and they generally use another approach:
Only reuse a tag within a particular page, and don't use a synchronized
pool to do it. Just pass the instance around within the generated code.
What is important is not primarily the global optimization gained by
using pools, but the local optimization gained by not creating tags for
each iteration in a iterative custom tag.

This is waaaay more efficient, and also avoids the suboptimization of
trying to reuse objects using Java code, something which is more
efficiently
handled by modern JVMs' memory management (i.e. creating objects using
"new" is
pretty snappy compared with Java-coded pools).

So, please remove the tag pooling, and do it right. If you don't believe
me, do some benchmarking or something.

/Rickard

-- 
Rickard Öberg
Software Development Specialist
xlurc - Xpedio Linköping Ubiquitous Research Center
Author of "Mastering RMI"
Email: rickard@xpedio.com

Re: Jasper performance/3.3 tag pooling

Posted by Rickard Öberg <ri...@xpedio.com>.
cmanolache@yahoo.com wrote:
> But in tomcat 3.3 we do a different trick - the thread pool is maintaining
> a "local storage" for each thread, and it's passing it to the worker.
> 
> The only synchronization in tomcat is in getting a thread from the thread
> pool - besides that we shouldn't need anything else.
> 
> Right now we keep the Request/Request pair - so we have a one-to-one
> relation between "main" request and thread ( in other words, the request
> is allways in the same thread ). Whatever attributes/notes you store in
> the request will be equivalent with thread-local data, without any sync.

That's good. But you still have the global vs local issue outlined in my
last post. Purely local, as you outline above, and proper pooling
management becomes tricky (=how to know how many tag instances to use
for the particular handled request).

> > Sorry, I should have been more specific. Of course object reuse can be a
> > good performance optimization. I'm just saying that you gotta balance it
> > with regard to modern JVM's ability to manage memory and "new" objects.
> > Optimize locally in code, and let the JVM do it globally. That's just
> > IMHO though, so feel free to disagree :-)
> 
> :-)
> 
> I was thinking the reverse - optimize globally, let the VM optimize
> locally, but it depends on definitions...

The problem is that global management is a tricky business. Say you keep
global pools of tag instances. Not only do you have to manage one
particular tag pool properly (not too big, not too small), you also have
to consider how many other pools are active (too many active pools with
too many tags, and you have a memory consumption problem). Then factor
in the temporal issues, i.e. that some tags are used more often than
others sometimes, and you have a situation that I dare you to find an
optimal algorithm to solve the pool management. And when/if you have
that algorithm, I can bet you quite a bunch of dolares that it won't be
more efficient than letting the JVM manage the memory and making sparse
"new"'s per page anyway.

Or (...standard disclaimer...) what am I missing? :-)

/Rickard

-- 
Rickard Öberg
Software Development Specialist
xlurc - Xpedio Linköping Ubiquitous Research Center
Author of "Mastering RMI"
Email: rickard@xpedio.com

Re: Jasper performance/3.3 tag pooling

Posted by cm...@yahoo.com.
On Tue, 22 May 2001, Rickard Öberg wrote:

> > Hash lookup is done once per jsp page - when the jsp page is first run.
> > After that, it's basically a synchronized push / pop pair on all subsequent
> > runs of the page.  In the future we can even get rid of the synch by using
> > thread local storage... one step at a time though. :)
> 
> Yup, that might improve things. Although then it depends on how
> ThreadLocal is implemented. I guess at some point deep down it has to do
> "synchronized", although I haven't checked.

It does ! :-)

But in tomcat 3.3 we do a different trick - the thread pool is maintaining
a "local storage" for each thread, and it's passing it to the worker.

The only synchronization in tomcat is in getting a thread from the thread
pool - besides that we shouldn't need anything else. 

Right now we keep the Request/Request pair - so we have a one-to-one
relation between "main" request and thread ( in other words, the request
is allways in the same thread ). Whatever attributes/notes you store in
the request will be equivalent with thread-local data, without any sync.

> Sorry, I should have been more specific. Of course object reuse can be a
> good performance optimization. I'm just saying that you gotta balance it
> with regard to modern JVM's ability to manage memory and "new" objects.
> Optimize locally in code, and let the JVM do it globally. That's just
> IMHO though, so feel free to disagree :-)

:-)

I was thinking the reverse - optimize globally, let the VM optimize
locally, but it depends on definitions... 



Costin


Re: Jasper performance/3.3 tag pooling

Posted by Rickard Öberg <ri...@xpedio.com>.
Casey Lucas wrote:
> Also, did you run the
> tests with and without tag pooling enabled on the same version of
> tomcat?  (By adding removing TagPoolManagerInterceptor.)

Yes. The only thing changed between the runs was the TPMI flag.

> > This is a bad design. Basically, any gains you get from reusing tags are
> > lost due to the overhead and general performance decrease you get by
> > using hashtables+"synchronized".
> >
> 
> Hash lookup is done once per jsp page - when the jsp page is first run.
> After that, it's basically a synchronized push / pop pair on all subsequent
> runs of the page.  In the future we can even get rid of the synch by using
> thread local storage... one step at a time though. :)

Yup, that might improve things. Although then it depends on how
ThreadLocal is implemented. I guess at some point deep down it has to do
"synchronized", although I haven't checked.

> > I've looked at pages generated by other more efficient JSP compilers
> > (e.g. Resin), and they generally use another approach:
> > Only reuse a tag within a particular page, and don't use a synchronized
> > pool to do it. Just pass the instance around within the generated code.
> > What is important is not primarily the global optimization gained by
> > using pools, but the local optimization gained by not creating tags for
> > each iteration in a iterative custom tag.
> >
> 
> Yes reusing a tag handler within a single page will be more efficient
> (for that particular page) but I would guess that once we change to pool
> per thread there's no way newing the tags at each use will be faster
> (at least for a busy site with lots of tags.)

And didn't say you should either. Right now 3.2 new's tags, and it's
slow. I'm saying, do it the middle way, but new'ing it once per page,
and then reuse within that page. No global optimization problems (i.e.
when to grow/shrink the pool), no synch problems, no shared pool
considerations, no hash lookup. All the good stuff and none of the bad.

As I said, last time I checked Resin worked this way, and I think we can
all agree that it's pretty snappy.

> > This is waaaay more efficient, and also avoids the suboptimization of
> > trying to reuse objects using Java code, something which is more
> > efficiently
> > handled by modern JVMs' memory management (i.e. creating objects using
> > "new" is
> > pretty snappy compared with Java-coded pools).
> >
> 
> I disagree.  I've found that object reuse can be a good performance
> optimization.

Sorry, I should have been more specific. Of course object reuse can be a
good performance optimization. I'm just saying that you gotta balance it
with regard to modern JVM's ability to manage memory and "new" objects.
Optimize locally in code, and let the JVM do it globally. That's just
IMHO though, so feel free to disagree :-)

> > So, please remove the tag pooling, and do it right. If you don't believe
> > me, do some benchmarking or something.
> >
> 
> I have done benchmarking and pooling enabled always wins.  :)  Maybe you
> can send some examples so that we can try and track down the problems.

As above, I've sent code to Costin. But I'll forward it to you to, so
you check it out.

Lastly, I would be absolutely thrilled to find out that the fault was
mine, i.e. some silly coding or config error. :-)

regards,
  Rickard

-- 
Rickard Öberg
Software Development Specialist
xlurc - Xpedio Linköping Ubiquitous Research Center
Author of "Mastering RMI"
Email: rickard@xpedio.com

Re: Jasper performance/3.3 tag pooling

Posted by Casey Lucas <cl...@armassolutions.com>.
Rickard,

Can you please send in some complete examples?  Also, did you run the
tests with and without tag pooling enabled on the same version of
tomcat?  (By adding removing TagPoolManagerInterceptor.)

My experience has been that if the jsp uses many tags, then pooling is
a big performance gain.  See comments below.

Rickard Öberg wrote:
> 
> Hi!
> 
> Ok, so now I've tested the Jasper performance with the 3.3 tag pooling
> fix. The test was performed with a medium complexity page using lots of
> iterative custom tags in a hierarchical fashion (i.e. tags within tags).
> 
> Results:
> The page ran slower, and above all the response time varied greatly
> (between 250ms and 460ms, whereas without tag pooling we got between
> 230ms and 340ms).
> 
> Looking at the generated code, I'm not particularly surprised: it uses
> (it seems) a real shared tag pool, so using tags will execute code that
> needs
> to be synchronized.

Yes, everytime you obtain a tag, there is a synch that occurs for the
pool that exists for each uniquely named tag and specific set of attributes.

There is actually a set of named pools per application context.

> 
> This is a bad design. Basically, any gains you get from reusing tags are
> lost due to the overhead and general performance decrease you get by
> using hashtables+"synchronized".
> 

Hash lookup is done once per jsp page - when the jsp page is first run.
After that, it's basically a synchronized push / pop pair on all subsequent
runs of the page.  In the future we can even get rid of the synch by using
thread local storage... one step at a time though. :)

> I've looked at pages generated by other more efficient JSP compilers
> (e.g. Resin), and they generally use another approach:
> Only reuse a tag within a particular page, and don't use a synchronized
> pool to do it. Just pass the instance around within the generated code.
> What is important is not primarily the global optimization gained by
> using pools, but the local optimization gained by not creating tags for
> each iteration in a iterative custom tag.
> 

Yes reusing a tag handler within a single page will be more efficient
(for that particular page) but I would guess that once we change to pool
per thread there's no way newing the tags at each use will be faster
(at least for a busy site with lots of tags.)

> This is waaaay more efficient, and also avoids the suboptimization of
> trying to reuse objects using Java code, something which is more
> efficiently
> handled by modern JVMs' memory management (i.e. creating objects using
> "new" is
> pretty snappy compared with Java-coded pools).
> 

I disagree.  I've found that object reuse can be a good performance
optimization.

> So, please remove the tag pooling, and do it right. If you don't believe
> me, do some benchmarking or something.
> 

I have done benchmarking and pooling enabled always wins.  :)  Maybe you
can send some examples so that we can try and track down the problems.

Thanks for taking a look at tag pooling.  I look forward to refining the
implementation.

-casey

Re: Jasper performance/3.3 tag pooling

Posted by Casey Lucas <cl...@armassolutions.com>.
I think the changes will be too big to add before the 3.3 freeze.  I like
your alternative and will start bashing the jsp->java files to get something
optimal before changing the jasper34 generator code.  I'll let you know when
I have something that looks interesting so that it can be discussed
before taking the time to modify the generator code.

-casey

cmanolache@yahoo.com wrote:
> 
> Casey,
> 
> We hope to freeze 3.3 for a release in the next weeks. If you feel the
> changes are reasonably small and will not create problems - you can still
> do it.
> 
> What about:
> 
> 1. We copy the code from 3.3 as it is in jasper34 area ( except that we
> rename the package ).
> 
> 2. We make sure it builds and runs in 3.3 - with a minimal set of changes:
> - copy jasper34.jar in lib/container
> - edit server.xml and replace <JspInterceptor> with <JspInterceptor34 >
> 
> 3. You can start making the optimizations, and I can start doing the
> refactoring, making sure we keep everything functional.
> 
> 4. In time we can merge the changes from 4.0, add the new interfaces
> proposed by Mel, add a new generator and so on - while making sure the
> tests are passing and jasper is stable.
> 
> This is unlikely to be finished before 3.3 is released, but we can make
> sure we keep passing all the test suites and we can release milestones of
> jasper34 for who needs the performance enhancements.
> 
> When the code is ready we can make a 3.3.1 release and replace the old
> jasper ( and same for when ajp14 is ready ).
> 
> What I tried in proposals/jasper34 is just wrong and against the basic
> ideas of "evolution" - and I realize that.
> 
> Just give me 2 days, I need to finish with xalan ( we just had the 2.1.0
> release and I need to finish my work on it )
> 
> Costin
> 
> On Wed, 23 May 2001, Casey Lucas wrote:
> 
> >
> > Costin & Craig,
> >
> > I agree with both of you.  The optimizations that Craig mentioned are
> > exactly the ones that I was hoping to add.  Yes, the least fun part
> > will probably be adding to the existing generator code.  But, until a
> > new generating architecture is in place, I think it would be good to
> > go ahead and try to add the code to the existing jasper.
> >
> > When the next gen jasper gets a lot of momentum, we can add the
> > tag related optimizations to it.
> >
> > -casey
> >
> > cmanolache@yahoo.com wrote:
> > >
> > > On Wed, 23 May 2001, Craig R. McClanahan wrote:
> > >
> > > > I know Costin loves evolutionary change :-), and it's certainly a valid
> > > > approach to Jasper.
> > > >
> > > > But there is also another approach we should consider - a green-field
> > > > recoding of at least some of the major components (conforming to an
> > > > agreed-upon overall architecture, of course).
> > >
> > > > NOTE:  For most of the rest of the overall problem (the PageContext
> > > > implementation, how Jasper fits in with the servlet container, and so
> > > > on) evolution is probably a very reasonable strategy.  On the compiler,
> > > > though, I'm not so sure.
> > >
> > > If we are talking about the compiler ( or code generator ): I partially
> > > agree, the current architecture will get a lot of pressure from more
> > > complex optimizations or tricks.
> > >
> > > But before we can even start to change the generator we need to do the
> > > initial refactoring and get the other components in order ( runtime, etc).
> > > We can also get some optimizations in, and use that to learn what's needed
> > > from a new generator architecture.
> > >
> > > I just don't think the new generator can happen in a 3.4 space - my goal
> > > is just to enable an effort to rewrite it, and gather as much information
> > > as possible about it's requirements.
> > >
> > > In any case - whatever happens in the current generator with regard to
> > > generated code  will still be usefull for any new generator architecture.
> > > And if certain optimizations can't be done - that's even better, because
> > > it would help us understand what's needed.
> > >
> > > I had big hopes for an XSLT based generator, and I still think it may be a
> > > good way to implement the code generator - and I hope to hear other
> > > ideas.
> > >
> > > Costin
> >

Re: Jasper performance/3.3 tag pooling

Posted by cm...@yahoo.com.
Casey,

We hope to freeze 3.3 for a release in the next weeks. If you feel the
changes are reasonably small and will not create problems - you can still
do it. 

What about: 

1. We copy the code from 3.3 as it is in jasper34 area ( except that we
rename the package ).

2. We make sure it builds and runs in 3.3 - with a minimal set of changes:
- copy jasper34.jar in lib/container
- edit server.xml and replace <JspInterceptor> with <JspInterceptor34 >

3. You can start making the optimizations, and I can start doing the 
refactoring, making sure we keep everything functional.

4. In time we can merge the changes from 4.0, add the new interfaces
proposed by Mel, add a new generator and so on - while making sure the
tests are passing and jasper is stable. 

This is unlikely to be finished before 3.3 is released, but we can make
sure we keep passing all the test suites and we can release milestones of
jasper34 for who needs the performance enhancements. 

When the code is ready we can make a 3.3.1 release and replace the old
jasper ( and same for when ajp14 is ready ). 


What I tried in proposals/jasper34 is just wrong and against the basic
ideas of "evolution" - and I realize that. 

Just give me 2 days, I need to finish with xalan ( we just had the 2.1.0
release and I need to finish my work on it )

Costin






On Wed, 23 May 2001, Casey Lucas wrote:

> 
> Costin & Craig,
> 
> I agree with both of you.  The optimizations that Craig mentioned are
> exactly the ones that I was hoping to add.  Yes, the least fun part
> will probably be adding to the existing generator code.  But, until a
> new generating architecture is in place, I think it would be good to
> go ahead and try to add the code to the existing jasper.  
> 
> When the next gen jasper gets a lot of momentum, we can add the
> tag related optimizations to it.
> 
> -casey
> 
> cmanolache@yahoo.com wrote:
> > 
> > On Wed, 23 May 2001, Craig R. McClanahan wrote:
> > 
> > > I know Costin loves evolutionary change :-), and it's certainly a valid
> > > approach to Jasper.
> > >
> > > But there is also another approach we should consider - a green-field
> > > recoding of at least some of the major components (conforming to an
> > > agreed-upon overall architecture, of course).
> > 
> > > NOTE:  For most of the rest of the overall problem (the PageContext
> > > implementation, how Jasper fits in with the servlet container, and so
> > > on) evolution is probably a very reasonable strategy.  On the compiler,
> > > though, I'm not so sure.
> > 
> > If we are talking about the compiler ( or code generator ): I partially
> > agree, the current architecture will get a lot of pressure from more
> > complex optimizations or tricks.
> > 
> > But before we can even start to change the generator we need to do the
> > initial refactoring and get the other components in order ( runtime, etc).
> > We can also get some optimizations in, and use that to learn what's needed
> > from a new generator architecture.
> > 
> > I just don't think the new generator can happen in a 3.4 space - my goal
> > is just to enable an effort to rewrite it, and gather as much information
> > as possible about it's requirements.
> > 
> > In any case - whatever happens in the current generator with regard to
> > generated code  will still be usefull for any new generator architecture.
> > And if certain optimizations can't be done - that's even better, because
> > it would help us understand what's needed.
> > 
> > I had big hopes for an XSLT based generator, and I still think it may be a
> > good way to implement the code generator - and I hope to hear other
> > ideas.
> > 
> > Costin
> 


Re: Jasper performance/3.3 tag pooling

Posted by Casey Lucas <cl...@armassolutions.com>.
Costin & Craig,

I agree with both of you.  The optimizations that Craig mentioned are
exactly the ones that I was hoping to add.  Yes, the least fun part
will probably be adding to the existing generator code.  But, until a
new generating architecture is in place, I think it would be good to
go ahead and try to add the code to the existing jasper.  

When the next gen jasper gets a lot of momentum, we can add the
tag related optimizations to it.

-casey

cmanolache@yahoo.com wrote:
> 
> On Wed, 23 May 2001, Craig R. McClanahan wrote:
> 
> > I know Costin loves evolutionary change :-), and it's certainly a valid
> > approach to Jasper.
> >
> > But there is also another approach we should consider - a green-field
> > recoding of at least some of the major components (conforming to an
> > agreed-upon overall architecture, of course).
> 
> > NOTE:  For most of the rest of the overall problem (the PageContext
> > implementation, how Jasper fits in with the servlet container, and so
> > on) evolution is probably a very reasonable strategy.  On the compiler,
> > though, I'm not so sure.
> 
> If we are talking about the compiler ( or code generator ): I partially
> agree, the current architecture will get a lot of pressure from more
> complex optimizations or tricks.
> 
> But before we can even start to change the generator we need to do the
> initial refactoring and get the other components in order ( runtime, etc).
> We can also get some optimizations in, and use that to learn what's needed
> from a new generator architecture.
> 
> I just don't think the new generator can happen in a 3.4 space - my goal
> is just to enable an effort to rewrite it, and gather as much information
> as possible about it's requirements.
> 
> In any case - whatever happens in the current generator with regard to
> generated code  will still be usefull for any new generator architecture.
> And if certain optimizations can't be done - that's even better, because
> it would help us understand what's needed.
> 
> I had big hopes for an XSLT based generator, and I still think it may be a
> good way to implement the code generator - and I hope to hear other
> ideas.
> 
> Costin

Re: Jasper performance/3.3 tag pooling

Posted by cm...@yahoo.com.
On Wed, 23 May 2001, Craig R. McClanahan wrote:

> I know Costin loves evolutionary change :-), and it's certainly a valid
> approach to Jasper.
> 
> But there is also another approach we should consider - a green-field
> recoding of at least some of the major components (conforming to an
> agreed-upon overall architecture, of course).

> NOTE:  For most of the rest of the overall problem (the PageContext
> implementation, how Jasper fits in with the servlet container, and so
> on) evolution is probably a very reasonable strategy.  On the compiler,
> though, I'm not so sure.

If we are talking about the compiler ( or code generator ): I partially
agree, the current architecture will get a lot of pressure from more
complex optimizations or tricks.

But before we can even start to change the generator we need to do the
initial refactoring and get the other components in order ( runtime, etc).
We can also get some optimizations in, and use that to learn what's needed
from a new generator architecture.

I just don't think the new generator can happen in a 3.4 space - my goal
is just to enable an effort to rewrite it, and gather as much information
as possible about it's requirements. 

In any case - whatever happens in the current generator with regard to
generated code  will still be usefull for any new generator architecture.
And if certain optimizations can't be done - that's even better, because
it would help us understand what's needed. 

I had big hopes for an XSLT based generator, and I still think it may be a
good way to implement the code generator - and I hope to hear other
ideas. 

Costin


Re: Jasper performance/3.3 tag pooling

Posted by "Craig R. McClanahan" <cr...@apache.org>.

On Wed, 23 May 2001 cmanolache@yahoo.com wrote:

> On Wed, 23 May 2001, Casey Lucas wrote:
> 
> > 
> > btw, If i start tinkering, should I work with jasper34 or the 3.3 stuff?
> 
> Difficult question...
> 
> The problem with jasper34 is that it doesn't work yet ( the one in
> proposals/jasper34 - I still have to move it in the new repository ). Mea
> culpa - I tried to make big changes instead of the old slow evolution... 
> 
> I'll start importing the current jasper33 in the new repository and make
> sure it builds, and use it as the first step for 34. Then I'll stick with
> the step-by-step evolution. Merging with jasper40 and xslt can wait a bit.
> 

I know Costin loves evolutionary change :-), and it's certainly a valid
approach to Jasper.

But there is also another approach we should consider - a green-field
recoding of at least some of the major components (conforming to an
agreed-upon overall architecture, of course).

What has struck me about the custom tags pooling question is that we're
trying to make a non-optimizing compiler into an optimizing compiler "from
the ground up", rather than taking advantage of the decades of compiler
writing experience and designing one from the top down.

Just as a for instance about why we might want to consider this, let's
look at a mythical "iterate" tag with a nested tag inside:

  <x:iterate from="0" to="999">
    <x:foo name="bar" value="<%= ... an expression %>"/>
  </x:iterate>

Today, Jasper will do a "new FooTag()" plus all of the associated tag
setup, inside the loop, 1000 times.  Tomorrow, using tag pooling can mean
that there will only be at most one create, but you've still got the
allocate/deallocate overhead plus the redundant setXxxx calls.

However, it's perfectly legal for the pseudo-code generated by this page
to look like this (see the examples in the JSP spec):

  IterateTag iteratetag = new IterateTag(); // or allocate from a pool
  iterateTag.setPageContext(...);
  iterateTag.setParent(null);
  iterateTag.setFrom(0);
  itearteTag.setTo(999);

  FooTag fooTag = new FooTag(); // Or allocate from a pool
  fooTag.setPageContext(...);   // Lifted out of the loop
  fooTag.setParent(iterateTag); // Lifted out of the loop
  fooTag.setName("bar");        // Lifted out of the loop

  ... iterate-start implementation ... {
    fooTag.setValue(expression);
    fooTag.doStartTag();
    fooTag.doEndTag();
  } ... iterate-end implementation ...

  fooTag.release();
  fooTag = null;  // or recycle to a pool

  iterateTag.release();
  iterateTag = null; // or recycle to a pool

In other words, you pay either *one* object creation or *one*
allocate/deallocate for the <x:foo> tag instance, and you don't waste your
time doing stuff inside the loop that only needs to be done once.

Optimizing compilers can be made smart enough to do things like this, as
long as you take the time to build in the appropriate knowledge of the
language (in this case, JSP syntax and semantics) that you are
translating.  If you happened to take a compiler class along a degree
path, this kind of thing will probably look familiar.

I think we owe it to ourselves to consider whether a completely new
effort, at least for the compiler, might get us to better results
(probably with less overall development effort) than an evolutionary
approach based on the current code.

NOTE:  For most of the rest of the overall problem (the PageContext
implementation, how Jasper fits in with the servlet container, and so
on) evolution is probably a very reasonable strategy.  On the compiler,
though, I'm not so sure.

> 
> Costin
> 

Craig



Re: Jasper performance/3.3 tag pooling

Posted by cm...@yahoo.com.
On Wed, 23 May 2001, Casey Lucas wrote:

> 
> btw, If i start tinkering, should I work with jasper34 or the 3.3 stuff?

Difficult question...

The problem with jasper34 is that it doesn't work yet ( the one in
proposals/jasper34 - I still have to move it in the new repository ). Mea
culpa - I tried to make big changes instead of the old slow evolution... 

I'll start importing the current jasper33 in the new repository and make
sure it builds, and use it as the first step for 34. Then I'll stick with
the step-by-step evolution. Merging with jasper40 and xslt can wait a bit.


Costin



> 
> -casey
> 
> 
> > Regards,
> > 
> > Glenn
> > 
> > ----------------------------------------------------------------------
> > Glenn Nielsen             glenn@more.net | /* Spelin donut madder    |
> > MOREnet System Programming               |  * if iz ina coment.      |
> > Missouri Research and Education Network  |  */                       |
> > ----------------------------------------------------------------------
> 


Re: Jasper performance/3.3 tag pooling

Posted by Casey Lucas <cl...@armassolutions.com>.

Glenn Nielsen wrote:

[snip]

> 
> I just had an idea (dangerous things) regarding tag pooling optimizations.
> 
> When Jasper translates a page it should be able to generate information
> about which tag handler classes it needs, and for each tag handler, the
> profile of the attribute/value pairs.  At runtime Jasper could make one call
> to a tag pooling synchronized method to get all available instances of the tag handlers
> it needs.  Any tag handlers/attribute profiles it couldn't obtain, it would have
> to create.  Then it would manage its own local tag pool during the execution
> of the request.  On termination of the request, after the page has been committed
> to the remote client, it would make one call to a tag pooling synchronized
> method to recycle/add the tag handlers it used.  So there would only be 2
> synchronized methods per page for implementing tag pooling regardless of
> how many tags are used.  And you have the benifits of minimizing JVM memory
> usage by sharing a global JVM tag pool.
> 

that sparked something..

If we just bite the bullet and modify Jasper to correctly determine tag
handler usage within a page (i.e. not get a new (from pool or "new") tag
each time) then we can probably get the best of both worlds -- local
reuse of tag handler variables (I don't like to call that a pool) plus
application wide tag pooling.  If application wide tag pooling is too expensive,
then we can chunk it.  Regardless, the per page reuse should be a big
gain.

Next step might be to determine if, in certain situations, we can not re-call
tag setters.  The spec says that attributes set should be "persistent".
Rickard's test case would really benefit from setter optimization because
most time was spent in body of setter methods.

Any comments?

btw, If i start tinkering, should I work with jasper34 or the 3.3 stuff?

-casey


> Regards,
> 
> Glenn
> 
> ----------------------------------------------------------------------
> Glenn Nielsen             glenn@more.net | /* Spelin donut madder    |
> MOREnet System Programming               |  * if iz ina coment.      |
> Missouri Research and Education Network  |  */                       |
> ----------------------------------------------------------------------

Re: Jasper performance/3.3 tag pooling

Posted by Rickard Öberg <ri...@xpedio.com>.
Glenn Nielsen wrote:
> I just had an idea (dangerous things) regarding tag pooling optimizations.
> 
> When Jasper translates a page it should be able to generate information
> about which tag handler classes it needs, and for each tag handler, the
> profile of the attribute/value pairs.  At runtime Jasper could make one call
> to a tag pooling synchronized method to get all available instances of the tag handlers
> it needs.  Any tag handlers/attribute profiles it couldn't obtain, it would have
> to create.  Then it would manage its own local tag pool during the execution
> of the request.  On termination of the request, after the page has been committed
> to the remote client, it would make one call to a tag pooling synchronized
> method to recycle/add the tag handlers it used.  So there would only be 2
> synchronized methods per page for implementing tag pooling regardless of
> how many tags are used.  And you have the benifits of minimizing JVM memory
> usage by sharing a global JVM tag pool.

I would be ok with that, as long as I can set the size of the pool to be
zero, since I don't trust Java coders to outperform the optimizations
done by the JVM as outlined in earlier posts.

/Rickard

-- 
Rickard Öberg
Software Development Specialist
xlurc - Xpedio Linköping Ubiquitous Research Center
Author of "Mastering RMI"
Email: rickard@xpedio.com

Re: Jasper performance/3.3 tag pooling

Posted by Glenn Nielsen <gl...@voyager.apg.more.net>.
Rickard Öberg wrote:
> 
> cmanolache@yahoo.com wrote:
> > > > We know the pool is synchronized and that may create problems under heavy
> > > > load, and we know how to fix this ( by using a per/thread pool without
> > > > synchronization ).
> > >
> > > That is one solution, but what do you do with the pool after page
> > > request?
> >
> > I'm not sure I understand. Each thread has a number of associated objects
> > that are recycled and reused - a Request object will "stick" with a
> > thread.
> >
> > Same can be done for the tag pools - except that this may use a lot of
> > memory ( but less than allocating/freeing ). It is possible to use a
> > middle ground, or tune this - but for maximum performance you can have a
> > local pool in each Request.
> 
> What I was considering is this: a pool is a managed resource, since it
> can shrink and grow. After a page request, you will want to reuse the
> pool and its contents, but you can't stick the contents into a global
> pool, because at next request how are you to know how many instances of
> a tag to put in the request-associated pool. I.e., thread-associated
> pools perform local optimizations per request/page, but for pools to be
> of any use they need to do global optimizations, i.e. pool the tags in a
> global pool. Otherwise you'll have lots of pools of tags and no way to
> manage them globally.
> 
> Example:
> Page request. No pools created yet.
> Page uses tag "foo" 10 times. Pool, associated with request/thread,
> created containing one "foo" tag instance.
> Concurrent page request with the above.
> Page uses tag "foo" 5 times. Another pool, associated with
> request/thread, created containing one "foo" tag instance.
> Both requests end: what to do with the pools?
> 1 Keep separate, each containing one instance
> 2 Merge so that there is only one pool for "foo" tags
> If 1, then there's no way to do proper global optimizations, i.e. say
> "don't create more than x tag instances".
> If 2, then at next request, what should the page associated "foo" pool
> contain? 1 tag instance, 2 tag instances..? The only way to really know
> is for the page to do its thing, and pull the tags from the global pool.
> And then you're in "synch" land again.
> 
> Do you understand now? I realize the above is a bit fuzzy...
> 
> > > I hope that Costin will be able to reproduce what I found.
> >
> > I hope not :-)
> >
> > Again - thanks for doing the tests and checking the code, and hope to see
> > more contributions and maybe few patches :-)
> 
> Jasper performance is a high priority thing for us (nr 1. on our "system
> performance fixing" list actually), so if possible, absolutely. I can't
> say I've delved that far into Jasper yet though. It was a bit hard to
> read.
> 
> > IMHO the right answer is "depends". And it depends on the actual use case,
> > on how many objects are created and where the synchronization occurs. For
> > tomcat, where we expect hundred of concurent requests and each would
> > create almost a hundred object ( that was the case in 3.0 ) - I doubt any
> > VM could make a difference.
> 
> Have you then considered the middle way I proposed, where each page
> creates the tags it needs, but only once. In my experience, the
> performance kills is in iterative and recursive use of tags, e.g.:
> <iterate>
>   <foo/>
> </iterate>
> which will create one "foo" tag per iteration in 3.2. *That's* the
> biggest problem IMHO. Creating the "iterate" and "foo" tag once for that
> page is not, considering that the overhead of managing pools of these
> tag instances is more resource draining, and hard to do properly on a
> global scale.
> 

I just had an idea (dangerous things) regarding tag pooling optimizations.

When Jasper translates a page it should be able to generate information
about which tag handler classes it needs, and for each tag handler, the
profile of the attribute/value pairs.  At runtime Jasper could make one call
to a tag pooling synchronized method to get all available instances of the tag handlers
it needs.  Any tag handlers/attribute profiles it couldn't obtain, it would have
to create.  Then it would manage its own local tag pool during the execution
of the request.  On termination of the request, after the page has been committed
to the remote client, it would make one call to a tag pooling synchronized
method to recycle/add the tag handlers it used.  So there would only be 2
synchronized methods per page for implementing tag pooling regardless of
how many tags are used.  And you have the benifits of minimizing JVM memory
usage by sharing a global JVM tag pool.

Regards,

Glenn

----------------------------------------------------------------------
Glenn Nielsen             glenn@more.net | /* Spelin donut madder    |
MOREnet System Programming               |  * if iz ina coment.      |
Missouri Research and Education Network  |  */                       |
----------------------------------------------------------------------

Re: Jasper performance/3.3 tag pooling

Posted by Casey Lucas <cl...@armassolutions.com>.
Hey Mel,

I'll use this as a chance to explain some thoughts
I've recently had on tag pooling.  Maybe you and
others have comments.

Mel Martinez wrote:
> 
> Hi folks!
> 
> I'm still overwhelmed with other priorities (new job,
> house-hunting, moving, etc.) to be able to help again,
> but I managed over the last day or so to get caught up
> with the list (for the most part - skipped some major
> threads along the way).
> 

Hope things are working out well.  I know where you're
coming from.  We just moved and are now in the process
of putting in a yard.

> On tag-pooling:  I am +1 on implementing a tag-cache
> on a per-page basis and tag-pooling on an application
> basis.  If/when we move to the interfaces and toolkit
> metaphor I proposed for Jasper34, then page-based
> caching can best be done by enabling access to a
> tag-cache via the page-life-cycle handler, the
> JspPageHandler interface.
> 

I agree.  I spent some time last week looking at possible
optimizations.  The general ideas were:

- pool tag handler objects per application. This could
still be turned on/off at runtime via module and is
already available.

- cache (re-use) handlers per page - i.e. only get the handler
from the pool once (when it is needed).  If application
wide pooling is disabled then we'll just "new" a handler.
To be clear: there won't be any data structures (stacks, etc.)
for caching -- it will just be done via the rendering.

- call most setters only once -- when the tag handler
is first obtained.  Attributes that are runtime expressions
will need to be called every time.

- in some situations we can pull out the tag handler
initialization code from inside "do" loops.  Currently,
if a Tag is inside of a BodyTag, the initialization for
the inner tag is done inside of the
do-while(BodyTag.doEndBody() == EVAL_BODY_TAG).  The
inner tag initializations only need to be done once
before the start of the do-while.  Pulling the inner
initializations/checks out of the do loop would be a nice
thing, but it won't be as important once the tags
and setter calls are re-used for the whole page.

- maybe get rid of some redundant do-while(false)
constructs and various other minor clean ups.

So, to summarize:  Each tag handler will be obtained once
per page (either from pool or via "new").  Setters
will be called once per handler per page.  Both obtaining
the handler and calling the setters will be done on
an as needed basis.  Yes, that will mean a synch call
to get each handler when it's first used if application
wide pooling is enabled.

So far, I was thinking that there would still be one tag
handler object per custom tag in the jsp page.  For example,
given:

<x:iterate count="100">
   <x:someTag/>
</x:iterate>
<x:someTag/>

there would still be 3 tag handler instances obtained.

The spec says the "someTag" handler could be reused because
tag scope allows it.  But then we have the question of when
to reuse handlers if scope allows it.  For example, if the
above was changed to:

<x:iterate count="100">
   <x:someTag attrib="abc"/>
</x:iterate>
<x:someTag attrib="xyz"/>

We could reuse the handler instance but would have to call
the setters for "attrib" each time.  What's more expensive, setter
call or just using a different handler?  Of course this
depends on tag usage and what the setters are doing.

So, for now, I was planning on not implementing tag handler
reuse across multiple uses of a custom tag in the same jsp.
This can, of course, be improved in the future.

> I am very much -1 on basing any sort of caching or
> pooling relative to the request thread using
> thread-local variables because it assumes the Thread
> will be pooled and reused - this may not be true in
> all containers and Jasper should be
> container-independent.
> 

I agree.  After the above stuff gets done, I hope
that we won't have to do any thread local variable
stuff.  I originally thought such optimizations would
be nice, but am now hoping that they won't be needed.
I'd like to make sure that all this stuff will (eventually)
work with tomcat 4 and future tomcats as well.

> Basically, one should think in terms of what temporal
> and access scope different objects have:  request,
> page, application, etc.  The JspPageHandler persists
> between requests for a page and should be used to
> represent access to objects and services concerned
> with the life-cycle of a page beyond one request, such
> as modification checking, name mangling,
> recompilation/loading as needed and clearly,
> tag-object caching.  Thus, it seems logical that tags
> could be retrieved via either directly from  methods
> on the page handler or from a tag cache manager object
> retrieved from the page handler.
> 
> Casey, do you see any problems following such a
> general design philosophy?  You are the lord gawd of
> the tag-pooling code, so I will defer to your
> judgement.
> 

I agree with the general design philosophy.  But don't
defer to much :) (The more I learn about Tomcat the more
I realize how much I don't know.) I haven't looked though
all the new Jasper stuff yet, but the idea sounds good.

> The source for the JasperToolkit and associated
> interfaces is still currently under
> jakarta-tomcat/src/jasper34/ and needs to be moved
> (along with the contents of
> jakarta-tomcat/proposals/jasper34) to
> jakarta-tomcat-jasper.  Unfortunately, I am not going
> to be able to do this for at least a couple of weeks
> or more (my jakarta dev environment is 300 miles
> away!).  I am chomping at the bit to resume coding on
> this, but alas, life has it's priorities.  I'm going
> to delay asking Brian for new passwords until I can
> move my network up here with me so I won't have access
> to the repositories until then.
> 

Costin is away for a while too.  Hopefully though we
can soon get things ironed out so that we can move forward
with jakarta-tomcat-jasper.

-casey

> I will try to at least stay caught up with the
> developments via this list.
> 
> Cheers,
> 
> Dr. Mel Martinez
> Extreme Blue/Cambridge
> IBM
> 
> __________________________________________________
> Do You Yahoo!?
> Get personalized email addresses from Yahoo! Mail - only $35
> a year!  http://personal.mail.yahoo.com/

Re: Jasper performance/3.3 tag pooling

Posted by Mel Martinez <me...@yahoo.com>.
Hi folks!

I'm still overwhelmed with other priorities (new job,
house-hunting, moving, etc.) to be able to help again,
but I managed over the last day or so to get caught up
with the list (for the most part - skipped some major
threads along the way).

On tag-pooling:  I am +1 on implementing a tag-cache
on a per-page basis and tag-pooling on an application
basis.  If/when we move to the interfaces and toolkit
metaphor I proposed for Jasper34, then page-based
caching can best be done by enabling access to a
tag-cache via the page-life-cycle handler, the
JspPageHandler interface.

I am very much -1 on basing any sort of caching or
pooling relative to the request thread using
thread-local variables because it assumes the Thread
will be pooled and reused - this may not be true in
all containers and Jasper should be
container-independent.

Basically, one should think in terms of what temporal
and access scope different objects have:  request,
page, application, etc.  The JspPageHandler persists
between requests for a page and should be used to
represent access to objects and services concerned
with the life-cycle of a page beyond one request, such
as modification checking, name mangling,
recompilation/loading as needed and clearly,
tag-object caching.  Thus, it seems logical that tags
could be retrieved via either directly from  methods
on the page handler or from a tag cache manager object
retrieved from the page handler.

Casey, do you see any problems following such a
general design philosophy?  You are the lord gawd of
the tag-pooling code, so I will defer to your
judgement.

The source for the JasperToolkit and associated
interfaces is still currently under
jakarta-tomcat/src/jasper34/ and needs to be moved
(along with the contents of
jakarta-tomcat/proposals/jasper34) to
jakarta-tomcat-jasper.  Unfortunately, I am not going
to be able to do this for at least a couple of weeks
or more (my jakarta dev environment is 300 miles
away!).  I am chomping at the bit to resume coding on
this, but alas, life has it's priorities.  I'm going
to delay asking Brian for new passwords until I can
move my network up here with me so I won't have access
to the repositories until then.

I will try to at least stay caught up with the
developments via this list.

Cheers,

Dr. Mel Martinez
Extreme Blue/Cambridge
IBM


__________________________________________________
Do You Yahoo!?
Get personalized email addresses from Yahoo! Mail - only $35 
a year!  http://personal.mail.yahoo.com/

Re: Jasper performance/3.3 tag pooling

Posted by Rickard Oberg <ri...@xpedio.com>.
> Thanks for sending the test application.  I've been using monthlist.jsp
while
> testing rendered then hand bashed code.  After some preliminary bashing :)
> I think it will be possible to call all setters (except runtime
expressions)
> only once per run of the page.  Also, we can create / obtain tag handler
instances
> only once per page run.

That is an excellent start!

> Anyway... after tweaking the rendered code, I was disappointed that there
> wasn't much of a change in the performance when I hit the page directly.
> The "optimized" version was even a bit slower :(  So, I hooked it up to a
> profiler.  It said that most of the time was being spent in
> webwork.util.ValueStack.findValue which is called from some of
> the setters and some of the do[Start|End]Tag methods.

Yeah, it's the by far most used method, and also where most of the magic
happens (name->value conversions). I've been tweaking it some, but probably
not enough.

> So, Is there any way you could send me a new webwork.jar (no need for the
> whole .war) that has tag implementations optimized for tag instance and
> setter call reuse?.  If you can move some/many of the calls to
ValueStack.findValue
> out of the doStart/doEnd methods, that should help.

I will start working on this after the weekend. However I am also rewriting
most of the tags for a new and simpler syntax, which is going to take some
coding time too, since all the examples need to be modified, docs, etc. I
will let you know as soon as possible though when the opts. are done.

> Yes, I know this doesn't solve the problem of why weblogic was faster
> for you, but any tag related optimizations we can make should help other
> tag users (me and my day job included).

Yup, that was the basic idea when I started this thread :-) Glad to see
things happen! :-)

> If you send a new jar, I'll test it out and let you know.

Will do.

/Rickard




Re: Jasper performance/3.3 tag pooling

Posted by Casey Lucas <cl...@armassolutions.com>.
Rickard, 

Thanks for sending the test application.  I've been using monthlist.jsp while
testing rendered then hand bashed code.  After some preliminary bashing :)
I think it will be possible to call all setters (except runtime expressions)
only once per run of the page.  Also, we can create / obtain tag handler instances
only once per page run.

Anyway... after tweaking the rendered code, I was disappointed that there
wasn't much of a change in the performance when I hit the page directly.
The "optimized" version was even a bit slower :(  So, I hooked it up to a
profiler.  It said that most of the time was being spent in
webwork.util.ValueStack.findValue which is called from some of
the setters and some of the do[Start|End]Tag methods.  So even though
the setters and tag handler "new"s were optimized, there wasn't much
change in page evaluation time.  (A strange note: under the profiler, the
optimized version ran in about 75% of the time it took the un-optimized
version.  Not sure why the big difference, but I have seen variations
like that before when code is run under a profiler.)

So, Is there any way you could send me a new webwork.jar (no need for the
whole .war) that has tag implementations optimized for tag instance and
setter call reuse?.  If you can move some/many of the calls to ValueStack.findValue
out of the doStart/doEnd methods, that should help.

Yes, I know this doesn't solve the problem of why weblogic was faster
for you, but any tag related optimizations we can make should help other
tag users (me and my day job included).

If you send a new jar, I'll test it out and let you know.

-casey

Rickard Öberg wrote:
> 
> cmanolache@yahoo.com wrote:
> > > Jasper performance is a high priority thing for us (nr 1. on our "system
> > > performance fixing" list actually), so if possible, absolutely. I can't
> > > say I've delved that far into Jasper yet though. It was a bit hard to
> > > read.
> >
> > I'm working on a refactoring of jasper, and "easy to read" is a big
> > priority. It's moving a bit slower than I expected - now I'm back on
> > planning stage after hearing so much bad things about using XSLT :-) But I
> > think there are ways to make ( almost ) everyone happy.
> >
> > I hope in few weeks ( after JavaOne ) we'll have something that works for
> > both 1.1 and 1.2 ( the first part of refactoring ), and we can start the
> > fun part - optimizing it.
> 
> Sounds like a good plan :-) I'd be happy to help out with commenting on
> the code. Code contribution is tricky right now (lots of other
> OpenSource projects to manage :-).
> 
> > The main problem is to avoid one synchronized call for each tag (
> > "new" _is_also_ a synchronized call on most VMs - it synchronizes
> > the heap !!! ).
> 
> Whoa.. I didn't know that.. that's an important factor to consider then.
> 
> > Tomcat3.3 has one synchronized call to get the worker
> > thread from the pool - and that doesn't seem to show up in any
> > performance tests.
> 
> As long as the synchs are few, and the block itself is short, you should
> be ok.
> 
> > We could keep a pool of pools ( probably for each context ). The local
> > pools can be unsynchronized - so we'll have only one sync per page. Each
> > context will have a set of pools ( with the size == the largest number of
> > concurent requests for that context ). And we can of course be agressive
> > in shrinking the pools that were not used recently.
> 
> That could work.
> 
> > We can try to do some of this in 3.3 space - or in a branch of 3.3 (
> > jasper34 is going to take a while, and I have a feeling you need results
> > fast ).
> 
> The big date for me is 2002-01-01. Before that I need some kind of
> "assurance" that it'll improve greatly 'till that time, or we need to
> look at alternatives (*shiver*).
> 
> So sooner than later, sure, but preferably righter than sooner. Get this
> stuff right, and I think you'll get lots of new supporters and keep old
> ones ;-)
> 
> > Regarding your application - I think we know the problem. There are few
> > things you can do to reduce the memory use, and you could cache and
> > recycle intermediary objects in each tag instance - you could benefit a
> > lot from the reuse of the tags.
> 
> I will start looking at optimizations on my side of things to, for sure.
> My code isn't extremely optimized, I know that, but OTOH I've tested the
> same code with WebLogic 5.0 (just to test) and it was waaaay faster, so
> there's definitely room on the JSP side to improve things.
> 
> > The memory savings of the thread pooling are not helping your application
> > yet ( since they are very small compared with the rest ), yet you pay the
> > synchronization price ( a lot - since you make heavy use of tags ). With
> > few changes in your app and few changes in the tag pool we could reverse
> > the situation - but if you disable the pool there's little chance you
> > could increase the performance above the current level.
> 
> Yup, that seems reasonable.
> 
> You mentioned in your private email that there was a lot of
> MethodDescriptor's being created. Please look into where these are
> coming from. They could be associated with the tag setters. Pool/cache
> these and you'll probably see some immediate results.
> 
> /Rickard
> 
> --
> Rickard Öberg
> Software Development Specialist
> xlurc - Xpedio Linköping Ubiquitous Research Center
> Author of "Mastering RMI"
> Email: rickard@xpedio.com

Re: Jasper performance/3.3 tag pooling

Posted by Rickard Öberg <ri...@xpedio.com>.
cmanolache@yahoo.com wrote:
> > Jasper performance is a high priority thing for us (nr 1. on our "system
> > performance fixing" list actually), so if possible, absolutely. I can't
> > say I've delved that far into Jasper yet though. It was a bit hard to
> > read.
> 
> I'm working on a refactoring of jasper, and "easy to read" is a big
> priority. It's moving a bit slower than I expected - now I'm back on
> planning stage after hearing so much bad things about using XSLT :-) But I
> think there are ways to make ( almost ) everyone happy.
> 
> I hope in few weeks ( after JavaOne ) we'll have something that works for
> both 1.1 and 1.2 ( the first part of refactoring ), and we can start the
> fun part - optimizing it.

Sounds like a good plan :-) I'd be happy to help out with commenting on
the code. Code contribution is tricky right now (lots of other
OpenSource projects to manage :-).

> The main problem is to avoid one synchronized call for each tag (
> "new" _is_also_ a synchronized call on most VMs - it synchronizes
> the heap !!! ). 

Whoa.. I didn't know that.. that's an important factor to consider then.

> Tomcat3.3 has one synchronized call to get the worker
> thread from the pool - and that doesn't seem to show up in any
> performance tests.

As long as the synchs are few, and the block itself is short, you should
be ok.

> We could keep a pool of pools ( probably for each context ). The local
> pools can be unsynchronized - so we'll have only one sync per page. Each
> context will have a set of pools ( with the size == the largest number of
> concurent requests for that context ). And we can of course be agressive
> in shrinking the pools that were not used recently.

That could work.

> We can try to do some of this in 3.3 space - or in a branch of 3.3 (
> jasper34 is going to take a while, and I have a feeling you need results
> fast ).

The big date for me is 2002-01-01. Before that I need some kind of
"assurance" that it'll improve greatly 'till that time, or we need to
look at alternatives (*shiver*).

So sooner than later, sure, but preferably righter than sooner. Get this
stuff right, and I think you'll get lots of new supporters and keep old
ones ;-)

> Regarding your application - I think we know the problem. There are few
> things you can do to reduce the memory use, and you could cache and
> recycle intermediary objects in each tag instance - you could benefit a
> lot from the reuse of the tags.

I will start looking at optimizations on my side of things to, for sure.
My code isn't extremely optimized, I know that, but OTOH I've tested the
same code with WebLogic 5.0 (just to test) and it was waaaay faster, so
there's definitely room on the JSP side to improve things.

> The memory savings of the thread pooling are not helping your application
> yet ( since they are very small compared with the rest ), yet you pay the
> synchronization price ( a lot - since you make heavy use of tags ). With
> few changes in your app and few changes in the tag pool we could reverse
> the situation - but if you disable the pool there's little chance you
> could increase the performance above the current level.

Yup, that seems reasonable. 

You mentioned in your private email that there was a lot of
MethodDescriptor's being created. Please look into where these are
coming from. They could be associated with the tag setters. Pool/cache
these and you'll probably see some immediate results.

/Rickard

-- 
Rickard Öberg
Software Development Specialist
xlurc - Xpedio Linköping Ubiquitous Research Center
Author of "Mastering RMI"
Email: rickard@xpedio.com

RE: Jasper performance/3.3 tag pooling (XSLT)

Posted by Paulo Gaspar <pa...@krankikom.de>.
Hi Costin,

> -----Original Message-----
> From: cmanolache@yahoo.com [mailto:cmanolache@yahoo.com]
> Sent: Wednesday, May 23, 2001 10:20 AM
>
> ...
>
> I'm working on a refactoring of jasper, and "easy to read" is a big
> priority. It's moving a bit slower than I expected - now I'm back on
> planning stage after hearing so much bad things about using XSLT :-) But I
> think there are ways to make ( almost ) everyone happy.
>
> ...

Considering your day job, I already had to change my "diagnostic" from
"you don't know what you are messing with" to "you know too much about
XSLT and then you think it is easy for everybody".

Still, I do not believe that using XSLT is a good idea. It goes a bit
against your own motivation of making Jasper more readable to make the
entry level lower for potential contributors.

Besides learning about Jasper, many will have to learn about XSLT. And
XSLT is not that easy to grasp. Worse, it is elusive - one tends to
think to have it all figured out before time, and then fall easy prey
of really big traps.


I am not going to argue with you about the CPU cost issue, since your
POV seems to be that everybody should manually compile JSPs for
production and that developers have good enough machines anyway.

We could start another holly war on this one, but I do not have the
motivation. I think that many people prefer doing it without manual
compilation, but we better just agree to disagree on that.


Anyway, for me, the main issue is the complexity of XSLT being an
obstacle for Jasper's code readability/maintenance.


In case you are wondering, I do not intend to use JSP for presentation
(I keep that Velocity is better at that) but I still think it as a lot
of potential as a server side scripting mechanism, with taglibs
providing an interesting way of defining simple dialects for common
problems and embedded Java filling the gaps. For simple logic, it looks
to have potential.


Have fun,
Paulo Gaspar



Re: Jasper performance/3.3 tag pooling

Posted by cm...@yahoo.com.
On Wed, 23 May 2001, Rickard Öberg wrote:

> Jasper performance is a high priority thing for us (nr 1. on our "system
> performance fixing" list actually), so if possible, absolutely. I can't
> say I've delved that far into Jasper yet though. It was a bit hard to
> read.

I'm working on a refactoring of jasper, and "easy to read" is a big
priority. It's moving a bit slower than I expected - now I'm back on
planning stage after hearing so much bad things about using XSLT :-) But I
think there are ways to make ( almost ) everyone happy.


I hope in few weeks ( after JavaOne ) we'll have something that works for
both 1.1 and 1.2 ( the first part of refactoring ), and we can start the
fun part - optimizing it.


> Have you then considered the middle way I proposed, where each page
> creates the tags it needs, but only once. In my experience, the
> performance kills is in iterative and recursive use of tags, e.g.:
> <iterate>
>   <foo/>
> </iterate>
> which will create one "foo" tag per iteration in 3.2. *That's* the
> biggest problem IMHO. Creating the "iterate" and "foo" tag once for that
> page is not, considering that the overhead of managing pools of these
> tag instances is more resource draining, and hard to do properly on a
> global scale.

Yes, in-page reuse is where thread local pools would probably make the
most difference. It's not only about the tag itself, it's also the
ContentBody and few other internal elements that need to be recycled.
( recycling the JspWriterImpl had a very nice effect ). 

The main problem is to avoid one synchronized call for each tag (
"new" _is_also_ a synchronized call on most VMs - it synchronizes 
the heap !!! ). Tomcat3.3 has one synchronized call to get the worker
thread from the pool - and that doesn't seem to show up in any
performance tests.

We could keep a pool of pools ( probably for each context ). The local
pools can be unsynchronized - so we'll have only one sync per page. Each
context will have a set of pools ( with the size == the largest number of
concurent requests for that context ). And we can of course be agressive
in shrinking the pools that were not used recently. 

We can try to do some of this in 3.3 space - or in a branch of 3.3 (
jasper34 is going to take a while, and I have a feeling you need results
fast ).

Regarding your application - I think we know the problem. There are few
things you can do to reduce the memory use, and you could cache and
recycle intermediary objects in each tag instance - you could benefit a
lot from the reuse of the tags.

The memory savings of the thread pooling are not helping your application
yet ( since they are very small compared with the rest ), yet you pay the
synchronization price ( a lot - since you make heavy use of tags ). With
few changes in your app and few changes in the tag pool we could reverse
the situation - but if you disable the pool there's little chance you
could increase the performance above the current level.

Costin


Re: Jasper performance/3.3 tag pooling

Posted by Rickard Öberg <ri...@xpedio.com>.
cmanolache@yahoo.com wrote:
> > > We know the pool is synchronized and that may create problems under heavy
> > > load, and we know how to fix this ( by using a per/thread pool without
> > > synchronization ).
> >
> > That is one solution, but what do you do with the pool after page
> > request?
> 
> I'm not sure I understand. Each thread has a number of associated objects
> that are recycled and reused - a Request object will "stick" with a
> thread.
> 
> Same can be done for the tag pools - except that this may use a lot of
> memory ( but less than allocating/freeing ). It is possible to use a
> middle ground, or tune this - but for maximum performance you can have a
> local pool in each Request.

What I was considering is this: a pool is a managed resource, since it
can shrink and grow. After a page request, you will want to reuse the
pool and its contents, but you can't stick the contents into a global
pool, because at next request how are you to know how many instances of
a tag to put in the request-associated pool. I.e., thread-associated
pools perform local optimizations per request/page, but for pools to be
of any use they need to do global optimizations, i.e. pool the tags in a
global pool. Otherwise you'll have lots of pools of tags and no way to
manage them globally.

Example:
Page request. No pools created yet.
Page uses tag "foo" 10 times. Pool, associated with request/thread,
created containing one "foo" tag instance.
Concurrent page request with the above.
Page uses tag "foo" 5 times. Another pool, associated with
request/thread, created containing one "foo" tag instance.
Both requests end: what to do with the pools?
1 Keep separate, each containing one instance
2 Merge so that there is only one pool for "foo" tags
If 1, then there's no way to do proper global optimizations, i.e. say
"don't create more than x tag instances".
If 2, then at next request, what should the page associated "foo" pool
contain? 1 tag instance, 2 tag instances..? The only way to really know
is for the page to do its thing, and pull the tags from the global pool.
And then you're in "synch" land again.

Do you understand now? I realize the above is a bit fuzzy...

> > I hope that Costin will be able to reproduce what I found.
> 
> I hope not :-)
> 
> Again - thanks for doing the tests and checking the code, and hope to see
> more contributions and maybe few patches :-)

Jasper performance is a high priority thing for us (nr 1. on our "system
performance fixing" list actually), so if possible, absolutely. I can't
say I've delved that far into Jasper yet though. It was a bit hard to
read.

> IMHO the right answer is "depends". And it depends on the actual use case,
> on how many objects are created and where the synchronization occurs. For
> tomcat, where we expect hundred of concurent requests and each would
> create almost a hundred object ( that was the case in 3.0 ) - I doubt any
> VM could make a difference.

Have you then considered the middle way I proposed, where each page
creates the tags it needs, but only once. In my experience, the
performance kills is in iterative and recursive use of tags, e.g.:
<iterate>
  <foo/>
</iterate>
which will create one "foo" tag per iteration in 3.2. *That's* the
biggest problem IMHO. Creating the "iterate" and "foo" tag once for that
page is not, considering that the overhead of managing pools of these
tag instances is more resource draining, and hard to do properly on a
global scale.

I might be wrong though 8-)

Nah. >:-)

/Rickard

-- 
Rickard Öberg
Software Development Specialist
xlurc - Xpedio Linköping Ubiquitous Research Center
Author of "Mastering RMI"
Email: rickard@xpedio.com

Re: Jasper performance/3.3 tag pooling

Posted by cm...@yahoo.com.
On Tue, 22 May 2001, Rickard Öberg wrote:

> Hi!
> 
> cmanolache@yahoo.com wrote:
> > Could you send a small page ( and the taglibs ) and the test conditions ?
> 
> I have sent taglib+page and test conditions to Costin.

Thanks, I'll try to add it to the tests dir.

> 
> > We know the pool is synchronized and that may create problems under heavy
> > load, and we know how to fix this ( by using a per/thread pool without
> > synchronization ).
> 
> That is one solution, but what do you do with the pool after page
> request?

I'm not sure I understand. Each thread has a number of associated objects
that are recycled and reused - a Request object will "stick" with a
thread.

Same can be done for the tag pools - except that this may use a lot of
memory ( but less than allocating/freeing ). It is possible to use a
middle ground, or tune this - but for maximum performance you can have a
local pool in each Request. 


> I hope that Costin will be able to reproduce what I found.

I hope not :-) 

Again - thanks for doing the tests and checking the code, and hope to see
more contributions and maybe few patches :-)

> I had a quick chat with the JRockit guys (the server JVM dudes) last J1,
> and they went "Waaah!" when I told them that JBoss pools EJB instances.
> The JVM would do a much better job with it in their opinion. If that's
> true or not I don't know, but I have seen other statements like that
> from other people.


IMHO the right answer is "depends". And it depends on the actual use case,
on how many objects are created and where the synchronization occurs. For
tomcat, where we expect hundred of concurent requests and each would
create almost a hundred object ( that was the case in 3.0 ) - I doubt any
VM could make a difference. 


Costin


Re: Jasper performance/3.3 tag pooling

Posted by Rickard Öberg <ri...@xpedio.com>.
Hi!

cmanolache@yahoo.com wrote:
> Could you send a small page ( and the taglibs ) and the test conditions ?

I have sent taglib+page and test conditions to Costin.

> We know the pool is synchronized and that may create problems under heavy
> load, and we know how to fix this ( by using a per/thread pool without
> synchronization ).

That is one solution, but what do you do with the pool after page
request?

> That was planned for later, in jasper34 space - but if you send code that
> shows a significant degradation in performance in some reasonable
> situations we can still fix it in 3.3.

I hope that Costin will be able to reproduce what I found.

> Regarding the default - I think it should be enabled, mostly because that
> will require people to make sure their taglibs are working corectly in a
> pooled environment. It should be possible to disable it on a per
> application basis, and we need to make sure we document how to do that.

I agree.

> I don't think the design is bad - just the implementation of the pool, but
> this is the first attempt with the goal of making sure the pooling work,
> optimizations will come later. The current experience with tomcat
> performance evolution from 3.1 to 3.3 shows that recycling objects has a
> huge effect ( if implemented corectly ) - and I see no reason why jasper
> would be different. 

Agree, object reuse can have nice effects. But the hash+sync overhead
must be balanced against the benefits of the actual object reuse.

> I'm looking forward to the VM where the allocation and
> GC will be free ( so far most do synchronize on object allocation ).

I had a quick chat with the JRockit guys (the server JVM dudes) last J1,
and they went "Waaah!" when I told them that JBoss pools EJB instances.
The JVM would do a much better job with it in their opinion. If that's
true or not I don't know, but I have seen other statements like that
from other people.

/Rickard

-- 
Rickard Öberg
Software Development Specialist
xlurc - Xpedio Linköping Ubiquitous Research Center
Author of "Mastering RMI"
Email: rickard@xpedio.com

Re: Jasper performance/3.3 tag pooling

Posted by cm...@yahoo.com.
Hi Rickard,

Could you send a small page ( and the taglibs ) and the test conditions ?

Most tests I run show a (significant) improvement in performance. 

We know the pool is synchronized and that may create problems under heavy
load, and we know how to fix this ( by using a per/thread pool without
synchronization ).

That was planned for later, in jasper34 space - but if you send code that
shows a significant degradation in performance in some reasonable
situations we can still fix it in 3.3.

Regarding the default - I think it should be enabled, mostly because that
will require people to make sure their taglibs are working corectly in a
pooled environment. It should be possible to disable it on a per
application basis, and we need to make sure we document how to do that.

I don't think the design is bad - just the implementation of the pool, but
this is the first attempt with the goal of making sure the pooling work,
optimizations will come later. The current experience with tomcat
performance evolution from 3.1 to 3.3 shows that recycling objects has a
huge effect ( if implemented corectly ) - and I see no reason why jasper
would be different. I'm looking forward to the VM where the allocation and
GC will be free ( so far most do synchronize on object allocation ).

Costin 

On Mon, 21 May 2001, Rickard Öberg wrote:

> Hi!
> 
> Ok, so now I've tested the Jasper performance with the 3.3 tag pooling
> fix. The test was performed with a medium complexity page using lots of
> iterative custom tags in a hierarchical fashion (i.e. tags within tags).
> 
> Results:
> The page ran slower, and above all the response time varied greatly
> (between 250ms and 460ms, whereas without tag pooling we got between
> 230ms and 340ms).
> 
> Looking at the generated code, I'm not particularly surprised: it uses
> (it seems) a real shared tag pool, so using tags will execute code that
> needs
> to be synchronized. 
> 
> This is a bad design. Basically, any gains you get from reusing tags are
> lost due to the overhead and general performance decrease you get by
> using hashtables+"synchronized".
> 
> I've looked at pages generated by other more efficient JSP compilers
> (e.g. Resin), and they generally use another approach:
> Only reuse a tag within a particular page, and don't use a synchronized
> pool to do it. Just pass the instance around within the generated code.
> What is important is not primarily the global optimization gained by
> using pools, but the local optimization gained by not creating tags for
> each iteration in a iterative custom tag.
> 
> This is waaaay more efficient, and also avoids the suboptimization of
> trying to reuse objects using Java code, something which is more
> efficiently
> handled by modern JVMs' memory management (i.e. creating objects using
> "new" is
> pretty snappy compared with Java-coded pools).
> 
> So, please remove the tag pooling, and do it right. If you don't believe
> me, do some benchmarking or something.
> 
> /Rickard
> 
>