--- /dev/null
+<HTML>\r
+<HEAD>\r
+ <!-- Created by GNNpress/1.2 -->\r
+ <!-- Changed by: Anselm Baird-Smith, 4-Feb-1997 -->\r
+ <TITLE>Jigsaw performance evaluation</TITLE>\r
+</HEAD>\r
+<BODY BGCOLOR="white">\r
+<P>\r
+<A HREF="../../../" TARGET="_top_"><IMG BORDER="0" SRC="/icons/WWW/w3c_home"\r
+ ALT="W3C" WIDTH="72" HEIGHT="48"></A>\r
+<A HREF="http://www.w3.org/pub/WWW/Jigsaw/" TARGET="_top_"><IMG SRC="/icons/jigsaw" WIDTH="212"\r
+ HEIGHT="49" ALT="Jigsaw" BORDER="0"></A>\r
+<P>\r
+ <HR>\r
+<P>\r
+<IMG SRC="/icons/32x32/caution.gif" ALT="WARN !" BORDER="0" WIDTH="32"\r
+ HEIGHT="32"> This page has not be updated since the 1.0alpha3 release, we\r
+do plan to do so real soon, stay tuned. To get some ideas as to how\r
+<B>Jigsaw</B> compares to a C based HTTP server, you may want to check the\r
+<A HREF="http://www.w3.org/Protocols/HTTP/Performance/Pipeline.html">HTTP\r
+Performance Paper</A> (which, even though not exactly on the same subject,\r
+provides a fair idea of relative performances).\r
+<P>\r
+ <HR>\r
+<H1>\r
+ Performance Evaluation\r
+</H1>\r
+<P>\r
+This document describes the current performance achieved by <B>Jigsaw</B>,\r
+and compare them to other servers. This paper is not intended to prove that\r
+<B>Jigsaw</B> is the fastest server (which it is not), it just tries to point\r
+out that writing a server in Java is a reasonable thing to do.\r
+<P>\r
+The second section of this document will describe the current bottlenecks,\r
+and hilight some of the possible work arounds (which will hopefully be included\r
+in the next <B>Jigsaw</B> release).\r
+<H2>\r
+ Numbers\r
+</H2>\r
+<H3>\r
+ Caveat\r
+</H3>\r
+<P>\r
+Benchmarking HTTPD servers is definitely a difficult task. They are at least\r
+two difficulties here:\r
+<UL>\r
+ <LI>\r
+ The configuration of the server to benchmark,\r
+ <LI>\r
+ The test-suite used to run the benchmark.\r
+</UL>\r
+<P>\r
+The benchmark will usually depend on things such as your hardware and your\r
+system, but also, the load of the machine you are using for the benches,\r
+the kind of filesystem the server runs in (is it NFS, AFS, does it uses some\r
+automounter ?), and a number of other parameters that are difficult to measure.\r
+The numbers we will give in this section have all been obtained under the\r
+same global configuration. This is a SunSparcstation 5, 64Mb of RAM, running\r
+solaris2.5, all files are served through a read/write AFS volume. I am probably\r
+lacking a number of interesting parameters in the latter description, that's\r
+why I will focus on relative numbers (i.e. how <B>Jigsaw</B> performs relatively\r
+to other servers), rather then absolute numbers. You shouldn't even try to\r
+scale these numbers in any ways: some servers speedup won't be linear with\r
+the power of the machine it runs on (e.g. if server foo is 2 times faster\r
+then server bar on a sparc station 5, the relative performance of foo and\r
+bar on a sparc 20 may not be the same).\r
+<P>\r
+How are these numbers collected ? The number we will present are <I>by no\r
+mean</I> related to what a typical server will experience in some real life\r
+conditions. For example, in our benchmarks, the client and the server programs\r
+are always run on the same machine. This probably affect the request rate,\r
+however, it still gives us a good indication of the CPU consumption of the\r
+server, which is what we are really interested in. To collect these numbers,\r
+we have used the ptester program which is a simple C hitter provided with\r
+the <A HREF="http://www.signum.se/phttpd/">phttpd server</A>.\r
+<H3>\r
+ The benchmarks\r
+</H3>\r
+<P>\r
+For each of the servers we measure, we run the following four benchmarks:\r
+<DL>\r
+ <DT>\r
+ Single document retreival\r
+ <DD>\r
+ This first bench gets the same document in sequence, and prints out the number\r
+ of requests achieved for a given duration of time. For those of you familiar\r
+ with ptester, the command line is as follows:<BR>\r
+ <VAR><CODE>ptester -t60 <document></CODE></VAR><BR>\r
+ We run this bench in two variants: first with a 4kb file(1.a) and 40kb file\r
+ (1.b)\r
+ <DT>\r
+ Multiple document retreival\r
+ <DD>\r
+ The second bench puts a little more load on the server, by requesting three\r
+ documents in parallel. The three documents are respectively of 4kb, 10kb\r
+ and 40kb. For those of you familiar with ptester, the command line is as\r
+ follows:<BR>\r
+ <CODE>ptester -t60 -rN <doc1> <doc2>\r
+ <doc3></CODE><BR>\r
+ We run this benchmark in two variants: first with N=2 (2.a) 2 simultaneous\r
+ hitters for each document, for a total of 6 simultaneous request flows and\r
+ with N=10 (2.b) for a total of 30 simultaneous connections.\r
+ <DT>\r
+ Keep-alive enabled bench\r
+ <DD>\r
+ This last bench will only benefit to those servers that implement the HTTP\r
+ keep-alive feature. Each connection will be used to run multiple requests.\r
+ For those of you familiar with ptester, the command line is as follows:<BR>\r
+ ptester -t60 -kN <document><BR>\r
+ The bench is only run for a single document of 4k, and for a <I>k</I> value\r
+ of 5, it is test 3.\r
+ <DT>\r
+ Long live bench\r
+ <DD>\r
+ This is to measure (or get some idea at least) the impact of the Java\r
+ garbage collector on <B>Jigsaw</B>. It's a replay of test 2 for a duration\r
+ of ten minutes, which give us our final benches 4.a and 4.b\r
+</DL>\r
+<H3>\r
+ Results\r
+</H3>\r
+<P>\r
+While running the benchmark, <B>Jigsaw</B> is configured to generate the\r
+appropriate (CommonLog) log files; no ident protocol is run.\r
+<P>\r
+We have obtained the following results:\r
+<P>\r
+<TABLE BORDER CELLPADDING="2">\r
+ <CAPTION ALIGN="Bottom">\r
+ Benchmark results in requests per second\r
+ </CAPTION>\r
+ <TR>\r
+ <TD></TD>\r
+ <TD>version</TD>\r
+ <TD>1.a</TD>\r
+ <TD>1.b</TD>\r
+ <TD>2.a</TD>\r
+ <TD>2.b</TD>\r
+ <TD>3</TD>\r
+ <TD>4.a</TD>\r
+ <TD>4.b</TD>\r
+ </TR>\r
+ <TR>\r
+ <TD><A HREF="http://www.w3.org/Daemon/">CERN-server</A></TD>\r
+ <TD>3.0</TD>\r
+ <TD>11</TD>\r
+ <TD>10</TD>\r
+ <TD>11</TD>\r
+ <TD>11</TD>\r
+ <TD>NA</TD>\r
+ <TD>11</TD>\r
+ <TD>10</TD>\r
+ </TR>\r
+ <TR>\r
+ <TD><A HREF="http://www.apache.org/">Apache</A></TD>\r
+ <TD>1.0.2</TD>\r
+ <TD>35</TD>\r
+ <TD>24</TD>\r
+ <TD>30</TD>\r
+ <TD>30</TD>\r
+ <TD>NA</TD>\r
+ <TD>33</TD>\r
+ <TD>30</TD>\r
+ </TR>\r
+ <TR>\r
+ <TD><A HREF="http://www.apache.org/">Apache</A></TD>\r
+ <TD>1.1.1</TD>\r
+ <TD>42</TD>\r
+ <TD>30</TD>\r
+ <TD>35</TD>\r
+ <TD>33</TD>\r
+ <TD>85</TD>\r
+ <TD>34</TD>\r
+ <TD>31</TD>\r
+ </TR>\r
+ <TR>\r
+ <TD><A HREF="http://www.signum.se/phttpd/">phttpd</A></TD>\r
+ <TD>0.99.70.1</TD>\r
+ <TD>46</TD>\r
+ <TD>37</TD>\r
+ <TD>39</TD>\r
+ <TD>38</TD>\r
+ <TD>4</TD>\r
+ <TD>39</TD>\r
+ <TD>37</TD>\r
+ </TR>\r
+ <TR>\r
+ <TD><B><A HREF="../../">Jigsaw</A></B></TD>\r
+ <TD>1.0alpha1</TD>\r
+ <TD>22</TD>\r
+ <TD>18</TD>\r
+ <TD>19</TD>\r
+ <TD>9</TD>\r
+ <TD>26</TD>\r
+ <TD>19(*)</TD>\r
+ <TD>8(*)</TD>\r
+ </TR>\r
+ <TR>\r
+ <TD><B><A HREF="../../">Jigsaw</A></B></TD>\r
+ <TD>1.0alpha3</TD>\r
+ <TD>22</TD>\r
+ <TD>18</TD>\r
+ <TD>19</TD>\r
+ <TD>18</TD>\r
+ <TD>26</TD>\r
+ <TD>19(*)</TD>\r
+ <TD>18(*)</TD>\r
+ </TR>\r
+</TABLE>\r
+<P>\r
+Due to some problems with the Java garbage collector, benches marked with\r
+a * have been run with 8 Mb of memory allocated to the Java interpreter rather\r
+than the default 1Mb, we'll come back to this.\r
+<P>\r
+Cells marked NA (not available) don't make sense for the given server (they\r
+don't support kepp-alive).\r
+<H2>\r
+ Lessons\r
+</H2>\r
+<P>\r
+A number of lessons can be deduced from the above performance numbers.\r
+Some of them are related to the current <B>Jigsaw</B> implementation,\r
+others are related to the current Java implementation.\r
+<P>\r
+All these lessons should be taken as hypothesis, only some experiments will\r
+tell the truth abouth these numbers.\r
+<H3>\r
+ <B>Jigsaw</B> implementation problems\r
+</H3>\r
+<P>\r
+Don't forget that <B>Jigsaw</B> current implementation is flaged as being\r
+<I>alpha</I>. This means a number of things, among which the fact that\r
+<B>Jigsaw</B> code has not yet been profiled and optimized. <B>Jigsaw</B>\r
+design should provide the basis of a fearly efficient httpd implementation.\r
+In particular, features such as authentication, logging, etc. which are not\r
+measured by the above benches should prove fearly efficient (the main reason\r
+for this assertion lies in the clever caching scheme <B>Jigsaw</B> uses for\r
+resource meta-informations).\r
+<P>\r
+However, what are the above numbers telling us ? First of all, benches 1.a\r
+and 1.b shows that <B>Jigsaw</B> throughput (the number of bytes/second it\r
+can emit) is not that bad. We did some experiments with a <I>native\r
+shuffler</I> to try to infer the cost of the actual file transmissions across\r
+the wire. This would run as follow: the Java part of the server would compute\r
+a reply, but would delegate the actual sending of the bytes to an efficient\r
+C multi-threaded process by using a Java native interface to the UNIX\r
+<CODE>sendmsg</CODE> system call. Although this gave us much better numbers\r
+on solaris 2.3, the results on solaris 2.5 were quite disapointing (the speed-up\r
+would totally disapear). The good news, however, is that the Java threaded\r
+IO performances are not that bad, and are probably not at this time the\r
+bottleneck. We do still, however, expect a significant boost in these number\r
+when the Java runtime will be able to use solaris native threads (although,\r
+at this stage, this should be taken as an intuition only).\r
+<H3>\r
+ As of 1.0alpha1\r
+</H3>\r
+<P>\r
+The real lesson from these numbers comes from the benches 2.a and 2.b.\r
+<B>Jigsaw</B> performance seems to be very sensitive to the number of\r
+<I>simultaneous</I> connections. After some quick investigation, our guess\r
+is that the main problem with the implementation is that it contains too\r
+many central resources, and that mutliple threads are mostly blocked trying\r
+to acquire them. At this point, we have detetected at least three of these:\r
+<DL>\r
+ <DT>\r
+ The <A HREF="../api/w3c.jigsaw.http.ClientPool.html">client pool</A>\r
+ <DD>\r
+ This object is the central part of the server: it dispatches incomming\r
+ connections to <I>client</I> objects which will then handle them. The current\r
+ implementation of the client pool has some nice features (for example, it\r
+ keeps a pool of threads, ready to run on behalf of any new incomming\r
+ connections). However it's current implementation locks the whole object\r
+ during the selection process of the client (which is poorly implemented right\r
+ now). This means that even if the server threads accept(2) connections as\r
+ fast as they arrive, it will block to acquire the lock on the client pool\r
+ before being able to dispatch the connection.\r
+ <DT>\r
+ The <A HREF="../api/w3c.tools.timers.EventManager.html">event manager</A>\r
+ <DD>\r
+ Before starting to read any incomming requests, client objects set a timer\r
+ in order to avoid maintaining idle connections for too long. Once the request\r
+ has been read and parsed, they then arm a second timer to control the duration\r
+ of the request processing. All these timers are set through a single event\r
+ manager, which is locked during both timers setting and timers cancelation.\r
+ To be more practical, if 10 simultaneous connections are made to the server,\r
+ then ten client objects will try to lock the event manager at the same time,\r
+ competing to acquire the appropriate lock.\r
+ <DT>\r
+ The <A HREF="../api/w3c.jigsaw.http.CommonLogger.html">logger</A>\r
+ <DD>\r
+ The logger is the central object in the server that logs all requests. As\r
+ for the above resources, deficiency in its current implementation (this logger,\r
+ for example, doesn't bufferize output) makes it a bottleneck.\r
+</DL>\r
+<P>\r
+Note that generally these bottlenecks exist only because the underlying\r
+implementation of the objects are not yet optimized (at this time, I don't\r
+think of them as being a design problem). To get an idea of how well\r
+<B>Jigsaw</B> would perform if these bottleneck were eliminated, I have put\r
+up together a version of <B>Jigsaw</B> that :\r
+<UL>\r
+ <LI>\r
+ Will no do any logging (that's easy, just undefine the <CODE>w3c.jigsaw.logger\r
+ property</CODE>)\r
+ <LI>\r
+ Will not register timeouts to the event manager (this makes sense since I\r
+ control the client side programs)\r
+</UL>\r
+<P>\r
+For the client pool, nothing simple can be done at this time. However, just\r
+with the two other optimizations, we already get 28 requests/second\r
+for bench 2.a and 22 requests/second for test 2.b. The really interesting\r
+thing is to notice how the gap between these two numbers disappear (which\r
+means we really had cotention problems).\r
+<P>\r
+This is for the <B>Jigsaw</B> implementation. We hope that by the next release\r
+all these contention problems will be solved (the three above are on the\r
+top of the TODO list). However, as we mentioned in the preamble of this section,\r
+there is another set of problems related to the current Java implementation.\r
+<H3>\r
+ Jigsaw 1.0alpha3\r
+ <IMG BORDER="0" SRC="/icons/WWW/new_red" WIDTH="32" HEIGHT="14">\r
+</H3>\r
+<P>\r
+Most of the 1.0alpha1 bottlenecks have been reduced, here is a brief overview\r
+of what has happened to the three previous ones:\r
+<DL>\r
+ <DT>\r
+ The <A HREF="../api/w3c.jigsaw.http.ClientPool.html">client pool</A>\r
+ <DD>\r
+ Has been entirely rewritten. The new client pool tries to be pretty smart\r
+ by running in one of <I>four</I> modes:\r
+ <UL>\r
+ <LI>\r
+ The first mode is the light load mode. Under that mode, <B>Jigsaw</B> keeps\r
+ connection alive as much as longer as possible (with <I>no</I> timeout values,\r
+ or whatever).\r
+ <LI>\r
+ The second mode is normal load mode. When entering that mode, <B>Jigsaw</B>\r
+ closes one idle persistent connection before actually accepting a new one.\r
+ This ensures that <B>Jigsaw</B> doesn't run out of socket descriptors.\r
+ <LI>\r
+ The third mode is the high load mode. In that mode, <B>Jigsaw</B> inverses\r
+ thread priority: it lowers the accepting thread priority lower to the normal\r
+ client threads priority, so that client threads can perform there tasks faster\r
+ then connections are accepted.\r
+ <LI>\r
+ Finally, the last mode, called the <I>dead</I> mode is when <B>Jigsaw</B>\r
+ starts refusing connections.\r
+ </UL>\r
+ <DT>\r
+ The <A HREF="../api/w3c.tools.timers.EventManager.html">event manager</A>\r
+ <DD>\r
+ The event manager jobs has been reduced to keep track of requests that take\r
+ to long to request. Getting rid of the keep alive timeout has basically reduced\r
+ by half the load on the event manager.\r
+ <DT>\r
+ The <A HREF="../api/w3c.jigsaw.http.CommonLogger.html">logger</A>\r
+ <DD>\r
+ The logger now uses a n optional buffer, that speeds up the critical section\r
+ were it emits log entries.\r
+</DL>\r
+<P>\r
+It should also be noted that <B>Jigsaw</B> HTTP API has been totally redesign,\r
+and is much more efficient the the one included in 1.0alpha1.\r
+<P>\r
+The result of these changes is mainly seen through the much better handling\r
+of simultaneous connections that <B>Jigsaw</B> now provides.\r
+<H3>\r
+ Java implementation problems\r
+</H3>\r
+<P>\r
+Although Java comes from an old (well, at least three years old) project,\r
+its current implementation is still pretty new. They are a number of problems\r
+with this implementation that need serious work to be fixed.\r
+<P>\r
+First of all, let's start with the byte-code interpretation, since this is\r
+what people are the most scared with. As our numbers show, <B>Jigsaw</B>\r
+out-performs the CERN server by far, on nearly all benches (except for benches\r
+4.a and 4.b, which we will come to later). The CERN server is written in\r
+C. So at least, this proves that the interpretation overhead of Java can\r
+be dealt with by a <I>better design</I>. I would guess that even when JIT\r
+compilers come out that are able to speed up Java code by 10 times, compiling\r
+<B>Jigsaw</B> with them won't make it ten times faster, just because byte-code\r
+interpretation may not be the overhead in <B>Jigsaw</B>.\r
+<P>\r
+The most serious problems with the current JDK is that it doesn't come with\r
+the appropriate tools for profiling and detecting the hot-sopt in the server's\r
+code. The three bottlenecks that we have exhibited in the previous section\r
+were found by simply printing the thread statuses at various point in time\r
+under heavy load. Getting the right tools should help a lot optimizing\r
+<B>Jigsaw</B> implementation.\r
+<P>\r
+Another problem with the current Java implementation is the thread-safe\r
+libraries. If you use the StringBuffer class, for example, you will slow\r
+down your application because most of its methods are synchronized, while\r
+at some point, you know your thread is the only one dealing with some instances\r
+of this class. The StringBuffer class is the first concern here, since you\r
+usually want to write code such as:\r
+<PRE>String x = ... ;\r
+String y = ... ;\r
+String xy = x + y ;\r
+</PRE>\r
+<P>\r
+What really happens in the third line here, is that you implicitly allocate\r
+a StringBuffer instance, initially filled up with the content of string\r
+<CODE>x</CODE>, and then you append to it the content of string\r
+<CODE>y</CODE>. Then you get the StringBuffer as a String to get back the\r
+result that you assign to <CODE>xy</CODE>. Note only have you allocated a\r
+StringBuffer object, but you had to allocate a monitor for it (locking the\r
+global monitor cache for some time), and then call a synchronized method\r
+in order to do the concatenation. Depending on the conditions in which the\r
+above code is running you can work-around it by implementing your own\r
+concatenation operations in your object (this is what <B>Jigsaw</B> MIME\r
+parser does, for example).\r
+<P>\r
+Now, we still haven't exlpain the purpose and the result of benches 4.a and\r
+4.b. These are meant to see how the Java garbage collector react when its\r
+hosting application is under heavy load. [WARNING: following explanations\r
+are not bullet-proof, also they have good roots.]. The general garbage collection\r
+process of Java can be divided in a two step process:\r
+<OL>\r
+ <LI>\r
+ The garbage collector runs, and detect all the objects that are currently\r
+ garbage (i.e not reachable from any of the global roots). These objects are\r
+ marked as such, but not yet collected.\r
+ <LI>\r
+ The finalizer runs through all the previously marked objects and\r
+ <I>finalize</I> them by invoking their <CODE>finalize</CODE> method.\r
+</OL>\r
+<P>\r
+Until an object has been finalized, its memory cannot be reused. Both stages\r
+one and two can run either asynchronously (i.e. when the system is idle)\r
+or synchronously (i.e. because they are required to run in order for the\r
+process to continue its job). The problem we are experiencing in benches\r
+4.a and 4.b is the following: as the server is never idle during the bench,\r
+the asynchronous version of the two stages is never able to run, so the\r
+server relies entirely on the synchronous version of them. What really happens\r
+here is best depicted by running the server with the <I>verbosegc</I> option\r
+turned on:\r
+<PRE>www24:Jigsaw$ java -verbosegc w3c.jigsaw.http.httpd \r
+loading properties from: /afs/w3.org/usr/abaird/Jigsaw/config/httpd.props\r
+*** Warning : no logger specified, not logging.\r
+[httpd]: listening at:http://www24.w3.org:9999\r
+<GC(async): freed 972 objects, 29712 bytes in 34 msec, 95% free>\r
+<GC(async): freed 2 objects, 16 bytes in 29 msec, 95% free>\r
+<GC: freed 3877 objects, 288960 bytes in 26 msec, 34% free>\r
+<GC: freed 736 objects, 285608 bytes in 23 msec, 54% free>\r
+<GC: freed 933 objects, 76040 bytes in 65 msec, 38% free>\r
+<GC: freed 1926 objects, 150320 bytes in 27 msec, 24% free>\r
+<GC: synchronously running 408 finalizers>\r
+<GC: freed 0 objects, 0 bytes in 64 msec, 24% free>\r
+<GC: expanded object space by 8192 to 847048 bytes, 25% free>\r
+...[more traces omited]\r
+</PRE>\r
+<P>\r
+What happens here is that the asynchornous GC never gets a chance to run\r
+(as expected). The synchronous GC tells us about its good work, however free\r
+memory ratio never improves: the finalization process doesn't run. As for\r
+the GC we don't expect the asynchronous version of it to run, but the synchronous\r
+finalizer falsly indicate that it has finazlied some objects (while in fact,\r
+the synchronous finalizer was probably unable to finalize them, because the\r
+asynchronous finalizer was lying around).\r
+<P>\r
+For real fun, here are two other traces collected under <I>exactly</I> the\r
+same circumstances:\r
+<PRE>www24:Jigsaw$ java -verbosegc w3c.jigsaw.http.httpd \r
+loading properties from: /afs/w3.org/usr/abaird/Jigsaw/config/httpd.props\r
+*** Warning : no logger specified, not logging.\r
+[httpd]: listening at:http://www24.w3.org:9999\r
+<GC(async): freed 972 objects, 29712 bytes in 34 msec, 95% free>\r
+<GC(async): freed 2 objects, 16 bytes in 27 msec, 95% free>\r
+<GC(async): freed 1424 objects, 92224 bytes in 61 msec, 86% free>\r
+<GC(async): freed 179 objects, 2368 bytes in 35 msec, 86% free>\r
+<GC(async): freed 520 objects, 41088 bytes in 33 msec, 86% free>\r
+<GC(async): freed 72 objects, 960 bytes in 38 msec, 86% free>\r
+<GC(async): freed 325 objects, 25680 bytes in 40 msec, 86% free>\r
+<GC(async): freed 45 objects, 600 bytes in 31 msec, 86% free>\r
+<GC(async): freed 1430 objects, 112992 bytes in 37 msec, 86% free>\r
+<GC(async): freed 198 objects, 2640 bytes in 31 msec, 86% free>\r
+<GC(async): freed 1950 objects, 154080 bytes in 37 msec, 86% free>\r
+<GC(async): freed 270 objects, 3600 bytes in 32 msec, 86% free>\r
+</PRE>\r
+<P>\r
+This run is pretty ideal. For some reasons, the asynchronous GC manages to\r
+run, and the memory is taken care of nicely (<B>Jigsaw</B> achieved 30\r
+requests/second during this test).\r
+<P>\r
+The last configuration I have encountered is the following:\r
+<PRE>www24:Jigsaw$ java -verbosegc w3c.jigsaw.http.httpd \r
+loading properties from: /afs/w3.org/usr/abaird/Jigsaw/config/httpd.props\r
+*** Warning : no logger specified, not logging.\r
+[httpd]: listening at:http://www24.w3.org:9999\r
+<GC(async): freed 972 objects, 29712 bytes in 35 msec, 95% free>\r
+<GC(async): freed 2 objects, 16 bytes in 27 msec, 95% free>\r
+<GC: freed 9208 objects, 707008 bytes in 33 msec, 84% free>\r
+<GC: freed 7233 objects, 571648 bytes in 34 msec, 82% free>\r
+<GC: freed 5834 objects, 460704 bytes in 34 msec, 81% free>\r
+<GC: freed 4550 objects, 359520 bytes in 34 msec, 80% free>\r
+<GC: freed 4485 objects, 354384 bytes in 36 msec, 79% free>\r
+<GC: freed 4420 objects, 349248 bytes in 41 msec, 78% free>\r
+<GC: freed 4355 objects, 344112 bytes in 40 msec, 77% free>\r
+<GC: freed 4355 objects, 344112 bytes in 42 msec, 76% free>\r
+<GC: freed 4355 objects, 344112 bytes in 44 msec, 75% free>\r
+<GC: freed 4290 objects, 338976 bytes in 45 msec, 74% free>\r
+<GC: freed 4160 objects, 328704 bytes in 46 msec, 73% free>\r
+<GC: freed 7222 objects, 309792 bytes in 41 msec, 79% free>\r
+<GC: freed 6319 objects, 297248 bytes in 31 msec, 83% free>\r
+<GC: freed 8631 objects, 647424 bytes in 32 msec, 84% free>\r
+<GC(async): freed 2557 objects, 129320 bytes in 42 msec, 86% free>\r
+<GC(async): freed 212 objects, 2848 bytes in 32 msec, 86% free>\r
+</PRE>\r
+<P>\r
+The memory keeps getting down, slowly. If the test continues for a while,\r
+the interpreter will fall back in the first situation presented above (i.e.\r
+trashing). However, whenever the test is stopped (as in the last two lines\r
+above) the asynchronous GC normally runs and get back all the memory.\r
+<H2>\r
+ Conclusion\r
+</H2>\r
+<P>\r
+What can you expect - with regard to performances - in the next <B>Jigsaw</B>\r
+release ? As said above, the <B>Jigsaw</B> implementation should improve,\r
+and provide better performances.\r
+<P>\r
+However, some real speed-up can be expected by better Java implementations\r
+in the next six monthes. By this time, the GC will hopefully be debugged,\r
+and on solaris at least, we can expect the native solaris threads to replace\r
+the Green thread package that is currently being used.\r
+<P>\r
+Send suggestions, comments, criticisms, corrections to\r
+<A HREF="mailto:jigsaw@w3.org">Jigsaw Team</A>\r
+<P>\r
+ <HR>\r
+<BR>\r
+<A HREF="mailto:jigsaw@w3.org">Jigsaw Team</A>.<BR>\r
+$Id: performance.html,v 1.1 2010/06/15 12:20:09 smhuang Exp $\r
+</BODY></HTML>\r