Есть ли разница в производительности между следующими двумя случаями? - PullRequest
1 голос
/ 29 июня 2011

есть ли разница в производительности между следующими двумя случаями:
Первое:

int test_some_condition(void);

if( some_variable == 2 && test_some_condition())
{
    //body
}

Второй:

int test_some_condition(void);

if( some_variable == 2 )
{
    if(test_some_condition())
    {
        //body
    }
}

ОБНОВЛЕНИЕ: я знаю, как создать тест и измерить производительность каждого случая или посмотреть на сборку, созданную для каждого случая, но я уверен, что я не первый, кто сталкивается с этим вопросом, и было бы здорово, если кто-то, кто уже проверил это, может быть простой ответ да / нет.

Ответы [ 6 ]

4 голосов
/ 29 июня 2011

Разница в том, что?

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

Производительность / "скорость"? Нет. Я бы поспорил на реальные деньги, что нет абсолютно никакой заметной разницы, как только вы запустите эти два фрагмента кода через компилятор с включенной оптимизацией. И это не займет много времени, чтобы убедить меня сделать ставку на тот же случай, даже если оптимизация отключена .

Почему? Потому что в C (и во всех известных мне C-производных языках) оператор && выполняет оценку короткого замыкания , что означает, что если первое условие оценивается как ложное, то оно не ' даже не стоит оценивать второе условие, потому что нет никакой возможности, чтобы все утверждение могло когда-либо оказаться верным.

Вложение операторов if было обычной уловкой «оптимизации» в старые добрые времена VB 6, когда оператор And не выполнял оценку короткого замыкания. Нет смысла использовать его в C-коде, если только он не улучшает читаемость. И если честно, если вы столкнетесь с компилятором, который не делает эти два фрагмента кода полностью эквивалентными с точки зрения производительности, то пришло время выбросить этот компилятор и прекратить его использование. Это самая базовая оптимизация под солнцем, «низко висящий фрукт» для авторов компиляторов. Если они не могут понять это правильно, я бы не стал доверять им остальную часть вашего кода.

Но, в общем, беспокойство по поводу такого рода вещей (которые определенно подпадают под категорию «микрооптимизации») не помогает вам писать лучший код или стать лучшим программистом. Это просто заставляет вас тратить много времени, задавая вопросы о переполнении стека, и способствует репутации таких пользователей, как я, которые публикуют один и тот же ответ на 2 - 3 похожих вопроса в неделю. И это время, когда вы не тратите написание кода и улучшаете свои навыки ощутимыми способами.

2 голосов
/ 29 июня 2011

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

2 голосов
/ 29 июня 2011

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

1 голос
/ 29 июня 2011

Тестирование этих двух примеров в цикле, выполняемом 10.000.000 раз, дает:

$ time ./test1

real    0m0.045s
user    0m0.044s
sys     0m0.001s

$ time ./test2

real    0m0.045s
user    0m0.043s
sys     0m0.003s

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

Кроме того, в условиях, когда первое вычисленное выражение возвращает false:

$ time ./test1_1

real    0m0.035s
user    0m0.034s
sys     0m0.001s
$ time ./test2_1

real    0m0.035s
user    0m0.034s
sys     0m0.000s
0 голосов
/ 29 июня 2011

Два образца логически эквивалентны, при условии, что составные условия лениво оцениваются, что означает, что в a && b, b не будет оцениваться, когда известно, что a ложно.Поэтому, даже если бы была разница, мне было бы все равно, потому что это мог быть артефакт (или ошибка) компилятора, который вы используете, и он может измениться в следующем выпуске или исправлении ошибки.

0 голосов
/ 29 июня 2011

Если вы думаете, всегда ли первая версия вызывает test_some_condition, но вторая версия вызывает его, только если первое условие истинно, то ответ таков: обе версии эквивалентны, поскольку оператор AND ленив, а не оцените свой второй аргумент, если первый уже ложный.

Стандарт гарантирует такое поведение.Это делает законным сказать:

if (array_size > n && my_array[n] == 1) { ... }

Это будет неработающий код без гарантии лени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...