const reference optimizations
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?
~~~ "'impossible' is a word in the dictonary of fools" --Napoleon
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.
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.
It's only funny 'till someone gets hurt.And then it's just hilarious.Unless it's you.
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!
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!
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
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
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.
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
// void foo(void) {}193:194: void foo(void)195: {00401060 push ebp00401061 mov ebp,esp00401063 sub esp,40h00401066 push ebx00401067 push esi00401068 push edi00401069 lea edi,[ebp-40h]0040106C mov ecx,10h00401071 mov eax,0CCCCCCCCh00401076 rep stos dword ptr [edi]196: // do nothing197: }00401078 pop edi00401079 pop esi0040107A pop ebx0040107B mov esp,ebp0040107D pop ebp0040107E ret// void test::foo(void) {}189: void test::foo(void)190: {00401030 push ebp00401031 mov ebp,esp00401033 sub esp,44h00401036 push ebx00401037 push esi00401038 push edi00401039 push ecx // this one doesn't exsist in the non-meber function0040103A lea edi,[ebp-44h]0040103D mov ecx,11h00401042 mov eax,0CCCCCCCCh00401047 rep stos dword ptr [edi]00401049 pop ecx // this one doesn't exsist in the non-meber function0040104A mov dword ptr [ebp-4],ecx // this one doesn't exsist in the non-meber function191: // do nothing192: }0040104D pop edi0040104E pop esi0040104F pop ebx00401050 mov esp,ebp00401052 pop ebp00401053 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
July 14, 2000 06:48 PM
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
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
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
"Paranoia is the belief in a hidden order behind the visible." - Anonymous
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
Enough said, no need to argue about little things like this...
Have a nice day/night...
//Jesse
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement