При переходе через некоторые файлы в Java API, я заметил много случаев, когда цикл встречного уменьшенных, а не приращение. то есть в for
и while
петлях в классе String. Хотя это может быть тривиально, есть ли какое-либо значение для уменьшения счетчика, а не увеличения?
ответ
Я скомпилировал две простые петли с eclipse 3.6 (java 6) и посмотрел на байтовый код, есть ли у нас некоторые отличия. Вот код:
for(int i = 2; i >= 0; i--){}
for(int i = 0; i <= 2; i++){}
И это байткод:
// 1st for loop - decrement 2 -> 0
0 iconst_2
1 istore_1 // i:=2
2 goto 8
5 inc 1 -1 // i+=(-1)
8 iload_1
9 ifge 5 // if (i >= 0) goto 5
// 2nd for loop - increment 0 -> 2
12 iconst_0
13 istore_1 // i:=0
14 goto 20
17 inc 1 1 // i+=1
20 iload_1
21 iconst 2
22 if_icmple 17 // if (i <= 2) goto 17
Операция/декремент приращения не должна иметь никакого значения, это либо +1
или +(-1)
. Основное отличие в этом типичном (!) Примере заключается в том, что в первом примере мы сравниваем с номером (ifge i
), во втором - по сравнению со значением (if_icmple i 2
). И компиляция делается на каждой итерации. Таким образом, , если у есть какой-либо (небольшой) прирост производительности, я думаю, это потому, что сравнивать его с 0, а затем сравнивать с другими значениями. Таким образом, я думаю, что это не увеличение/уменьшение, что делает разницу, но критерии остановки.
Так что, если вы в необходимости сделать некоторые микро-оптимизацию на уровне исходного кода, попробуйте написать свои петли таким образом, чтобы вы сравнить с нулем, в противном случае оставьте его в читаемом как можно (и инкрементации является гораздо проще понять):
for (int i = 0; i <= 2; i++) {} // readable
for (int i = -2; i <= 0; i++) {} // micro-optimized and "faster" (hopefully)
Добавление
Вчера я сделал очень простой тест - только что создал массив 2000x2000 и заселен клетку, основанную на расчетах с клеточным отром ices, после подсчета от 0->1999
для обеих строк и ячеек, в другое время назад от 1999->0
. Я не был удивлен, что оба сценария имели аналогичную производительность (185..210 мс на моей машине).
Так да, есть разница в уровне байтового кода (eclipse 3.6), но, эй, мы сейчас в 2010 году, похоже, сейчас это не имеет существенного отличия. Итак, опять же, используя слова Стивенса, «не тратьте свое время» на такую оптимизацию. Держите код читаемым и понятным.
Ummm ...смотреть на байт-код не особо поучительно. Вам действительно нужно сделать тщательный анализ собственного кода, испускаемого компилятором JIT. –
@ Stephen C - Я не согласен, что это не поучительно, это дает нам верхнюю границу любой дельта производительности. Предполагая, что мы знали тайминги 'iconst',' ifge' и 'if_icmple' и что JIT не собирается делать что-либо более медленным *, можно сказать, что одна версия будет меньше X% медленнее, чем другая , – CurtainDog
Прохладный! Я даже не думал об этой проблеме в этом аспекте. Спасибо. – AlexR
В случае сомнения, контрольный показатель.
public class IncDecTest
{
public static void main(String[] av)
{
long up = 0;
long down = 0;
long upStart, upStop;
long downStart, downStop;
long upStart2, upStop2;
long downStart2, downStop2;
upStart = System.currentTimeMillis();
for(long i = 0; i < 100000000; i++)
{
up++;
}
upStop = System.currentTimeMillis();
downStart = System.currentTimeMillis();
for(long j = 100000000; j > 0; j--)
{
down++;
}
downStop = System.currentTimeMillis();
upStart2 = System.currentTimeMillis();
for(long k = 0; k < 100000000; k++)
{
up++;
}
upStop2 = System.currentTimeMillis();
downStart2 = System.currentTimeMillis();
for(long l = 100000000; l > 0; l--)
{
down++;
}
downStop2 = System.currentTimeMillis();
assert (up == down);
System.out.println("Up: " + (upStop - upStart));
System.out.println("Down: " + (downStop - downStart));
System.out.println("Up2: " + (upStop2 - upStart2));
System.out.println("Down2: " + (downStop2 - downStart2));
}
}
Со следующим JVM:
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04-307-10M3261)
Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03-307, mixed mode)
имеет следующий вывод (RAN это несколько раз, чтобы убедиться, что виртуальная машина была загружена и убедиться, что номера успокоились немного).
$ java -ea IncDecTest
Up: 86
Down: 84
Up2: 83
Down2: 84
Они все идут очень близко друг к другу, и у меня есть ощущение, что любое несоответствие является виной виртуальная машина загружается код в некоторых точках, а не другие, или фоновая задача происходит, или просто упасть и округляется на миллисекундной границе.
Хотя в какой-то момент (первые дни Java), возможно, было какое-то исполнение voodoo, мне кажется, что это уже не так.
Не стесняйтесь, попробуйте запустить/изменить код, чтобы увидеть сам.
Хотя я не думаю, что реальность была бы намного иной, чем это, помните, что это не очень хорошая микробиблиотека ... начиная с того, что она использует 'currentTimeMillis()', а не 'nanoTime()' для (прочитайте Javadoc для этих методов). Также взгляните на [this] (http://code.google.com/p/caliper/wiki/JavaMicrobenchmarks). – ColinD
Возможно, это связано с тем, что инженеры Sun делают много профилирования и микро-оптимизации, и те примеры, которые вы нашли, являются результатом этого. Также возможно, что они являются результатом того, что инженеры Sun «оптимизируют», основываясь на глубоком знании компиляторов JIT ... или на основе неглубокого/неправильного знания/вуду-мышления.
Это не исключено, что эти последовательности:
- быстрее, чем петли приращения,
- не быстрее или медленнее, чем петли приращения или
- медленнее, чем прибавка петель для последних виртуальных машин, и код больше не является оптимальным.
В любом случае, вы не должны подражать эту практику в вашем коде, если тщательное профилирование с последней JVM, демонстрирует, что:
- вашего код действительно выиграет от оптимизации, и
- декрементный цикл действительно быстрее, чем инкрементный цикл для вашего конкретного приложения.
И даже тогда, вы может обнаружить, что ваш тщательно ручной оптимизированный код меньше оптимальной на других платформах ... и что вам нужно повторить процесс снова и снова.
В наши дни общепризнано, что лучшей первой стратегией является написать простой код и оставить оптимизацию JIT-компилятору. Написание сложного кода (например, циклов, выполняющихся в обратном порядке) может фактически сорвать попытки компилятора JIT оптимизировать.
- 1. Счетчик вращения глобальных циклов
- 2. Счетчик циклов, не увеличивающий
- 3. Как сбросить счетчик циклов?
- 4. Вложенный счетчик циклов сброса
- 5. счетчик циклов в процедуре оракула
- 6. Счетчик циклов в языке D
- 7. Хотя счетчик циклов в PLSQL
- 8. Счетчик параллельных циклов в Julia
- 9. Excel VBA: перезапустить счетчик циклов
- 10. Счетчик циклов Python в цикле for
- 11. Java 8 Stream API эквивалент вложенных циклов
- 12. Использовать ввод пользователя как счетчик циклов
- 13. JavaScript - Можно ли уменьшить счетчик внутри циклов?
- 14. Счетчик циклов при рендеринге с {{render}}
- 15. Как сделать счетчик циклов использовать нулевое дополнение?
- 16. Как сбросить счетчик циклов для каждой строки?
- 17. Scala: проблема с прямой ссылкой + счетчик циклов
- 18. Обновить динамическое предложение where, используя счетчик циклов?
- 19. Как установить <%= ...> на счетчик циклов?
- 20. Как создать счетчик циклов во время цикла?
- 21. Как перебрать счетчик символов в Java?
- 22. Счетчик FPS в Java
- 23. Счетчик времени в Java
- 24. Объектно-ориентированный счетчик (Java)
- 25. Счетчик циклов и назначение переменных в шаблоне Django?
- 26. Как получить счетчик циклов/индекс, используя синтаксис for ... в JavaScript?
- 27. Как я могу увеличить счетчик каждые N циклов в JMeter?
- 28. PHP В то время как счетчик циклов ID ID
- 29. Как синхронизировать счетчик циклов «for» в многопоточном режиме?
- 30. Добавить счетчик циклов к данным CSV в jMeter
Я посмотрел на http://www.docjar.com/html/api/java/lang/String.java.html и видел только декрации, используемые в lastIndexOf, что имеет смысл. Можете ли вы указать нам на источник, на который вы смотрите? – Synesso
Это странно. Я смотрю исходный код JDK 1.6, и метод equals() отличается от ссылки, о которой вы упоминали. Я не могу найти эти строки в указанной вами ссылке. –
@Synesso @ darkie15: Это похоже на версию Apache Harmony «String». – ColinD