Ваш тест не даст многого с точки зрения понимания того, как работает работа. Из-за характера JVM писать тесты производительности достаточно сложно, чтобы все системы были написаны для бенчмаркинга.
Чтобы понять, в чем разница, вы должны декомпилировать код, используя javap
.
Я составил этот класс:
public class MyClass {
public static void main(String[] args) {
for (int i = 0; i < 20; i++)
System.out.println(i);
}
}
И побежал javap -c MyClass
, чтобы получить это для main
:
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iload_1
3: bipush 20
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
}
я тогда сделал это снова, но на этот раз, использовали Преинкремент:
for (int i = 0; i < 20; ++i)
И я получил это для javap
:
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iload_1
3: bipush 20
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
}
Обратите внимание на что-нибудь? В частности, что они точно такие же?
Это связано с тем, что Java оптимизировала дополнительные инструкции по предварительной загрузке или после загрузки значения. Он распознает, что команда, которую он генерирует для загрузки переменной в регистр (iload_#
в javap
), является излишней и ненужной и оптимизирует ее.
В программировании есть термин, называемый преждевременной оптимизацией. Здесь вы оптимизируете то, что вам не нужно оптимизировать, потому что может вызывать проблемы с производительностью. Все, что вы действительно делаете, делает ваш код более сложным. Большинство «хороших» программистов (если такое существо существует) избегают этого и вместо этого сосредотачиваются на написании кода, который можно обслуживать. Если поддерживаемый код не работает хорошо, затем оптимизирован. Я помню, как читал ответ здесь о SO о трех разных уровнях программистов (начинающих, промежуточных, продвинутых) и о том, как сказать (свободно), в какую категорию вы попадаете. Я посмотрю, смогу ли я его найти.
Редактировать: Быстрое объяснение моего ответа: javac
скомпилирует ваши .java-файлы в байт-код. Байт-код хранится в файлах .class. Байт-код сообщает JVM шаг за шагом, как выполнить что-то. Например, iinc 1, 1
сообщает, что он принимает переменную 1
(в данном случае это i
) и увеличивайте ее на 1. iload_1
сообщает, что она принимает переменную 1
и загружает ее так, чтобы ее можно было использовать, как правило, при вызове операции или метода. Например, это:
8: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_1
12: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
означает "получить System.out
и загрузить его, а затем загрузить переменную # 1 (i
), теперь вызвать метод # 3." Когда мы вызываем метод, первое, что загружается (System.out
), является нашей «целью», что означает вызов метода для этого парня. Каждая другая вещь, загруженная в, передается в качестве аргумента. В этом случае это означает i
. Таким образом, эти три строки обозначают линию System.out.println(i)
. Байт-код просто говорит Java, что нужно делать на самом деле do что.
Тот факт, что в декомпилированном коде 0-нет декомпилированного кода как для предварительного, так и для последующего приращения, означает, что Java оптимизировал его, так как он понял, что на самом деле он не будет использоваться. В обоих случаях он просто сделал iinc
без iload
, что в точности противоречит большинству других ответов в этой теме.
Я бы не сказал, что эта программа действительно сообщает вам, какая версия «быстрее» в общем случае. –
Возможный дубликат [Is ++ x эффективнее, чем x ++ в Java?] (Http: // stackoverflow.com/questions/12396740/is-x-more-efficient-than-x-in-java) – hrv
Основной вопрос был в том, что предпочтительнее приращивание цикла for, а не более эффективного. Я все еще очень новичок в программировании, и я постоянно сталкиваюсь с неясными ошибками, используя конкретный оператор или метод, который работает в одной ситуации, а не другой. Просто хочу убедиться, что я правильно использую его. Спасибо всем за ваши ответы. – brock