views:

288

answers:

8

I'm reading some C code like that:

double function( int lena,double xa,double ya, double za, double *acoefs, ...,
                 int lenb,double xb,double yb, double zb, double *bcoefs, ...,
                 same for c,
                 same for d )

This function is called in the code mor than 100.000 times so it's performance-critical.

I'm trying to extend this code but I want to know if it's efficient or not (and how much this influences the speed) to encapsulate all the parameters in a struct like this

struct PGTO { int len; double x,y,z ; double *acoefs }

and then access the parameters in the function.

+5  A: 

The answer to this question depends very much on the platform and its calling conventions. It also depends on wether the function could be inlined and other compiler optimizations.

I’d say, on many platforms the struct version could be more efficient, since there are fewer parameters to be copied to the stack if you are passing a pointer to the struct.

Anyway, the question cannot be answered easily. So, as with all performance considerations: Just test and profile!

Nikolai Ruhe
If you pass a pointer to the struct, you're passing by reference, not by value.
Blank Xavier
A: 

Modern compilers will most likely produce identical code in both cases. So, unless your compiler is not state-of-the-art, the only(but important) benefit you will get with structures is improved readability.

Glorphindale
No, it can't. Calling conventions require arguments to be passed on the stack. The compiler can't bend the calling conventions unless the function is declared `static`. That's typically not the case.
edgar.holleis
You're right, I forgot about that.
Glorphindale
@How is that a difference between structs and single parameters? In both cases, the parameters will be copied on the stack.
Konrad Rudolph
A: 

The best thing is to profile and test.

But, one thing, lesser parameters will be copied onto the stack when you pass a pointer to struct. Also, you function call might look more neat.

Jay
+4  A: 

First of all, using structs seems to be a right way in this exact case. The code will be much easier to read and unerstand, it will become less cluttered as well.

Passing a pointer to a struct is generally cheaper than passing lots of parameters.

Roman D
Not if you need to fill the struct every time you call the function.
lhf
Sure, but, once again, it depends on the calling code and the rest of the source :) There's a plenty of factors to consider.
Roman D
A: 

Yes, they are. I would bet a million bucks, if I had that much, that the performance difference is negligible.

Tuomas Pelkonen
A: 

Passing a struct or the argument list shouldn't make a whole lot of difference. Calling convention require both to be passed by value and to be passed via the stack (unless the function can be declared static).

You could refactor the code to enable pass-by-reference (passing a pointer to a struct). But that's probably a major redesign it will probably make your code more complicated and less readable.

edgar.holleis
Does "Calling convention" mean all calling conventions? All calling conventions you've seen? The `cdecl` calling convention?
Steve Jessop
+3  A: 

Visual c++ 2008 64 bit seems to pass the structure by having the caller allocate space for a copy of the structure on it's stack and copying the data items into it and then passing just the address of that copy into the function by value.

This simple example compiled as follows -

struct data {
   int a;
   int b;
   int c;
   char d;
   float f;
};




double f2(data d)
{
    return d.a+d.b+d.c+d.d+d.f;
}

Compiles to this -

movsx   eax, BYTE PTR [rcx+12]
add eax, DWORD PTR [rcx+8]
add eax, DWORD PTR [rcx+4]
add eax, DWORD PTR [rcx]
movd    xmm0, eax
cvtdq2ps xmm0, xmm0
addss   xmm0, DWORD PTR [rcx+16]
unpcklps xmm0, xmm0
cvtps2pd xmm0, xmm0
ret 0

So basically when you pass individual items the caller pushed them onto the stack and the function accesses them relative to the stack. When you pass a strcuture the caller copies the data items into a block of memory on the stack and then passed the address of that into the function, which accesses them relative to that.

The second way has a couple more assembly languge instructions but that it, so as far as I can tell from my tests there is no significant difference in efficiency between the two methods at all other than a few microseconds. In all my tests the compiler wanted to inline any calls anyway unless I forced it to call it via a pointer so it's possible that nothing is passed via the stack at all in your real program anyway.

In my opinion using a struct is clearer and there appear to be no significant differences in speed so go for that one :)

As always, if in doubt over performance you need to profile your exact setup

John Burton
+1  A: 

I would assume it depends on how often you have to fill the struct.

Passing a single pointer to a struct (4 bytes) will take fewer instructions than passing an int, 3 doubles, and a pointer (32 bytes), but if you have to fill the struct with those 32 bytes before doing the call, then you've lost the advantage.

At any rate, performance is always relative, so the only way to tell if it is worthwhile is to see what percentage of time is spent in passing those arguments. To do that, I just get it running and pause it randomly 10 or 20 times. Unless I catch it more than 10% of the time passing those arguments, chances are there are bigger problems that could be fixed first.

Mike Dunlavey