Pull to refresh

Comments 12

С этими оптимизациями на jvm сплошная мистика. Недавно тестировал вызов функций по ссылке, так скорость отличалась на порядок из-за способа, которым в массив те же самые ссылки складывал — если делал это в цикле то быстрее, а если каждый элемент индивидуально то в десять раз медленнее.

В новой версии JVM у вас может что-то работать уже иначе. И вообще непонятно зачем так "загоняться" по поводу микрооптимизаций JVM. Возможно если вы уперлись в производительность и дальше возможный выход только оптимизации такого рода, а я думаю в подавляющей массе проектов подобное не возникнет, нужно посмотреть в сторону других инструментов/языков.
p.s.
В общем спасибо за статью, то что написал не является целью её критики или утверждения что статья не нужна.)

В новой версии JVM у вас может что-то работать уже иначе.

Может. Но в девятке пока все по прежнему.

И вообще непонятно зачем так «загоняться» по поводу микрооптимизаций JVM.

Чтобы уменьшить стоимость железа? У нас, например, лоад в 10_000 рек-сек.
И вообще непонятно зачем так "загоняться" по поводу микрооптимизаций JVM.

А по мне так прекрасная информация. Думаю, разработчикам Котлина очень даже пригодится (см. новый топик).


И если писать твой кодогенератор, то тоже пригодится.


И так ясно, что эта информация не для случая, когда код руками создается.

Зная что "" + "" это синтаксический сахар от new StringBuilder().append("").append("").toString(), а так же, что потом эта конструкция оптимизируется и статические части «сшиваются» на этапе компиляции, вывод очевиден, но привести доказательства подозрений, я бы не смог. Спасибо.
UFO just landed and posted this here
В конкатенации можно сразу возвращать
return a1 + a2 + a3;
.

Я надеялся что компилятор сделает это за меня — это ведь настолько очевидная оптимизация!


Поэтому я создал два метода (по сути — добавил "оптимизированную" версию в существующий класс) чтобы это проверить:


public class Chaining {

    private String a1 = "111111111111111111111111";
    private String a2 = "222222222222222222222222";
    private String a3 = "333333333333333333333333";

    public String typicalChaining() {
        return new StringBuilder().append(a1).append(a2).append(a3).toString();
    }

    public String noChaining() {
        StringBuilder sb = new StringBuilder();
        sb.append(a1);
        sb.append(a2);
        sb.append(a3);
        return sb.toString();
    }

    public String concatenationWithExtraVar() {
        String result = a1 + a2 + a3;
        return result;
    }

    public String concatenationWithoutExtraVar() {
        return a1 + a2 + a3;
    }
}

Метод с дополнительной переменной мы уже видели:


  public java.lang.String concatenationWithExtraVar();
    Code:
       0: new           #8                  // class java/lang/StringBuilder
       3: dup
       4: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
       7: aload_0
       8: getfield      #3                  // Field a1:Ljava/lang/String;
      11: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      14: aload_0
      15: getfield      #5                  // Field a2:Ljava/lang/String;
      18: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      21: aload_0
      22: getfield      #7                  // Field a3:Ljava/lang/String;
      25: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      28: invokevirtual #11                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      31: astore_1
      32: aload_1
      33: areturn

А вот когда я увидел байткод метода без дополнительной переменной, я был несколько удивлен:


  public java.lang.String concatenationWithoutExtraVar();
    Code:
       0: new           #8                  // class java/lang/StringBuilder
       3: dup
       4: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
       7: aload_0
       8: getfield      #3                  // Field a1:Ljava/lang/String;
      11: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      14: aload_0
      15: getfield      #5                  // Field a2:Ljava/lang/String;
      18: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      21: aload_0
      22: getfield      #7                  // Field a3:Ljava/lang/String;
      25: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      28: invokevirtual #11                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      31: areturn

Отличие едва заметно — различны только последние три строки, но тем не менее, компилятор Java, похоже, не потрудился сделать это самостоятельно (по умолчанию).


Основываясь на моих небольших похождениях по StackOverflow, компилятор Java не оптимизирует (или очень незначительно оптимизирует) байткод; вместо него это делает JIT.


Поэтому я пошел дальше и сгенерировал ассемблерный выхлоп JIT. Но на его расковыривание уйдет больше времени, чем обеденный перерыв на работе =)

Замените плиз ссылку на доклад Шипилёва на эту: https://youtu.be/SZFe3m1DV1A

Тут гораздо лучше записано, и, к тому же, по-русски.
Sign up to leave a comment.

Articles