John
John

Reputation: 5297

Calendar.getInstance() performance improvement with 'warm up' call?

I have noticed that if i call Calendar.getInstance() once, before i really need Calendar instance, performance on second call is improved.

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());

    // this block of code performs faster if the above code is included
    Calendar calendar2 = Calendar.getInstance();
    calendar2.setTimeInMillis(System.currentTimeMillis());

I am getting time since epoch from my server and initializing calendar with it. The calendar is then parsed for hours, minutes, second and milliseconds which are passed to native function that sets time.

What i have noticed is that clock difference between nodes is 2-5 milliseconds if i instantiate dummy calendar first, and 15-20 milliseconds if i don't.

I am measuring round trip time and packet travel time from node A to B, and vice versa. I am sharing times tamps between nodes in request-response transactions and noticed that these time stamps are more off when there is no 'warm up'.

While it's probable that something is wrong with my measurements, i am consistently getting smaller values for travel times with the 'warm up' call.

I am looking at the source code of the Calendar and i don't see any explanation of this behavior.

Is there anything in calendar implementation that could affect performance of initialization with subsequent calls ?

Average from A to B: 21,4 

Average from A to B: 15,14 

Average from A to B: 14,84 

Average from A to B: 14,07 

With warm up call

Average from A to B: 11,8 

Average from A to B: 4,77 

Average from A to B: 4,54 

Average from A to B: 4,4

Update

Single call to native functions in advance seems to also benefit from performance improvement as time difference went to 0.8 - 1 millisecond.

Upvotes: 1

Views: 2081

Answers (1)

M A
M A

Reputation: 72864

Is there anything in calendar implementation that could affect performance of initialization with subsequent calls ?

Here's the code of Calendar#getInstance():

public static Calendar getInstance()
{
    Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));
    cal.sharedZone = true;
    return cal;
}

The code of TimeZone#getDefaultRef() is:

static TimeZone getDefaultRef() {
    TimeZone defaultZone = getDefaultInAppContext();
    if (defaultZone == null) {
        defaultZone = defaultTimeZone;
        if (defaultZone == null) {
            // Need to initialize the default time zone.
            defaultZone = setDefaultZone();
            assert defaultZone != null;
        }
    }
    // Don't clone here.
    return defaultZone;
}

and the one of Locale.getDefault(Locale.Category.FORMAT):

public static Locale getDefault(Locale.Category category) {
    // do not synchronize this method - see 4071298
    // it's OK if more than one default locale happens to be created
    switch (category) {
    case DISPLAY:
        if (defaultDisplayLocale == null) {
            initDefault(category);
        }
        return defaultDisplayLocale;
    case FORMAT:
        if (defaultFormatLocale == null) {
            initDefault(category);
        }
        return defaultFormatLocale;
    default:
        assert false: "Unknown Category";
    }
    return getDefault();
}

Notice how both of these methods check for already initialized variables, e.g. the static variables defaultTimeZone and defaultFormatLocale. At least this is expected to improve the performance of the second invocation of Calendar#getInstance().

Upvotes: 3

Related Questions