You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Glenn Nielsen <gl...@mail.more.net> on 2003/07/11 00:46:06 UTC

java Date related classes synchronization bottlenecks

David Rees wrote:
> Glenn,
> 
> This is quite interesting.  How many concurrent threads need to be
> running before this bottleneck starts to become a significant issue?

The worst case we have seen so far is when a JDBC query was made which
returned 100's of result sets where one of the fields was of type
DATE, TIME, or DATESTAMP.  A java.sql.(Date|Time|Timestamp) would get
created for each row in the result as you iterated over it. This was
with the MySQL Connector/J JDBC driver, other JDBC drivers might perform
better.

It doesn't take too many conncurrent requests doing this before the app
server starts bogging down.  Especially when there are other things using
Date related classes like web application code and Loggers.

Here is an example of what happens with the org.apache.catalina.logger.FileLogger:

      public void log(String msg) {

          // Construct the timestamp we will use, if requested
          Timestamp ts = new Timestamp(System.currentTimeMillis());
          String tsString = ts.toString().substring(0, 19);
          String tsDate = tsString.substring(0, 10);

         ...
     }


Now use jar to unarchive the src.jar file in your java SDK.
Take a look at the java.sql.Timestamp.toString() method which the FileLogger
above uses.

Each of the six get methods used in Timestamp.toString() trigger one or two
synchronizationsin in the underlying java.util.Date object.  Each of those get
methods end up calling a synchronized block on a static object in java.util.Date
and a call to the  static synchronized TimeZone.getDefault() method,
or one to two calls to the static synchronized TimeZone.getDefault() method.
So when the FileLogger logs it ends up hitting a synchronized block a minimum of
six times, but usually twelve times.

To verify this look at the source for java.util.Date.getField().

And there are many other synchronization bottlenecks in the following Date
related classes:

java.util.Calendar.getInstance()
java.util.Date
java.util.TimeZone.getDefault()
java.sql.Date
java.sql.Time
java.sql.Timestamp

  > Does a simple test case which simply starts up a number of threads which
  > all use one of the classes shown below display the problem nicely?

I am sure it would, I haven't had time to write one up yet.

Regards,

Glenn



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


Re: java Date related classes synchronization bottlenecks

Posted by David Rees <db...@greenhydrant.com>.
On Fri, Jul 11, 2003 at 08:57:54AM -0700, David Rees wrote:
> 
> System 4:
> Dual Mips R10k 225MHz, SGI Java 1.4.1 SGI IRIX

I was mistaken about the CPU freq of this machine, it really has 2 R10k
180MHz CPUs, not 225MHz.

-Dave

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


Re: java Date related classes synchronization bottlenecks

Posted by David Rees <db...@greenhydrant.com>.
Here are the results from the last version of the TestDatePerf program I
sent out.  Below are the results from 3 different systems when run for 1
million iterations.

Here's how I interpret the results:

The program verifies the synchronization performance issue.
Dual-CPU machines take a huge performance hit when going from 1-2
processes fighting for the same synchronized lock.  The dual processor
machine always performs worse than the single processor with more than 1
thread running and doesn't start catching up until 16 threads are running.

I did a few test runs when running 2 threads and watching the output from
top, I noticed that both CPUs were not kept busy (as expected).

Out of curiosity, I also tweaked the progrom and took out the call to
Timestamp.toString() and replaced it with some non-synchronized code. 
This code scaled almost perfectly when going from 1 to 2 threads on the
dual-cpu systems (run-time cut very close to 1/2) and increasing the
number of threads to 16 showed very little performance deviation over the
2 thread case.

So it looks like the bottleneck is real and depending on CPU performance I
would guess that you would start seeing when when you start making a few
thousand calls a second to these methods.

-Dave

------------

Each system ran the following:
time java TestJavaPerf <threads> 1000000
with threads values of 1, 2, 4, 8, 16.

All Linux systems on on kernel 2.4.20.  It would interesting to see if
recent 2.5.x kernels perform better as they reported have improved
multi-thread performance in the latest development kernels.

System 1:
Duron 600MHz, Sun Java 1.4.2, RedHat Linux

System 2:
PIII 500MHz, Sun Java 1.4.2, RedHat Linux

System 3:
Dual PIII 500MHz, Sun Java 1.4.2, RedHat Linux

System 4:
Dual Mips R10k 225MHz, SGI Java 1.4.1 SGI IRIX

Sys# Threads  Real   User   Sys
1    1        60.3   59.6   0.2
1    2        78.2   72.8   5.3
1    4       122.0   93.1  28.8
1    8       152.1  105.0  47.0
1    16      184.4  121.6  62.7
Sys# Threads  Real   User   Sys
2    1        80.5   80.2   0.3
2    2       108.0  111.2   3.2
2    4       177.2  141.5  34.4
2    8       290.1  200.3  88.5
2    16      325.2  220.0 103.9
Sys# Threads  Real   User   Sys
3    1        80.4   80.2   0.4
3    2       249.3  221.3  94.8
3    4       289.8  244.0 124.8
3    8       309.8  257.6 130.5
3    16      325.4  264.4 132.2
Sys# Threads  Real   User   Sys
4    1       197.0  186.9   1.5
4    2       289.7  487.5   8.9
4    4      1148.9  996.9 267.0
4    8      1734.8 1086.0 284.3
4    16     1717.2 1058.4 284.8


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


Re: java Date related classes synchronization bottlenecks

Posted by David Rees <db...@greenhydrant.com>.
On Thu, Jul 10, 2003 at 05:46:06PM -0500, Glenn Nielsen wrote:
> 
> Now use jar to unarchive the src.jar file in your java SDK.
> Take a look at the java.sql.Timestamp.toString() method which the FileLogger
> above uses.
> 
> To verify this look at the source for java.util.Date.getField().

Yes, that looks bad (looking at 1.4.2 src)!  It appears that avoiding calls to the
Timestamp.toString() is really to be avoided if possible.

> And there are many other synchronization bottlenecks in the following Date
> related classes:
> 
> java.util.Calendar.getInstance()
> java.util.Date
> java.util.TimeZone.getDefault()
> java.sql.Date
> java.sql.Time
> java.sql.Timestamp

I took a look at some of these, these don't appear to be as bad as the
Timestamp.toString().

I did a quick google of Date performance issues and didn't find
anything.  Is this a well known bottleneck in multi-threaded
applications?

>   > Does a simple test case which simply starts up a number of threads which
>   > all use one of the classes shown below display the problem nicely?
> 
> I am sure it would, I haven't had time to write one up yet.

I wrote a simple multithreaded program which makes calls to
Timestamp.toString() and varied the number of threads running and the
number of calls.  On a single CPU system (a Duron 600), scaling from
1-20 threads performed as I expected, with the 20 thread iteration
taking only slightly longer than the single thread iteration.  

However, when running this on a dual-cpu system (PIII 500), going from
1 to 2 treads took over twice as long for the same overall number of
calls to Timestamp.toString().  From 4-20 threads overall time
slightly increased most likely due to the overhead of scheduling
multiple threads.

You must be running on a multiple-CPU system as it doesn't appear to be
a bottle-neck (except for the fact that it's a slow operation) on a
single-cpu machine and only one multi-cpu machines.

Given that this is the case, a temporary fix in your case would be to
run as many Tomcat's as you have processors on that particular machine
(assuming you have enough memory)

-Dave