You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@lucene.apache.org by Otis Gospodnetic <ot...@yahoo.com> on 2006/07/22 01:10:04 UTC

Re: svn commit: r424449 - /lucene/java/trunk/src/java/org/apache/lucene/document/DateTools.java

I remember reading somewhere (SDF javadoc?) that SDF instances are not thread-safe.  I take it that means class instances could mean trouble.

Otis

----- Original Message ----
From: dnaber@apache.org
To: java-commits@lucene.apache.org
Sent: Friday, July 21, 2006 4:38:23 PM
Subject: svn commit: r424449 - /lucene/java/trunk/src/java/org/apache/lucene/document/DateTools.java

Author: dnaber
Date: Fri Jul 21 13:38:23 2006
New Revision: 424449

URL: http://svn.apache.org/viewvc?rev=424449&view=rev
Log:
Don't re-create SimpleDateFormat objects, use static ones instead. Gives about a 2x performance increase in a micro benchmark.

Modified:
    lucene/java/trunk/src/java/org/apache/lucene/document/DateTools.java

Modified: lucene/java/trunk/src/java/org/apache/lucene/document/DateTools.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/document/DateTools.java?rev=424449&r1=424448&r2=424449&view=diff
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/document/DateTools.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/document/DateTools.java Fri Jul 21 13:38:23 2006
@@ -40,6 +40,26 @@
   
   private final static TimeZone GMT = TimeZone.getTimeZone("GMT");
 
+  private static final SimpleDateFormat YEAR_FORMAT = new SimpleDateFormat("yyyy");
+  private static final SimpleDateFormat MONTH_FORMAT = new SimpleDateFormat("yyyyMM");
+  private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("yyyyMMdd");
+  private static final SimpleDateFormat HOUR_FORMAT = new SimpleDateFormat("yyyyMMddHH");
+  private static final SimpleDateFormat MINUTE_FORMAT = new SimpleDateFormat("yyyyMMddHHmm");
+  private static final SimpleDateFormat SECOND_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
+  private static final SimpleDateFormat MILLISECOND_FORMAT = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+  static {
+    // times need to be normalized so the value doesn't depend on the 
+    // location the index is created/used:
+    YEAR_FORMAT.setTimeZone(GMT);
+    MONTH_FORMAT.setTimeZone(GMT);
+    DAY_FORMAT.setTimeZone(GMT);
+    HOUR_FORMAT.setTimeZone(GMT);
+    MINUTE_FORMAT.setTimeZone(GMT);
+    SECOND_FORMAT.setTimeZone(GMT);
+    MILLISECOND_FORMAT.setTimeZone(GMT);
+  }
+
+  // cannot create, the class has static methods only
   private DateTools() {}
 
   /**
@@ -54,7 +74,7 @@
   public static String dateToString(Date date, Resolution resolution) {
     return timeToString(date.getTime(), resolution);
   }
-  
+
   /**
    * Converts a millisecond time to a string suitable for indexing.
    * 
@@ -72,30 +92,41 @@
     
     cal.setTime(new Date(round(time, resolution)));
 
-    SimpleDateFormat sdf = new SimpleDateFormat();
-    sdf.setTimeZone(GMT);
-    String pattern = null;
+    String result;
     if (resolution == Resolution.YEAR) {
-      pattern = "yyyy";
+      synchronized (YEAR_FORMAT) {
+        result = YEAR_FORMAT.format(cal.getTime());
+      }
     } else if (resolution == Resolution.MONTH) {
-      pattern = "yyyyMM";
+      synchronized (MONTH_FORMAT) {
+        result = MONTH_FORMAT.format(cal.getTime());
+      }
     } else if (resolution == Resolution.DAY) {
-      pattern = "yyyyMMdd";
+      synchronized (DAY_FORMAT) {
+        result = DAY_FORMAT.format(cal.getTime());
+      }
     } else if (resolution == Resolution.HOUR) {
-      pattern = "yyyyMMddHH";
+      synchronized (HOUR_FORMAT) {
+        result = HOUR_FORMAT.format(cal.getTime());
+      }
     } else if (resolution == Resolution.MINUTE) {
-      pattern = "yyyyMMddHHmm";
+      synchronized (MINUTE_FORMAT) {
+        result = MINUTE_FORMAT.format(cal.getTime());
+      }
     } else if (resolution == Resolution.SECOND) {
-      pattern = "yyyyMMddHHmmss";
+      synchronized (SECOND_FORMAT) {
+        result = SECOND_FORMAT.format(cal.getTime());
+      }
     } else if (resolution == Resolution.MILLISECOND) {
-      pattern = "yyyyMMddHHmmssSSS";
+      synchronized (MILLISECOND_FORMAT) {
+        result = MILLISECOND_FORMAT.format(cal.getTime());
+      }
     } else {
       throw new IllegalArgumentException("unknown resolution " + resolution);
     }
-    sdf.applyPattern(pattern);
-    return sdf.format(cal.getTime());
+    return result;
   }
-
+  
   /**
    * Converts a string produced by <code>timeToString</code> or
    * <code>dateToString</code> back to a time, represented as the
@@ -121,26 +152,38 @@
    *  expected format 
    */
   public static Date stringToDate(String dateString) throws ParseException {
-    String pattern = null;
-    if (dateString.length() == 4 )
-      pattern = "yyyy";
-    else if (dateString.length() == 6 )
-      pattern = "yyyyMM";
-    else if (dateString.length() == 8 )
-      pattern = "yyyyMMdd";
-    else if (dateString.length() == 10 )
-      pattern = "yyyyMMddHH";
-    else if (dateString.length() == 12 )
-      pattern = "yyyyMMddHHmm";
-    else if (dateString.length() == 14 )
-      pattern = "yyyyMMddHHmmss";
-    else if (dateString.length() == 17 )
-      pattern = "yyyyMMddHHmmssSSS";
-    else
+    Date date;
+    if (dateString.length() == 4) {
+      synchronized (YEAR_FORMAT) {
+        date = YEAR_FORMAT.parse(dateString);
+      }
+    } else if (dateString.length() == 6) {
+      synchronized (MONTH_FORMAT) {
+        date = MONTH_FORMAT.parse(dateString);
+      }
+    } else if (dateString.length() == 8) {
+      synchronized (DAY_FORMAT) {
+        date = DAY_FORMAT.parse(dateString);
+      }
+    } else if (dateString.length() == 10) {
+      synchronized (HOUR_FORMAT) {
+        date = HOUR_FORMAT.parse(dateString);
+      }
+    } else if (dateString.length() == 12) {
+      synchronized (MINUTE_FORMAT) {
+        date = MINUTE_FORMAT.parse(dateString);
+      }
+    } else if (dateString.length() == 14) {
+      synchronized (SECOND_FORMAT) {
+        date = SECOND_FORMAT.parse(dateString);
+      }
+    } else if (dateString.length() == 17) {
+      synchronized (MILLISECOND_FORMAT) {
+        date = MILLISECOND_FORMAT.parse(dateString);
+      }
+    } else {
       throw new ParseException("Input is not valid date string: " + dateString, 0);
-    SimpleDateFormat sdf = new SimpleDateFormat(pattern);
-    sdf.setTimeZone(GMT);
-    Date date = sdf.parse(dateString);
+    }
     return date;
   }
   






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


