JDK-6594712 : [Fmt-Da] subclasses of DateFormatSymbols can have MASSIVE performance issues
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.text
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2007-08-20
  • Updated: 2013-11-01
  • Resolved: 2011-05-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u10Fixed 7 b22Fixed
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_02"
Java(TM) SE Runtime Environment (build 1.6.0_02-b05)
Java HotSpot(TM) Client VM (build 1.6.0_02-b05, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
Subclasses of DateFormatSymbols have MASSIVE performance issues if they attempt to parse date Strings with time zone information.

In the code that I supply below, benchmarking reveals that the "do nothing" subclass DateFormatSymbols2 has performance that is 1000X worse than its superclass's parse method if the date and time pattern that it is using contains time zone information.

That same class has essentially the same parsing performance, however, if the pattern omits TZ info.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the code below.  When I do, here is what I find:

benchmark for pattern = Gyyyy-MM-dd'T'HH:mm:ss.SSS, dateFormatSymbols = java.text.DateFormatSymbols:
4.638950197151737E-6 s

benchmark for pattern = Gyyyy-MM-dd'T'HH:mm:ss.SSSZ, dateFormatSymbols = java.text.DateFormatSymbols:
1.0008830173E-4 s

benchmark for pattern = Gyyyy-MM-dd'T'HH:mm:ss.SSS, dateFormatSymbols = DateFormatSymbolsSubclassBug$DateFormatSymbols2:
3.889240900357809E-6 s

benchmark for pattern = Gyyyy-MM-dd'T'HH:mm:ss.SSSZ, dateFormatSymbols = DateFormatSymbolsSubclassBug$DateFormatSymbols2:
0.053081175125 s

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The DateFormatSymbols2 subclass ought to have identical parsing performance as DateFormatSymbols in all circumstances.
ACTUAL -
It had worse performance when TZ info was present.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.Date;
import java.text.*;


/**
* This class proves how subclasses of DateFormatSymbols
* have massive performance issues if they attempt to parse date Strings with time zone information.
* <p>
* @author Brent Boyer
*/
public class DateFormatSymbolsSubclassBug {
	
	
	public static void main(String[] args) throws Exception {
		benchmark( "Gyyyy-MM-dd'T'HH:mm:ss.SSS", new DateFormatSymbols() );
		benchmark( "Gyyyy-MM-dd'T'HH:mm:ss.SSSZ", new DateFormatSymbols() );
		benchmark( "Gyyyy-MM-dd'T'HH:mm:ss.SSS", new DateFormatSymbols2() );
		benchmark( "Gyyyy-MM-dd'T'HH:mm:ss.SSSZ", new DateFormatSymbols2() );
	}
	
	
	private static void benchmark(String pattern, DateFormatSymbols dateFormatSymbols) throws Exception {
		System.out.println();
		System.out.println("benchmark for pattern = " + pattern + ", dateFormatSymbols = " + dateFormatSymbols.getClass().getName() + ":");
		
		DateFormat dateFormat = new SimpleDateFormat(pattern, dateFormatSymbols);
		
		String[] dateStrings = new String[100];
		for (int i = 0; i < dateStrings.length; i++) {
			dateStrings[i] = dateFormat.format( new Date(i) );
		}
		
			// do some warmup parsing before start timing to ensure classes loaded, hotspot optimizes, etc:
		for (String s : dateStrings) {
			dateFormat.parse(s);
		}
		
			// try to cleanup the JVM before start timing:
		System.runFinalization();
		System.gc();
		
		long tenSecondsInNs = 10L * 1000L * 1000L * 1000L;
		long t1 = System.nanoTime();
		long t2;
		int n = 0;
		do {
			for (String s : dateStrings) {
				dateFormat.parse(s);
			}
			++n;
			t2 = System.nanoTime();
		} while (t2 - t1 < tenSecondsInNs);
		double timeInS = (t2 - t1) / ( (1000.0 * 1000.0 * 1000.0) * (n * dateStrings.length) );
		System.out.println( timeInS + " s" );
	}
	
	
	/** Subclass of DateFormatSymbols that does NOTHING extra other than just be a subclass. */
	private static class DateFormatSymbols2 extends DateFormatSymbols {
		
		private static final long serialVersionUID = 1;
		
		private DateFormatSymbols2() {}
		
	}
	
	
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
None that I know of!

searching thru the bug database, I am guessing that this bug is the reason for the problem:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6304305

That bug is marked as fixed, but evidently the fix was just a hack that only works for DateFormatSymbols and not any subclasses of it.

Comments
EVALUATION Changed not to call getZoneStringWrappter() in matchDSTString() and matchZoneString().
21-08-2007