Odi's astoundingly incomplete notes

New entries | Code

Unexpected Date.before() / .after() performance impact

The java.util.Date class has two convenience methods before() and after(). If your application is very intensive on these Date operations, be careful of a performance bottleneck here!

Each call to before/after (and even getTime()) may have the cost of an internal object allocation. However not always. If you had called toString() on the instance before, then an object allocation will happen. Otherwise probably not.

To understand this we need to dive into the source code of Date. If you think about it, Date should be nothing more than a wrapper for a long variable holding a system timestamp. This variable is called fastTime. However the Date class has some deprecated methods that deal with a calendar date. These methods are from a time when original developers were confused about Date and Calendars, but have since been deprecated. But to support them Date still needs an internal Calendar instance of type sun.util.calendar.BaseCalendar.Date which is held in the variable cdate. Today this variable is usually null. That is as long as none of the deprecated interface has been used on the instance! Whenever it needs to convert the fastTime to a real date it will instantiate a BaseCalendar.Date in cdate. The problem is that toString() also performs a conversion to a real date. Too bad, toString() is very handy for logging. So any Date instance whose toString() method has been called once, will be slow and a memory waster.

The before/after methods are particularly bad because they will clone the cdate object on each call! The getTime() method is not as bad, but may still allocate a GregorianCalendar object.

My advice is, to never use Date.toString(), or completely work with long timestamps directly.

The bug has been reported to Sun.

posted on 2009-12-07 10:01 UTC in Code | 0 comments | permalink