Производительность Java: верно против Boolean.TRUE - PullRequest
25 голосов
/ 02 августа 2011

Что из нижеперечисленного лучше с точки зрения производительности и эффективного использования памяти?

Boolean isItTrue(arg){ 
    return Boolean.TRUE;
}

boolean isItTrue(arg){
    return Boolean.TRUE
}

Boolean isItTrue(arg){
    return true;
}

boolean isItTrue(arg){
    return true;
}

Должно быть быстрее и проще работать с примитивными типами, но, с другой стороны, при использовании ссылки настатический объект, новое значение не создается.Или он оптимизирован на уровне компилятора и все true и false заменены ссылками на статические объекты для экономии памяти?

Ответы [ 9 ]

24 голосов
/ 02 августа 2011

Во-первых, преимущество в производительности при использовании любого из них перед , скорее всего, слишком мало, чтобы быть актуальным. Простота кода / удобочитаемость / удобство сопровождения гораздо важнее ... в подавляющем большинстве случаев.


Ни один из примеров не связан с созданием Boolean экземпляров. Теоретически возможно, что 3 из 4 вызовут инициализацию класса Boolean ... и что ваше приложение иначе не сделало бы этого. В этом крайне маловероятном событии все ваше приложение выделит 2 объекта, которые иначе не были бы выделены.


Этот будет равен или быстрее, чем все остальные, потому что это просто влечет за собой установку регистра в ноль.

boolean isItTrue(arg){
    return true;
}

Взятый отдельно, он должен загружать статическую ссылку из памяти, а не обнулять регистр. Тем не менее, JIT-компилятор может быть в состоянии оптимизировать это в некоторых случаях.

Boolean isItTrue(arg){ 
    return Boolean.TRUE;
}

На первый взгляд, это включает в себя вызов Boolean.valueOf(true) для "упаковки" true, но JIT-компилятор должен иметь возможность оптимизировать его под тот же код, что и предыдущий, вставляя вызов.

Boolean isItTrue(arg){
    return true;
}

На первый взгляд, это вызов Boolean.booleanValue(Boolean.TRUE), чтобы "распаковать" Boolean. Этот звонок может быть встроен. Также возможно, что JIT-компилятор может избежать загрузки ссылки на объект Boolean и извлечения его поля значения.

boolean isItTrue(arg){
    return Boolean.TRUE
}

Суть в том, что относительная производительность 4 альтернатив зависит от того, насколько успешным будет JIT-компилятор в оптимизации. Это будет зависеть от контекста, специфики JIT-компилятора, настроек JVM и так далее. В лучшем случае JIT-компилятор может (по крайней мере, теоретически) создать одинаковый (оптимальный) код для всех них.

11 голосов
/ 02 августа 2011

Если есть какой-либо выигрыш в производительности, он настолько мал, что не имеет значения. Boolean.TRUE и Boolean.FALSE ни в коем случае не возвращают новый объект.

8 голосов
/ 02 августа 2011

Любите ясность для сопровождающего кода по таким микрооптимизациям. Вопрос не должен быть «который меньше / быстрее», во-первых, который выражает то, что вы имеете в виду.

Если метод возвращает логический объект, то всякий, кто получает, должен решить, существует ли вероятность того, что он может быть нулевым, и что, если он равен нулю, это может означать что-то отличное от true / false как "мы не знаем".

Итак, верните тип логического значения, если вы это имеете в виду, в противном случае, если вы хотите разрешить Null, тогда Boolean.

Если возвращено логическое значение, то

return true; // or false

должно быть лучше, чем полагаться на автобокс, опять же для ясности и производительности.

Если возвращается логическое значение, то

return Boolean.TRUE

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

7 голосов
/ 02 августа 2011

Они будут намного быстрее. Я не думаю, что между этими двумя будет какая-то разница.

Boolean isItTrue(arg){ 
    return Boolean.TRUE;
}

boolean isItTrue(arg){
    return true;
}

Но другая реализация будет медленнее, потому что это будет упаковка, а распаковка на серверной части займет некоторое время процессора.


Редактировать

Я собрал некоторые факты, реализовав 4 различных способа. Просто хочу поделиться этим с вами, я не знаю, если это так, как пишут.

Boolean isItTrue(){ 
    return Boolean.TRUE;
}

Free Memory before start --> 16030936
Time taken in Secs --> 7.844
Free Memory After Process --> 15940472
Memory Usage --> 90464

boolean isItTrue(){
    return Boolean.TRUE;
}

Free Memory before start --> 16030936
Time taken in Secs --> 10.109
Free Memory After Process --> 15940472
Memory Usage --> 90464

Boolean isItTrue(){
    return true;
}

Free Memory before start --> 16030936
Time taken in Secs --> 7.906
Free Memory After Process --> 15940472
Memory Usage --> 90464

boolean isItTrue(){
    return true;
}

Free Memory before start --> 16030936
Time taken in Secs --> 7.828
Free Memory After Process --> 15940472
Memory Usage --> 90464

Основной класс

public static void main(String[] args){
    NewClass n = new NewClass();

    long sysTime = System.currentTimeMillis();

    Runtime rt = Runtime.getRuntime();
    long freeMem = rt.freeMemory();
    System.out.println( "Free Memory before start --> " + freeMem );
    for( int i = 0; i < Integer.MAX_VALUE; i++ ){
        n.isItTrue();
    }
    System.out.println( "Time taken in Secs --> " + (System.currentTimeMillis() - sysTime)/1000D);
    System.out.println( "Free Memory After Process --> " + rt.freeMemory() );
    System.out.println( "Memory Usage --> " + ( freeMem - rt.freeMemory() ) );
}
3 голосов
/ 02 августа 2011

Последний

boolean isItTrue(arg){
    return true;
}

Я использую Boolean только если метод иногда должен возвращать null

2 голосов
/ 02 августа 2011

Используйте последний (просто boolean). Даже если компилятор оптимизирует их все до одного и того же, по крайней мере вы облегчаете работу компилятора (это не простая работа, вы знаете!).

Плюс это меньше нажатий клавиш (не нужно нажимать Shift). Но на самом деле единственная причина, по которой вы должны использовать класс-обертку, - это когда вам нужна возможность установить его на null и для использования в общих структурах данных, таких как LinkedList<E>.

2 голосов
/ 02 августа 2011

По этой логике ссылка на сам статический объект так же затратна, как и значение истинности, если не больше.

Использование объектов может быть несколько медленнее, чем примитивы, но я бы не стал беспокоиться: разница не имеет значения.

1 голос
/ 02 августа 2011

Мои эмпирические правила таковы:

  1. По умолчанию выбран тип примитива (boolean).
  2. Если мне нужна обнуляемость или нужно хранить значения в контейнере, я использую класс (Boolean).

Имея это в виду, мой выбор по умолчанию будет:

boolean isItTrue(arg){
    return true;
}

Что касается производительности, то единственное, что кажется очевидным, это то, что трудно представить сценарий, в котором использование Boolean было бы на быстрее , чем использование boolean. Будет ли это медленнее или то же самое, зависит от многих вещей, и вообще невозможно ответить.

Если вы действительно заботитесь об этом, профилируйте код, где это важно!

0 голосов
/ 02 августа 2011

java.lang.Boolean занимает 16 байтов.

. Этот путь подходит, если вам нужны только проблемы с производительностью и размером памяти:

boolean isItTrue(arg){
    return true;
}
...