Я новичок в Java, и вчера вечером запускал какой-то код, и это меня очень беспокоило. Я создавал простую программу для отображения всех выходов X в цикле for, и я заметил МАССОВОЕ снижение производительности, когда я использовал модуль как variable % variable
против variable % 5000
или еще много чего. Может кто-нибудь объяснить мне, почему это происходит и чем это вызвано? Так что я могу быть лучше...
Вот "эффективный" код (извините, если я немного ошибаюсь в синтаксисе, я сейчас не на компьютере с кодом)
long startNum = 0;
long stopNum = 1000000000L;
for (long i = startNum; i <= stopNum; i++){
if (i % 50000 == 0) {
System.out.println(i);
}
}
Вот "неэффективный код"
long startNum = 0;
long stopNum = 1000000000L;
long progressCheck = 50000;
for (long i = startNum; i <= stopNum; i++){
if (i % progressCheck == 0) {
System.out.println(i);
}
}
Имейте в виду, у меня была переменная даты для измерения различий, и как только она стала достаточно длинной, первая заняла 50 мс, а другая - 12 секунд или что-то в этом роде. Возможно, вам придется увеличить stopNum
или уменьшить progressCheck
если ваш компьютер более эффективен, чем мой, или нет.
Я искал этот вопрос в Интернете, но не могу найти ответ, может быть, я просто не правильно его спрашиваю.
РЕДАКТИРОВАТЬ: Я не ожидал, что мой вопрос будет настолько популярным, я ценю все ответы. Я выполнил эталонный тест по каждой полученной половине времени, и неэффективный код занял значительно больше времени, 1/4 секунды против 10 секунд отдачи или взятия. Конечно, они используют println, но оба делают одинаковое количество, так что я бы не подумал, что это сильно исказит это, тем более что расхождение повторяется. Что касается ответов, так как я новичок в Java, я позволю голосам решить, какой ответ лучше. Я постараюсь выбрать один к среде.
РЕДАКТИРОВАТЬ 2: Я собираюсь сделать еще один тест сегодня вечером, где вместо модуля он просто увеличивает переменную, а когда он достигает progressCheck, он выполнит ее, а затем сбросит эту переменную на 0. для третьего варианта.
EDIT3.5:
Я использовал этот код, и ниже я покажу свои результаты.. Спасибо ВСЕМ за прекрасную помощь! Я также попытался сравнить короткое значение long с 0, поэтому все мои новые проверки выполняются когда-либо "65536" раз, делая его равным в повторениях.
public class Main {
public static void main(String[] args) {
long startNum = 0;
long stopNum = 1000000000L;
long progressCheck = 65536;
final long finalProgressCheck = 50000;
long date;
// using a fixed value
date = System.currentTimeMillis();
for (long i = startNum; i <= stopNum; i++) {
if (i % 65536 == 0) {
System.out.println(i);
}
}
long final1 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
//using a variable
for (long i = startNum; i <= stopNum; i++) {
if (i % progressCheck == 0) {
System.out.println(i);
}
}
long final2 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
// using a final declared variable
for (long i = startNum; i <= stopNum; i++) {
if (i % finalProgressCheck == 0) {
System.out.println(i);
}
}
long final3 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
// using increments to determine progressCheck
int increment = 0;
for (long i = startNum; i <= stopNum; i++) {
if (increment == 65536) {
System.out.println(i);
increment = 0;
}
increment++;
}
//using a short conversion
long final4 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
for (long i = startNum; i <= stopNum; i++) {
if ((short)i == 0) {
System.out.println(i);
}
}
long final5 = System.currentTimeMillis() - date;
System.out.println(
"\nfixed = " + final1 + " ms " + "\nvariable = " + final2 + " ms " + "\nfinal variable = " + final3 + " ms " + "\nincrement = " + final4 + " ms" + "\nShort Conversion = " + final5 + " ms");
}
}
Результаты:
- исправлено = 874 мс (обычно около 1000 мс, но быстрее из-за мощности 2)
- переменная = 8590 мс
- конечная переменная = 1944 мс (было ~ 1000 мс при использовании 50000)
- приращение = 1904 мс
- Короткое преобразование = 679 мс
Неудивительно, что из-за отсутствия деления "короткая конверсия" была на 23% быстрее "быстрого" пути. Это интересно отметить. Если вам нужно что-то показывать или сравнивать каждые 256 раз (или примерно там), вы можете сделать это и использовать
if ((byte)integer == 0) {'Perform progress check code here'}
ОДНО ЗАКЛЮЧИТЕЛЬНОЕ ЗАИНТЕРЕСОВАННОЕ ЗАМЕЧАНИЕ: использование модуля в "Окончательной объявленной переменной" с 65536 (не довольно большое число) вдвое быстрее (медленнее), чем фиксированное значение. Где раньше это было тестирование примерно с той же скоростью.