This patch significantly improves the logging performance of the AbsoluteTimeDateFormat class (a.k.a. "%d{ABSOLUTE}"), and indirectly ISO8601DateFormat ("%d{ISO8601}") and DateTimeDateFormat (%d{"DATE"}).
The "HH:mm:ss," time string (less the "SSS" milliseconds portion) is cached and reused as long as the second does not change. Since many thousands of events can be logged each second, considerable CPU time can be saved by not recalculating the "HH:mm:ss," portion of the time string each time. In tests using JDK 1.3/Windows I've seen an overall log4j logging speed improvement of 10% to 50% depending on the date format used. Other Log4J date formatting classes could be changed to employ the same optimization. I'll leave it to someone else, since I don't use the other date formats. The method DecimalFormatSymbols.getDecimalSeparator() was also used instead of the previously hard coded "," character for the decimal point symbol in your machine's locale ("." in my case). This diff was made against jakarta-log4j-1.2alpha6/src/java/org/apache/log4j/helpers/AbsoluteTimeDateFormat.java -Andrew Vajoczki --- AbsoluteTimeDateFormat.java.orig Thu Jan 17 18:16:48 2002 +++ AbsoluteTimeDateFormat.java Thu Jan 17 21:20:14 2002 @@ -56,7 +56,11 @@ AbsoluteTimeDateFormat(TimeZone timeZone) { setCalendar(Calendar.getInstance(timeZone)); } - + + private static Object previousTimeLock = new Object(); + private static long previousTime; + private static char[] previousTimeWithoutMillis = new char[9]; // "HH:mm:ss." + /** Appends to <code>sbuf</code> the time in the format "HH:mm:ss,SSS" for example, "15:49:37,459" @@ -69,32 +73,52 @@ StringBuffer format(Date date, StringBuffer sbuf, FieldPosition fieldPosition) { - // We use a previously instantiated Date object to avoid the needless - // creation of temporary objects. This saves a few micro-secs. - calendar.setTime(date); - - int hour = calendar.get(Calendar.HOUR_OF_DAY); - if(hour < 10) { - sbuf.append('0'); - } - sbuf.append(hour); - sbuf.append(':'); - - int mins = calendar.get(Calendar.MINUTE); - if(mins < 10) { - sbuf.append('0'); - } - sbuf.append(mins); - sbuf.append(':'); - - int secs = calendar.get(Calendar.SECOND); - if(secs < 10) { - sbuf.append('0'); - } - sbuf.append(secs); - sbuf.append(','); + long now = date.getTime(); + int millis = (int)(now % 1000); + + synchronized (previousTimeLock) { + if ((now - millis) != previousTime) { + // We reach this point at most once per second + // across all threads instead of each time format() + // is called. This saves considerable CPU time. + + calendar.setTime(date); + + int start = sbuf.length(); + + int hour = calendar.get(Calendar.HOUR_OF_DAY); + if(hour < 10) { + sbuf.append('0'); + } + sbuf.append(hour); + sbuf.append(':'); + + int mins = calendar.get(Calendar.MINUTE); + if(mins < 10) { + sbuf.append('0'); + } + sbuf.append(mins); + sbuf.append(':'); + + int secs = calendar.get(Calendar.SECOND); + if(secs < 10) { + sbuf.append('0'); + } + sbuf.append(secs); + + // use current locale's decimal separator + sbuf.append(new java.text.DecimalFormatSymbols().getDecimalSeparator()); + + // store the time string for next time to avoid recomputation + sbuf.getChars(start, sbuf.length(), previousTimeWithoutMillis, 0); + + previousTime = now - millis; + } + else { + sbuf.append(previousTimeWithoutMillis); + } + } - int millis = calendar.get(Calendar.MILLISECOND); if(millis < 100) sbuf.append('0'); if(millis < 10)
AbsoluteTimeDateFormat.java.diff.gz
Description: GNU Zip compressed data
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>