Pull to refresh
20
0
Александр Чебаненко @acebanenco

User

Send message
Спасибо, кэп. Именно байткод помог мне понять почему следующий код печатал 10 в jdk1.3:

{
  int i=10;
}
{
  int x; 
  println(x);
}


Именно тесты комманды работяющей над Lucene выявили на довольно подзней стадии серьезный баг в jdk7 перед самым релизом.
Ни один компилятор не развернет reversed loop, максимум закеширует array.length, т.е. пожертвует регистром ради производительности. Они, компиляторы, сейчас чертовски хороши, но их пока писали люди, а людям свойственно ошибаться. Давайте будем думать, а не идеализировать.
Ведь недалеко еще ушил те времена когда synchronized блок в однопоточной программе было страшное зло, где за вызов метода через интерфейс, а не конкретный класс (java.util.List vs java.util.ArrayList) били по рукам и т.п.
Было ведь?
Та я не обижаюсь, я в курсе что вы хорошие, карму Вам поплюсовал, думаю не подеремся из-за таких мелочей.
Про пример ответил выше.
та ладно. еще скажите что Вы белые и пушистые :)
Вы хорошие performance инженеры, Вам судьба велела цеплятся к мелочам, словам, незначительным деталям. Это бывает немного необычно, но как-то переживу.

Пример показывает что вынесение доступа к volatile переменной за скобки цикла дало прирост производителности. Хотя в обычной ситуации не дало бы ничего.

Есть две грани, с одной стороны можно писать код ради перформанса в ущерб функионалу, с другой стороны забить на все оптимизации и рекомендации. И то, и другое само по себе плохо, важно понимать где золотая середина, где надо знать что написание опреденного кода приведет к проблеме (например конкатенация строк в цикле), а где можно довериться оптимизатору и например не боятся виртуальных вызовов.

Все, можно ржать конструктивно критиковать.
У вас же в слайдах тоже есть замечательный пример. Вот тут http://shipilev.net/pub/talks/j1-April2012-jmm.pdf ближе к концу, там где

private volatile int[] array = new int[10000];
...
public void test(){
  int s = 0;
  for(int i=0; i<array.length; i++) {
    s+=array[i];
  }
  sum = s;
}

Throughput = 62 ops/msec. 


Жаль красным нельзя выделить как на слайде. И чего Вы на меня накинулись, кусок хлеба я у Вас не отбирал, дорогу Вам не переходил, может скучно было и решили срач в комментах развести, а тут еще и тема близкая по духу. Как-то глупо все вышло.
мда, извините, 2 буквы в спешке перепутал, правильно будет
— make it right

постораюсь больше их не путать.
Спасибо, оставте пожалуйста свой емайл чтобы мы могли Вам отсылать комменты на премодерацию.
Вобще ничего нет, ни стека, ни байткода, есть только джуниоры и грабли на которые они не наступают. Аминь!
А тем что все-таки наступили Вы отрываете все что торчит? Забавно…
«Есть» и «работают с» это разные вещи, в байткоде есть инструкции, а стек есть у виртуальной машины. У байткода нет стека. А только инструкции для работы с ним + max_stack:

«The value of the max_stack item gives the maximum depth of the operand stack of this method (§2.6.2) at any point during execution of the method.»
Я не настаиваю, просто сказал что постфиксному надо на один регистр больше, что бы у вас там не было, Java, C++, C… И я не против того что это ерунда в сравнении с мировой революцией.
Вы реально к словам цепляетесь и делаете вид что про стек не надо думать никогда, его типа нет. Да, в 99% случаев не надо про него думать, а про разницу пост- и преинкремента и вовсе можно забыть, но раньше это было актуально.

Вы отрицаете очевидное, как будто я придумал reverse for loop. Да в Java такими глупостями не стоит заморачиваться, ну разве что Вам действительно надо пройтись по массиву в обратном порядке. Повторюсь, слово «оптимизация» в кавычках кавычках кавычках кавычках кавычках.

Не надо мне доказывать что оптимизации зло, я сам могу рассказать про
— make it work
— make it rihgt
— make it fast.
Я Вас ни в чем не обвинял, просто сказал что у меня такое ощущение возникло.

И Вы меня простите конечно, но что и где именно я посоветовал что «вот так надо делать, а не то Ваше Java приложение сожрет все доступные ресурсы»?

1. По поводу пре- и постинкремента Вы согласитесь что раньше раньше раньше раньше на это замарачивались в цикле for из-за лишнего регистра?
2. Про сравнение с 1000, а не с нулем. Слово «оптимизация» в кавычках кавычках кавычках кавычках? А если по сути то что проще, загрузить 2 числа на стек и их сравнить или загрузить одно для сравнения? Точно издеваетесь, а жаль.

Я в том смысле что не ошибается тот, кто ничего не делает. Если Вы не разу не ошиблись в своей жизни, то что Вы делаете на этой грешной земле…
Сорри, привычка Ctrl+Enter нажимать

THIS IS SLOW
  for(int count=0; counter<1000; counter++) method(); 

тут используется постинкремент и неявное создание пустого массива

THIS IS FAST
  for(int count=1000; counter-->0;) method((String[])null)// this is fast

тут используется еще одна «оптимизация», сравнение с нулем быстрее чем с 1000. И не создается лишний мусор.

Ощущение что я от тролей отбиваюсь :(
Читаем еще раз:
> Ну разве что по старинке все привылки писать ++counter, а не counter++.

Ключевое слово по старинке. Раньше это было важно потому что постинкремент требует +1 регистр.
Представьте себе рекурсивный вызов, и в теле функции Вы наплевательски отнеслись к стеку. Это может закончится выходом за стек. Не думайте что StackOverflowError это только когда баг в рекурсии. Стек очень часто урезают на серверах для экономии памяти. (по умолчанию на стек дается 1MB, т.е. на тысячу потоков это 1GB).

P.S. Кстати в байткоде нет стека, там есть только max_stack: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.3
Вы может считает что ошибки делать нельзя, а я считаю что когда ты новичок ты только это и должен делать что ошибаться, ошибаться и еще раз ошибаться. А иначе никак.
Стек вызовов. Вы вроде бы не новичок, неужели действительно не знаете почему преинкремент предпочтительнее постинкремента?
Я не говорю про performance, он тут одинаковый.
Потому что если вы вызываете varargs метод в цикле и каждый раз при этом создается пустой массив, пусть и быстро создается, но все его назначение лишь в том чтобы бы съеденым GC, то лучше избежать этого.
void method(String... args) {
  // do something
}
void user() {
  for(int count=0; counter<1000; counter++) method(); // this is slow
  for(int count=1000; counter-->0;) method((String[])null)// this is fast
}

Information

Rating
Does not participate
Location
Киев, Киевская обл., Украина
Date of birth
Registered
Activity