Re: svn commit: r424449 - /lucene/java/trunk/src/java/org/apache/lucene/document/DateTools.java

Posted by Yonik Seeley <ys...@gmail.com>.
Uncontended locking in recent JVMs is relatively cheap... it had to be
made cheap given how much synchronization (much of it unneeded) goes
on in Java's standard libs.

As long as the synchronized operation is relatively quick and
relatively infrequent, there shouldn't be much contention and hence
not much overhead.

-Yonik

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


Re: svn commit: r424449 - /lucene/java/trunk/src/java/org/apache/lucene/document/DateTools.java

Posted by Simon Willnauer <si...@googlemail.com>.
Creating SimpleDateFormat instances are very expensive as Daniel
already said. I had similar issues with SDF in JSP pages formatting
lots a date strings. Using a simple stack or kind of pool reusing the
SDF instances turned out in a reasonable performance gain. That would
also solve the doubt about concurrent use, wouldn't it?!

regards Simon

On 7/22/06, Daniel Naber <lu...@danielnaber.de> wrote:
> On Samstag 22 Juli 2006 07:58, Chris Hostetter wrote:
>
> > however i'm not sure if the
> > performance benefits of the static instances Daniel mentioned in his
> > commit will exist in a multithreaded app (the synchronization costs may
> > outway the instantiation costs)
>
> I created a micro benchmark with 2 to 4 threads and the new version was
> faster about a factor of at least 2.
>
> Regards
>  Daniel
>
> --
> http://www.danielnaber.de
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: java-dev-unsubscribe@lucene.apache.org
> For additional commands, e-mail: java-dev-help@lucene.apache.org
>
>

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


Re: svn commit: r424449 - /lucene/java/trunk/src/java/org/apache/lucene/document/DateTools.java

Posted by Daniel Naber <lu...@danielnaber.de>.
On Samstag 22 Juli 2006 07:58, Chris Hostetter wrote:

> however i'm not sure if the
> performance benefits of the static instances Daniel mentioned in his
> commit will exist in a multithreaded app (the synchronization costs may
> outway the instantiation costs)

I created a micro benchmark with 2 to 4 threads and the new version was 
faster about a factor of at least 2.

Regards
 Daniel

-- 
http://www.danielnaber.de

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


Re: svn commit: r424449 - /lucene/java/trunk/src/java/org/apache/lucene/document/DateTools.java

Posted by Chris Hostetter <ho...@fucit.org>.
: I remember reading somewhere (SDF javadoc?) that SDF instances are not
: thread-safe.  I take it that means class instances could mean trouble.

correct, but all usages of the static formaters in this patch seem to be
synchronized, so it's probably not an issue -- however i'm not sure if the
performance benefits of the static instances Daniel mentioned in his
commit will exist in a multithreaded app (the synchronization costs may
outway the instantiation costs)

: Don't re-create SimpleDateFormat objects, use static ones instead. Gives
: about a 2x performance increase in a micro benchmark.



-Hoss


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