views:

390

answers:

6

Hello,

I have a public function that needs to check the validity of a few parameters, but this function is also used internally in a few others places in which I know that the given parameters will be valid. Thus, I'm wondering, which is more costly: 1) Leave the validity checks in every public function, or 2) Do the validity checks in the public functions, but create private/internal functions that do not do that checks (use the public functions as wrappers for the internal functions).

Does the overhead of the function call out-weigh the benefit of not having to perform the redundant checks?

Basically, my current code would be along the following lines:

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);
 }

Thus, bar() does checks on a, b, and c because it is an exposed/public function, but then foo repeates the same checks. Would it be more efficient to allow this to occur? or to create an internal function along the lines of the following:

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);
 }

I'm primarily concerned with the efficiency in regards to C code, but general answers/answers specific to other languages are helpful as well.

Thanks!

+1  A: 

If the checks are as you described, i would do nothing until you REALLY see it's a performance issue. This check will probably done in nano seconds, if not pico...

Drakosha
+2  A: 

When it comes to performance, unless there is measurable data demonstrating that there is a performance problem by using profiling, the emphasis should be on code that is readable and maintainable.

In this case, unless the parameter checks are really expensive, then I would think it's fine as it is. The code shows that the intent is that there should be parameter checks before performing the foo and bar functions.

If foo and bar are independent functions which are expected to be called on their own, then having the checks run multiple times probably isn't a big issue. That is of course, if the parameter checking is too costly, and it is shown by profiling that the checking is indeed taking a good portion of the time.

coobird
A: 

If you are really concerned about the speed, you can always make the public function inline. But I would really check that it is indeed a problem. Function calls are very fast in C, and unless you call the functions in tight loops, it is unlikely to be a problem.

This is very different from a language like python, where function calls are very expensive (on cPython at least) - in this case, if speed is a concern at all, you should think quite ahead about your API with this in mind.

David Cournapeau
A: 

Each function call has an overhead of: storing registers, putting parameters on the stack, whenever it has result to return it's also should be copied to return register and there probably more details I've forgot. So you need to consider to split function just because you want to avoid double parameters check only when parameters checking is very, very, very expensive. Working in C you can consider to use macros in order to increase readability.

Artem Barger
A: 

Keep the parameter checks in foo() and be happy. Remove all redundant checks before calling it. When you're done with that, you can be even happier to have refactored your code :)

Magnus Skog
+2  A: 

I usually advise using a lot of ASSERTS.I.e. in the debug mode you can check everything more is better.
Error handling in the release mode i will do only when i really can find a problem. For example i would not check buffer pointers for NULL in release mode (Null is a very small example of invalid pointer), but i would check for size of buffer if my buffer is limited.

Ilya