Влияет ли порядок выражения для проверки в логическом выражении на производительность - PullRequest
2 голосов
/ 15 сентября 2010

Если у меня есть логическое выражение для проверки

(A && B)

Если A окажется ложным, потрудится ли язык проверить B?Различается ли это от языка к языку?

Причина, по которой я спрашиваю, заключается в том, что мне интересно, проверяется ли B, даже если A ложно, тогда не будет

if (A) {
  if(B) {

  } else {
     // code x
  }
} else {
  // code x
}

быть немного быстрее чем

if (A && B) {

} else {
   // code x
}

Ответы [ 6 ]

4 голосов
/ 15 сентября 2010

Это зависит от языка. Большинство языков реализуют A && B как оператор короткого замыкания, а это означает, что если A оценивается как ложное, B никогда не будет оцениваться. В Википедии есть подробный список .

1 голос
/ 15 сентября 2010

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

Во-вторых, это тот тип микрооптимизации, который вы предоставляете интерпретатору языка, JIT или компилятору.

1 голос
/ 15 сентября 2010

Это будет зависеть на 100% от того, как язык компилирует указанный код. Все что угодно возможно:)

Есть ли конкретный язык, который вас интересует?

1 голос
/ 15 сентября 2010

Почти каждый язык реализует то, что называется оценка короткого замыкания , что означает, что да, (A && B) не будет оценивать B, если A ложно. Это также вступает в силу, если вы напишите:

if (A || B) {
    ...
}

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

Как немного истории, на мой взгляд, это немного болезненная часть LISP, потому что такой код:

(if (and (= x 5) (my-expensive-query y)) "Yes" "No")

состоит не из функций, а из так называемых «специальных форм» (то есть «и здесь нельзя определить»).

1 голос
/ 15 сентября 2010

Многие языки (включая почти все языки с фигурными скобками, такие как C / C ++ / Java / C #) предлагают булево вычисление при коротком замыкании. В этих языках, если A ложно, B не будет оцениваться. Вам нужно будет узнать (или спросить), верно ли это для вашего конкретного языка, или есть ли способ сделать это (например, VB имеет AndAlso).

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

0 голосов
/ 15 сентября 2010

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

Если A и B на самом деле являются вызовами, которые имеют побочные эффекты (т.е. они не просто возвращают значение, подходящее для сравнения), то я бы сказал, что эти вызовы должны быть преобразованы в назначения переменных, которые затем используются в вашем сравнении , Не имеет значения, всегда ли вам требуются эти побочные эффекты или они требуются только условно, код будет более читабельным, если вы не будете зависеть от того, существует или нет короткое замыкание.

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

...