Archived

This topic is now archived and is closed to further replies.

const reference optimizations

This topic is 6363 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am still having some problems understanding how I should define functions the "fastest" way. For example, originally projection''s prototype was something like this; D3DVECTOR C3d::project(D3DVECTOR v); Then, I decided to take it out from the class; (as well matrix it needed, it''s public anyway...) (shouldn''t have that much impact, AFAIK...) D3DVECTOR project(D3DVECTOR v); Still needs too much construction? D3DVECTOR project(D3DVECTOR *v); Could const reference be faster? D3DVECTOR project(const D3DVECTOR &v); And how about not needing to return a new vector? void project(const D3DVECTOR &v, D3DVECTOR &to); Now I can think only inlining as a next step... Am I on the right track here?

Share this post


Link to post
Share on other sites
More or less on the right track:
the const reference is probably not faster than the passed pointer, however, it''s safer and more transparant to the user that way. Plus, knowing that the parameter is const might lead to some compiler optimisations.

Returning a new vector:
You might use a pointer return value, that doesn''t cost much.
If you''re going to have the target variable passed as a parameter, I would not make it a reference, but a pointer. That''s more obvious to the caller, there''ll be no mistaking that it''s a variable parameter.


Give me one more medicated peaceful moment.
~ (V)^|) |<é!t|-| ~
ERROR: Your beta-version of Life1.0 has expired. Please upgrade to the full version. All important social functions will be disabled from now on.

Share this post


Link to post
Share on other sites
Passing a pointer and reference are the same thing to the compiler. In either case, marking it ''const'' is a good idea. It can help spot errors during compile-time rather than run-time, and could potentially give the compiler opportunities to optimize.

Returning a D3DVECTOR is okay, but if it is a call you make frequently, then placing it as a destination parameter as you did works fine.

Returning a pointer could be okay, but if you''re allocating memory (using ''new'') and returning it, you have the delicate job of knowing when it is appropriate to discard that memory. Efficient and complete memory management can be a bitch, so I opt to let the compiler do that as much as possible (and I do it as little as possible).

Returning a reference is not an option, if the item to be returned is created/allocated/local to that function. It will compile, but think about it... If you return a reference to a local (on the stack) variable, as soon as the function returns, that local variable is destroyed. You now have a bad reference. The problem then becomes timing; depending on when you use it, it may look like it''s working (if it hasn''t been overwritten yet) or not. It''s entirely unpredictable and shouldn''t be used.

Returning a reference to memory alllocated with ''new'' is safer, but still a bad option. Sometime later, you''re going to have to get the address of that reference so you can ''delete'' it. And depending on how you''re keeping track of references, how will you know when and where each reference is really a reference or a hidden pointer? If you''re going to do that, you''re better simply returning a pointer. And again, that brings up the memory management issues.

---- --- -- -
Blue programmer needs food badly. Blue programmer is about to die!

Share this post


Link to post
Share on other sites
I would just like to point out that calling a function in a class (i.e. calling a method) is no more expensive than calling a ''regular'' function, unless the method is declared virtual, then there is a small performance hit when calling it (one extra indirect memory read).

A method compiles to a ''regular'' function with one additional implicit parameter, the ''this'' pointer.

If you already knew this or if optimization was not the reason for removing the method from the C3d class then please ignore me.


//Jesse

Share this post


Link to post
Share on other sites
Actually Jesse, it is a bit more time consuming to call a member function. The implict this parameter will add another push and another pop, that's for sure. Okay, no biggie but I felt I should point it out . The below code was produced in VC6, debug mode.

        
// void foo(void) {}

193:
194: void foo(void)
195: {
00401060 push ebp
00401061 mov ebp,esp
00401063 sub esp,40h
00401066 push ebx
00401067 push esi
00401068 push edi
00401069 lea edi,[ebp-40h]
0040106C mov ecx,10h
00401071 mov eax,0CCCCCCCCh
00401076 rep stos dword ptr [edi]
196: // do nothing

197: }
00401078 pop edi
00401079 pop esi
0040107A pop ebx
0040107B mov esp,ebp
0040107D pop ebp
0040107E ret

// void test::foo(void) {}

189: void test::foo(void)
190: {
00401030 push ebp
00401031 mov ebp,esp
00401033 sub esp,44h
00401036 push ebx
00401037 push esi
00401038 push edi
00401039 push ecx // this one doesn't exsist in the non-meber function

0040103A lea edi,[ebp-44h]
0040103D mov ecx,11h
00401042 mov eax,0CCCCCCCCh
00401047 rep stos dword ptr [edi]
00401049 pop ecx // this one doesn't exsist in the non-meber function

0040104A mov dword ptr [ebp-4],ecx // this one doesn't exsist in the non-meber function

191: // do nothing

192: }
0040104D pop edi
0040104E pop esi
0040104F pop ebx
00401050 mov esp,ebp
00401052 pop ebp
00401053 ret


Three more instructions! Oh my!!

"Paranoia is the belief in a hidden order behind the visible." - Anonymous

Edited by - Staffan on July 14, 2000 7:16:58 PM

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Staffan:
I thought that VC 6 passed the ''this'' pointer in a register (ecx, I believe), the ''__thiscall'' calling convention. Thus not needing an extra push/pop pair (perhaps a mov or so).
Perhaps I remember incorrectly or perhaps this is only done in an optimized build...

Ok, I see now that the push/pop you''re talking about occurrs inside the functions, I thought you meant parameter pushing.
It''s not really fair to use unoptimized code now is it?
All the code you pasted in would reduce to a single ''ret'' instruction for each function.

It is true that a small performance hit occurrs because the compiler generates one extra ''lea'' instruction before a call to a method, that does not occur before a call to a function, other than that there is no real difference (that I can see, correct me if I''m wrong).
Though I doubt that it will be noticeable, considering that the body of the ''project vector'' function probably takes proportionately much longer than the intro/extro code for the function.

//Jesse

Share this post


Link to post
Share on other sites
Yes, the __thiscall calling convention does send the implicit this parameter in ecx. Okay so thiscall may add one instruction only, no biggie. I just felt I should point it out - I''m in this kind of mood today . And if the function/method actually did something it wouldn''t turn into just a ret.

"Paranoia is the belief in a hidden order behind the visible." - Anonymous

Share this post


Link to post
Share on other sites
No, of course a real function would be compiled to more than a ''ret'', all I''m saying is that the three instructions you''re mentioning is in a bunch of junk-code that will be optimized away in a release build, I know that its not much to bother about....

Enough said, no need to argue about little things like this...

Have a nice day/night...

//Jesse

Share this post


Link to post
Share on other sites