‘…! = Null’ или ‘null! = …’ лучшая производительность?

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

public class Test1 { private String value; public void notNull(){ if( value != null) { //do something } } public void nullNot(){ if( null != value) { //do something } } } 

и проверил его байтовый код после компиляции

 public void notNull(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: getfield #2; //Field value:Ljava/lang/String; 4: ifnull 7 7: return LineNumberTable: line 6: 0 line 9: 7 StackMapTable: number_of_entries = 1 frame_type = 7 /* same */ public void nullNot(); Code: Stack=2, Locals=1, Args_size=1 0: aconst_null 1: aload_0 2: getfield #2; //Field value:Ljava/lang/String; 5: if_acmpeq 8 8: return LineNumberTable: line 12: 0 line 15: 8 StackMapTable: number_of_entries = 1 frame_type = 8 /* same */ } 

здесь два опкода используются для реализации условия if: в первом случае он использует ifnull- check top значение стека имеет значение null, а во втором случае используется if_acmpeq- check top два значения равны в стеке,

так, это повлияет на производительность? (это поможет мне доказать, что первая реализация null хороша в производительности, а также в аспекте удобочитаемости :))

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

Это не то, о чем вам нужно беспокоиться. Посмотрите на оптимизацию больших изображений.

Не оптимизируйте за счет удобочитаемости, если скорость (или память / независимо от того, что может быть) будет незначительной. Я думаю !=null как правило, более читабельна, поэтому используйте это.

С такими вопросами трудно понять, насколько умна JVM (хотя ответ «обычно довольно умный, если это возможно», и в этом случае это выглядит очень возможно). Но, чтобы быть уверенным, протестируйте его:

 class Nullcheck { public static class Fooble { } Fooble[] foo = {null , new Fooble(), null , null, new Fooble(), null, null, new Fooble() }; public int testFirst() { int sum = 0; for (int i=0 ; i<1000000000 ; i++) if (foo[i&0x7] != null) sum++; return sum; } public int testSecond() { int sum = 0; for (int i=0 ; i<1000000000 ; i++) if (null != foo[i&0x7]) sum++; return sum; } public void run() { long t0 = System.nanoTime(); int s1 = testFirst(); long t1 = System.nanoTime(); int s2 = testSecond(); long t2 = System.nanoTime(); System.out.printf("Difference=%d; %.3f vs. %.3f ns/loop (diff=%.3f)\n", s2-s1,(t1-t0)*1e-9,(t2-t1)*1e-9,(t0+t2-2*t1)*1e-9); } public static void main(String[] args) { Nullcheck me = new Nullcheck(); for (int i=0 ; i<5 ; i++) me.run(); } } 

И на моей машине это дает:

 Difference=0; 2.574 vs. 2.583 ns/loop (diff=0.008) Difference=0; 2.574 vs. 2.573 ns/loop (diff=-0.001) Difference=0; 1.584 vs. 1.582 ns/loop (diff=-0.003) Difference=0; 1.582 vs. 1.584 ns/loop (diff=0.002) Difference=0; 1.582 vs. 1.582 ns/loop (diff=0.000) 

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


Обновление : приведенный выше код запускает специальный тест. Использование JMH (теперь, когда оно существует!) - это хороший способ избежать (некоторых) ошибок микробизнеса. Приведенный выше код избегает худших ошибок, но он не дает явных оценок ошибок и игнорирует различные другие вещи, которые иногда имеют значение. В эти дни: используйте JMH! Кроме того, если вы сомневаетесь, запустите свои собственные тесты. Детали иногда имеют значение - не очень часто для чего-то столь же простого, как это, но если это действительно важно для вас, вы должны проверить состояние, близкое к производству, как вы можете управлять.

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

Обычно тело функции будет использовать только несколько переменных, и это обычно проявляется в контексте контекста, который переменная находится под контролем. Поместив константу слева, мы более точно имитируем switch и case : с учетом этой переменной выберите подходящее значение. Увидев значение слева, вы фокусируетесь на выбранном конкретном состоянии.

Когда я сканирую

