| 1 | = C++ Performance Tweaking Tips = |
| 2 | |
| 3 | == Inline Functions == |
| 4 | Function declared as inline will be included in the calling code in compilation time. This speeds up execution because all the branching stuff hasn't to be executed. The speedup will be the bettest, when these functions are only very small, so when the execution of the function needs aproximatly the same time as the branching time. Here a little example: |
| 5 | {{{ |
| 6 | class Test |
| 7 | { |
| 8 | public: |
| 9 | int getSize(); |
| 10 | private: |
| 11 | int size; |
| 12 | }; |
| 13 | |
| 14 | inline int Test:getSize() |
| 15 | { |
| 16 | return this->size; |
| 17 | } |
| 18 | }}} |
| 19 | This function will be executed aproximatly 10 times faster on a Pentium II based processor. |
| 20 | '''BUT''' |
| 21 | Don't write everywhere inline functions: use it only for time critical stuff, so said functions, that are executed very often during the game-time of orxonox like: |
| 22 | * ''void !WorldEntity::tick(float time) {}'' this function is called everytime a frame is rendered |
| 23 | * ''bool !BaseObject::isFinalized()'' this function is called from the garbage collector every time he does its job |
| 24 | Don't use it for functions that are normaly called before and after the game time. Or functions that are rarely called at all. |
| 25 | |
| 26 | |
| 27 | == Memory Allocation and Deletion: new, delete == |
| 28 | Creation of new Objects needs very much time compared to mathematical operations. It can take you 20 to 200 times the time a normal function call coasts, depending of how much the class has been derived, etc (measured on a pentium II computer). So try to make as few new objects you can and recycle them if possible (altough it can lead to strang code).[br] |
| 29 | Given the case, you have to create a new object, try to make it like this: |
| 30 | {{{ |
| 31 | |
| 32 | void ExampleClass::goodStyle() |
| 33 | { |
| 34 | Object* obj = new Object(); |
| 35 | obj->doSomeStuf(); |
| 36 | delete obj; |
| 37 | } |
| 38 | }}} |
| 39 | To free the memory is very important, if the function is called multiple times! [br] |
| 40 | If you write it in the follwing way, you don't have to delete it: |
| 41 | {{{ |
| 42 | void ExampleClass::goodStyle2() |
| 43 | { |
| 44 | Object obj; |
| 45 | obj.doSomeMoreStuf(); |
| 46 | } |
| 47 | }}} |
| 48 | The difference is, that this ''obj'' will be stored as a temporary variable and deleted after the function returns! This leads to some other problems: If you want to give a reference to object via the argument of a function to another object, '''never''' use these temporary variables. |
| 49 | {{{ |
| 50 | void SomeClass::wantsObjectReference(Object* reference) |
| 51 | { |
| 52 | /* do something with the reference */ |
| 53 | } |
| 54 | |
| 55 | void ExampleClass::badBadBad() |
| 56 | { |
| 57 | Object obj; /* this is only a local reference! automaticly deleted after function return */ |
| 58 | SomeClass* sc = new SomeClass(); /* creation of a new object needs much time, avoid it if possible - here we need it */ |
| 59 | sc->wantObjectReference(&obj); /* BAD BAD BAD BAD!!!!! */ |
| 60 | delete sc; |
| 61 | } |
| 62 | }}} |
| 63 | The compile will complain about such things with a message like this: "WARNING: taking address of a temprary". And Mr.Compiler is absolutly right! |
| 64 | Better would be: |
| 65 | {{{ |
| 66 | void SomeClass::wantsObjectReference(Object* reference) |
| 67 | { |
| 68 | /* do something with the reference */ |
| 69 | } |
| 70 | |
| 71 | void ExampleClass::badBadBad() |
| 72 | { |
| 73 | Object* obj = new Object*(); /* this is only a local reference! automaticly deleted after function return */ |
| 74 | SomeClass* sc = new SomeClass(); /* creation of a new object needs much time, avoid it if possible - here we need it */ |
| 75 | sc->wantObjectReference(obj); /* BAD BAD BAD BAD!!!!! */ |
| 76 | delete sc; |
| 77 | } |
| 78 | }}} |
| 79 | |