Hans Bergsten wrote:
Costin Manolache wrote:
[...]
Wow. I would be _very_ curious to see those benchmarks and the "modern"
JVM that was used.
All my tests ( including JDK1.4, IBM vms, GCJ ) show that reusing is well
worth the trouble - at least if you have 100s of requests per second
( it is not worht the trouble for very low loads ). But I'm happy to
hear that I'm wrong.
I'll try to find the figures we looked at and post them, or run a new
benchmark against TC 4.1 with and without tag handler pooling enabled.
But it may take some time, because right now I'm busy with other stuff.
If you disagree with the decision, you may want to send your feedback
to the EG: [EMAIL PROTECTED] JSP 2.0 is still just PFD.
Okay, I ran a few test cases with Tomcat 4.1.18. Benchmarks are of
course never perfect, but it should be good enough to evaluate the
difference with and without tag handler reuse.

My test server is a 1 GHz Pentium with 256 MB, with Sun's Linux
JDK 1.4.1. I ran all tests with Apache JMeter, once with 5 threads (so
the MAX_POOL_SIZE is not exceeded) and one time with 20 threads, with
and without pooling enabled.

I also hacked the servlet class generated with pooling enabled so that
there's no overhead from the reuse itself. I simple create one instance
of each tag handler at the beginning of the _jspService() method and
use this instance for all invokations. This is as efficient as it can
be, with no extra cost for synchronization or Map lookups. I ran this
test once with 20 threads.

I used this test page:

  <%@ page contentType="text/plain" %>
  <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core"; %>

  <c:forEach begin="1" end="100">
    <c:forEach begin="1" end="10">
      <c:out value="" />
    </c:forEach>
  </c:forEach>

While it's simple, it should show the impact of tag handler reuse.
With pooling disabled, one tag handler instance is created for the
outer <c:forEach>, a new one is created for the inner <c:forEach>
for each pass through the loop (i.e. 100 instances), and a new
instance for <c:out> is created for each invokation (i.e. 1000
instances). With pooling enabled, the total number of instances
depends on the number of concurrent requests. For the 5 threads tests,
it should stay close to 5 instances (although non-pooled instances
may occasionally be created and released immediately). For the 20
threads test, a lot more instances are created (since the pool is
currently limited to 5 instances), but it should still be less than
when pooling is disabled.

Okay, here are the results

            Without pooling  With pooling  Reuse w/o overhead
-------------------------------------------------------------
5 threads
  Avg.:              330 ms        349 ms                 N/A
  Rate:            15.2/sec      13.6/sec                 N/A

20 threads
  Avg.:            1,752 ms      1,446 ms            1,265 ms
  Rate:            12.1/sec      13.6/sec            14.7/sec

To me, this indicates that if you can avoid _all_ reuse overhead,
there's some performace to be gained from reuse but not much. With the
current implementation, however, the overhead seems to kill all gains
from creating fewer instances. I doubt increasing MAX_POOL_SIZE makes
much of a difference.

Feel free to run the test on your platform. It could be interesting
to see some more results. Also, if you think my test page is flawed,
I'd appreciate ideas for how to improve it.

Hans
--
Hans Bergsten                                <[EMAIL PROTECTED]>
Gefion Software                       <http://www.gefionsoftware.com/>
Author of O'Reilly's "JavaServer Pages", covering JSP 1.2 and JSTL 1.0
Details at                                    <http://TheJSPBook.com/>


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to