Использование new Date().getTime()
дает время часы стены. Но это действительно не то, что мы, как разработчики, хотим (большую часть времени, до тех пор, пока не будем проводить бенчмаркинг, где используется бенчмаркинг уровня предприятия), потому что время настенных часов выполняется многими процессами на задней панели, поэтому для противодействия тому, что Java предоставляет более сложный API для измерения времени.
Чтобы исключить эффекты другой активности системы, вам необходимо вместо этого измерить приложение «Пользовательское время».
- «время Пользователь» время, потраченное на работу собственного кода приложения.
- «Время процессора» - это время пользователя и системное время. Это общее время, потраченное на использование процессора для вашего приложения.
Ниже приведен пример, чтобы продемонстрировать расчет времени процессора и пользователя с использованием API ManagementFactory.getThreadMXBean()
.
Thread thread = new Thread(){
public void run() {
for (int i = 0; i < 100000; ++i) {
int result = 0;
for (int j = 0; j < i + 1; ++j) {
result += j;
}
}
System.out.println("FOR approach: ThreadCpuTime = " + ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime()/1000000000d);
System.out.println("FOR approach: UserTime = " + ManagementFactory.getThreadMXBean().getCurrentThreadUserTime()/1000000000d);
};
};
thread.start();
Thread thread2 = new Thread(){
public void run() {
for (int i = 0; i < 100000; ++i) {
int result = 0;
int j = 0;
while (j < i + 1) {
result += j++;
}
}
System.out.println("WHILE approach: ThreadCpuTime = " + ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime()/1000000000d);
System.out.println("WHILE approach: UserTime = " + ManagementFactory.getThreadMXBean().getCurrentThreadUserTime()/1000000000d);
};
};
thread2.start();
Сказав, что я действительно не знаю, почему вы получаете неожиданное поведение, я побежал ваш код, как в Eclipse, и IntelliJ IDE, и я всегда получал для подхода цикла, как это быстрее, чем цикл WHILE ,
Возможно, попробуйте перезапустить Eclipse и запустить меньшее количество фоновых процессов или не запускать его. Eclipse, но запустите тесты из командной строки Java, чтобы вы могли точно узнать результаты.
Как видно из ниже байт кода анализа что в то время, и для захода на посадку петли имеет одинаковые коды байт сгенерированные, что означает, что будет же собрать код и, следовательно, же процессорного времени потребуется для выполнения инструкций.
Но практически, когда мы запускаем вашу среду IDE или другие мудрые, это происходит из-за фоновых процессов, поэтому наблюдаются разные времена. Но в этом конкретном случае - WHILE v/s FOR, более целесообразно выполнять анализ байтового кода и заключить, что подходы WHILE и FOR будут выполняться в одно и то же время.
Байт код для цикла:
{
public Test2();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: bipush 10
5: if_icmpge 21
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_1
12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
15: iinc 1, 1
18: goto 2
21: return
LineNumberTable:
line 3: 0
line 4: 8
line 3: 15
line 6: 21
StackMapTable: number_of_entries = 2
frame_type = 252 /* append */
offset_delta = 2
locals = [ int ]
frame_type = 250 /* chop */
offset_delta = 18
}
Байт код цикла WHILE:
{
public Test();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: bipush 10
5: if_icmpge 21
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_1
12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
15: iinc 1, 1
18: goto 2
21: return
LineNumberTable:
line 3: 0
line 4: 2
line 5: 8
line 6: 15
line 8: 21
StackMapTable: number_of_entries = 2
frame_type = 252 /* append */
offset_delta = 2
locals = [ int ]
frame_type = 18 /* same */
}
Дальнейшее чтение:
Написание микро-теста на Java требует дополнительных усилий. Посмотрите эту тему: http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java для некоторого понимания области. –
Имейте в виду, что JVM всегда нуждается в разминке, для некоторых начальных исполнений результирующие времена не будут стоить внимания. –
Так звучит, что этот подход не рекомендуется, правильно? –