Проверка параметров по сравнению с издержками на вызовы функций - PullRequest
2 голосов
/ 21 июня 2009

У меня есть открытая функция, которая должна проверять правильность нескольких параметров, но эта функция также используется внутри некоторых других мест, в которых я знаю, что данные параметры будут действительными. Таким образом, мне интересно, что обходится дороже: 1) Оставьте проверки достоверности в каждой общедоступной функции, или 2) Выполните проверки достоверности в общедоступных функциях, но создайте частные / внутренние функции, которые не выполняют эту проверку (используйте публичные функции как оболочки для внутренних функций).

Слишком ли накладные расходы на вызов функции перевешивают выгоду от отсутствия необходимости выполнять избыточные проверки?

По сути, мой текущий код будет выглядеть следующим образом:

boolean foo(int* a, int* b, int* c)
{
   if (!a || !b || !c) {
       return FALSE;
   }
   <do the whatever foo does here>
}

boolean bar(int* a, int* b, int* c)
{
    if (!a || !b || !c) {
        return FALSE;
    }
    <do the whatever bar does here>
    foo(a, b, c);
 }

Таким образом, bar () проверяет a, b и c, потому что это открытая / публичная функция, но затем foo повторяет те же проверки. Будет ли эффективнее позволить этому произойти? или создать внутреннюю функцию по следующим направлениям:

static boolean foo_internal(int* a, int* b, int* c)
{
    <do the whatever foo does here>
}

boolean foo(int* a, int* b, int* c)
{
   if (!a || !b || !c) {
       return FALSE;
   }
   foo_internal();
}

boolean bar(int* a, int* b, int* c)
{
    if (!a || !b || !c) {
        return FALSE;
    }
    <do the whatever bar does here>
    foo_internal(a, b, c);
 }

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

Спасибо!

Ответы [ 6 ]

2 голосов
/ 21 июня 2009

Я обычно советую использовать много ASSERTS.I.e. в режиме отладки вы можете проверить все больше и лучше.
Обработка ошибок в режиме релиза я буду делать только тогда, когда действительно смогу найти проблему. Например, я бы не проверял указатели буфера на NULL в режиме выпуска (Null - очень маленький пример неверного указателя), но я бы проверял размер буфера, если мой буфер ограничен.

2 голосов
/ 21 июня 2009

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

В этом случае, если проверки параметров не действительно дорогие, то я думаю, что все в порядке, как есть. Код показывает, что перед выполнением функций foo и bar необходимо проверить параметры.

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

1 голос
/ 21 июня 2009

Если проверки такие же, как вы описали, я ничего не буду делать, пока вы ДЕЙСТВИТЕЛЬНО не увидите, что это проблема производительности Эта проверка, вероятно, будет выполнена за несколько секунд, если не пико ...

0 голосов
/ 21 июня 2009

Держите проверки параметров в foo () и будьте счастливы. Удалите все лишние проверки перед вызовом. Когда вы закончите с этим, вы можете быть еще более счастливы, если бы рефакторинг вашего кода:)

0 голосов
/ 21 июня 2009

У каждого вызова функции есть накладные расходы: хранение регистров, помещение параметров в стек, всякий раз, когда у него есть результат для возврата, его также следует копировать в регистр возврата, и, возможно, я забыл еще больше деталей. Таким образом, вам нужно рассмотреть функцию разделения только потому, что вы хотите избежать двойной проверки параметров, только когда проверка параметров очень, очень, очень дорогая. Работая в C, вы можете использовать макросы для повышения читабельности.

0 голосов
/ 21 июня 2009

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

Это очень отличается от языка, подобного python, где вызовы функций очень дороги (по крайней мере, на cPython) - в этом случае, если скорость вообще вызывает беспокойство, вы должны заранее подумать о своем API с учетом этого .

...