2013-03-03 5 views
1

Я использую этот маленький кусочек кода, чтобы проверить, какой метод быстрее:Большая разница по System.currentTimeMillis()

public void test() { 
    long start = System.currentTimeMillis(); 
    MyDate date = new MyDate(); 
    int max = 5000; 

    for (int i = 0; i < max; i++) { 
    Calendar.getInstance().getTimeInMillis(); // <-- 
    } 

    System.out.println("Calendar instance delay: " + (System.currentTimeMillis() - start)); 
    start = System.currentTimeMillis(); 

    for (int i = 0; i < max; i++) { 
    date.getMillis(); // <-- 
    } 

    System.out.println("My date delay: " + (System.currentTimeMillis() - start)); 
} 

Так, в принципе, я пытается сравнить производительность между Calendar.getInstance().getTimeInMillis() и MyDate.getMillis() (MyDate - это класс, созданный мной).

Ну, когда я запускал код, указанный выше, выход был:

Calendar instance delay: 413 
My date delay: 2 

НО, когда я перевернул заказ (первый под названием MyDate, и после того, как календарь), я получил:

My date delay: 247 
Calendar instance delay: 119 

Я попытался использовать System.nanoTime(), но произошло то же самое: первый проверенный код - тот, который занял больше времени.

Кто-нибудь знает, почему это происходит? Или, есть ли способ точно профилировать коды без использования внешнего приложения-профилировщика (только чистый код Java)?

Спасибо.

+0

Ну, во-первых, вы инициализируете объект даты внутри первого блока синхронизации. Во-вторых, вы можете столкнуться с GC-5000, вероятно, недостаточно вызовов. Наконец, действительно ли это проблема производительности в вашем приложении? –

+0

Каково ваше возражение против использования профилировщика? – Torious

+0

@PhilipWhitehouse Нет, я просто использую это для тестирования. – BloodShura

ответ

4

Чтобы проверить производительность «маленького» кода, вы должны называть его много раз. В противном случае эффекты JIT, кэширования и прогнозирования ветвлений испортят ваше тестирование. Если я позвоню вам по телефону, чтобы узнать, сколько времени потребуется, прежде чем ответить, я получу совсем другой ответ, если я просто позвоню тебе несколько секунд назад.

+0

Спасибо, Дэвид! – BloodShura

+0

+1 Короче говоря, вы должны игнорировать результаты первых 10000 итераций. Ответ заключается в том, что System.currentTimeMillis() является самым быстрым, как при чтении кода, который вы видите, все остальные называют это и выполняют некоторую дополнительную работу. –

1

Существует Секундомер класс Commons Lang, который использует System.nanoTime,

http://commons.apache.org/lang/

org.apache.commons.lang.time.StopWatch

+0

Спасибо! Я посмотрю на это. – BloodShura

1

При измерении производительности, имейте в виду, что JVM может исключить код, который не имеет побочных эффектов как часть оптимизации.

Чтобы избежать этого, вы можете сделать следующее:

for (int i = 0; i < max; i++) { 
    long a = date.getMillis(); 
    if (a % 1000 == i) { 
     System.out.print(a); 
    } 
} 

Еще одна вещь, чтобы быть в курсе, горячая точка-оптимизации. Перед измерением вы должны «разогреть» свой код.

+0

Спасибо, Мелоу! – BloodShura

Смежные вопросы