 if (var == null) 

Я читал это как: «Мы проверяем var здесь, и мы сравниваем его для равенства, против … ah, null». И наоборот, когда я сканирую

 if (null == var) 

Я думаю: «Мы видим, что значение равно null, и … да, это мы проверяем var ». Это еще более

 if (null != var) 

который мой глаз сразу подхватывает.

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

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

Разница будет небрежной, поэтому переходите к тому, что наиболее читаемо ( != null Null imo)

Я бы придерживался (value! = Null) для удобочитаемости. Но вы всегда можете использовать Assertions.

Минутная оптимизация – это работа компилятора, особенно на языках высокого уровня, таких как Java.

Хотя строго это не имеет значения здесь, не оптимизируйте преждевременно!

Полагая сначала null кажется, генерирует дополнительный байт-код, но помимо этого может не быть разницы в производительности.

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

Я бы использовал метод notNull() , так что вы не бросаете ошибку компилятора, если вы забудете ! и случайно введите null = value .

О, если вы попросите максимальную производительность, не создавайте дополнительный class или методы. Даже статические методы занимают немного времени, так как загрузчик classов Java должен JIT загружать его.

Поэтому, когда вам нужно проверить, является ли переменная нулевой, вы просто проверяете ее

 if (x == null) 

или

 if (null == x) 

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

Вы можете игнорировать эту самую последнюю информацию о оптимизации во время кодирования

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

С точки зрения, нет существенной разницы в производительности.

Однако полезно сначала записать нуль, чтобы уловить ошибки опечаток.

Например, если вы привыкли писать этот код:

 if (obj == null) 

Может быть написано по ошибке:

 if (obj = null) 

С точки зрения компилятора это прекрасно.

Однако, если вы привыкли писать код как:

 if (null == obj) 

и сделал ошибку, чтобы написать:

 if (null = obj) 

компилятор сообщит вам, что вы допустили ошибку в этой строке.

В Java-8 для classа Objects были добавлены два дополнительных метода: Объекты # notNull и Objects # isNull , которые вы можете использовать для замены null проверок. Интересно, что оба из них сначала используют объекты:

 public static boolean isNull(Object obj) { return obj == null; } 

а также

 public static boolean nonNull(Object obj) { return obj != null; } 

соответственно. Я думаю, это означает, что это рекомендуемый способ (по крайней мере, разработчики ядра jdk использовали этот подход) Исходный код объектов

Я бы использовал «новую» функцию Java 8, я пишу несколько примеров:

 import java.util.Optional; public class SillyExample { public void processWithValidation(final String sampleStringParameter){ final String sampleString = Optional.ofNullable(sampleStringParameter).orElseThrow(() -> new IllegalArgumentException("String must not be null")); //Do what you want with sampleString } public void processIfPressent(final String sampleStringParameter){ Optional.ofNullable(sampleStringParameter).ifPresent(sampleString -> { //Do what you want with sampleString }); } public void processIfPressentWithFilter(final String sampleStringParameter){ Optional.ofNullable(sampleStringParameter).filter("hello"::equalsIgnoreCase).ifPresent(sampleString -> { //Do what you want with sampleString }); } 

}

Байт-код – это просто перевод исходного кода.

  • jQuery hasClass () - проверьте несколько classов
  • Самый эффективный список методов data.frame?
  • Сколько накладных расходов на интеллектуальные указатели по сравнению с обычными указателями на C ++?
  • Почему добавление «" в String сохраняет память?
  • Производительность mgo-запросов кажется медленно медленной (500-650 мс)
  • Является ли изменчивая переменная «читается» так же быстро, как обычно?
  • Установка свойства изображения UIImageView вызывает серьезное отставание
  • В .NET, какой цикл работает быстрее, «for» или «foreach»?
  • Что происходит быстрее, итерации вектора STL с помощью vector :: iterator или с at ()?
  • Ужасная производительность перерисовки DataGridView на одном из моих двух экранов
  • Является ли стандарт C ++ низкой эффективностью для iostreams, или я просто имею дело с плохой реализацией?
  • Interesting Posts
    Давайте будем гением компьютера.