Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changes between Version 8 and Version 9 of code/PerformanceTips


Ignore:
Timestamp:
Sep 20, 2008, 5:08:50 PM (16 years ago)
Author:
landauf
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • code/PerformanceTips

    v8 v9  
    33
    44== General Idea ==
    5 It doesn't make sense to tweak every program code. Sometimes they are executed in time-uncritical sections of the program or they are executed only a few times. In these cases its nice to do some performance tweaking but it doesn't slow down the program to much if you don't. '''The more a certain part of code is executed, the more you will want to tweak it!'''
     5It doesn't make sense to tweak every program code. Sometimes they are executed in time-uncritical sections of the program or they are executed only a few times. In these cases its nice to do some performance tweaking but it doesn't slow down the program to much if you don't. '''The more a certain part of code is executed, the more you will want to tweak it'''!
    66
    77== Inline Functions ==
     
    2727Don't use it for functions that are normally called before and after the game time or functions that are rarely called at all.
    2828Inlining brings some problems, too. First: Inlined code doesn't have to be made inline by the compiler. Some reasons, why this could happen are: loops in the inlined code, recursive code in the inlined code and function calls in the inlined code. Private functions are inlined automaticaly.
    29  
     29
     30== const and const& ==
     31Given the following example:
     32{{{
     33class MyClass
     34{
     35    public:
     36        void setPosition(Vector3 position) { this->myPosition_ = position; }
     37        Vector3 getPosition() { return this->myPosition_; }
     38    private:
     39        Vector3 myPosition_;
     40};
     41}}}
     42And you execute the following code:
     43{{{
     44    MyClass obj1, obj2;
     45    Vector3 pos(10, 20, 30);
     46
     47    obj1->setPosition(pos);
     48    obj2->setPosition(obj1->getPosition());
     49}}}
     50In this example, a lot of overhead is executed, because Vector3 pos is not only created once, but in fact 4 times. The red parts of the code create a new instance of Vector3:
     51{{{
     52#!html
     53<pre class="wiki">
     54    void setPosition(<span style="color:#FF0000;">Vector3 position</span>) { this->myPosition_ = position; }
     55    <span style="color:#FF0000;">Vector3</span> getPosition() { return this->myPosition_; }
     56</pre>
     57}}}
     58By calling 2 times setPosition and once getPosition, we create 3 additional instances of Vector3. This overhead can be reduced by using constant references:
     59{{{
     60#!html
     61<pre class="wiki">
     62    void setPosition(<span style="color:#00AA00;">const Vector3& position</span>) { this->myPosition_ = position; }
     63    <span style="color:#00AA00;">const Vector3&</span> getPosition() { return this->myPosition_; }
     64</pre>
     65}}}
     66The rest of the code remains the same.
     67
     68Now you may think of a situation, where OtherClass has a MyClass as a membervalue:
     69{{{
     70class OtherClass
     71{
     72    public:
     73        void setObject(const MyClass& object) { this->object_ = object; }
     74        const MyClass& getObject() { return this->object_; }
     75
     76    private:
     77        MyClass object_;
     78};
     79}}}
     80And you want to execute the following code:
     81{{{
     82OtherClass instance;
     83Vector3 position = instance.getObject().getPosition();
     84}}}
     85But this doesn't work. Why? Because OtherClass returns a '''const''' reference to MyClass. This means, you can't change anything in MyClass. But getPosition() doesn't change anything? You're absolutely right, but the compiler doesn't know about that. You have to tell him by adding the const keyword to the function head as well:
     86{{{
     87#!html
     88<pre class="wiki">
     89        const Vector3& getPosition() <span style="color:#00AA00;">const</span> { return this->myPosition_; }
     90</pre>
     91}}}
     92And we better do the same for OtherClass::getObject as well:
     93{{{
     94#!html
     95<pre class="wiki">
     96        const MyClass& getObject() <span style="color:#00AA00;">const</span> { return this->object_; }
     97</pre>
     98}}}
     99Now the code from above will compile without problem.
     100
     101So please remember the following rules:
     102 * Alway use '''const&''' if you got an existing instance of the object you want to pass
     103 * Only create a new instance in a return value if you return a temporary object
     104 * Add '''const''' to all functions that don't change the class.
     105
     106And remember: '''const ObjectName&''' might look scary, but it's your friend. ;)
     107
    30108== Memory Allocation and Deletion: new, delete ==
    31 Creation of new objects needs very much time compared to mathematical operations. It can take from 20 to 200 times the time a normal function call costs depending of how deeply the class has been derived (measured on a pentium II computer). Try to make as few new objects you can and recycle them if possible (altough it can lead to strange code).[br]
     109Creation of new objects needs very much time compared to mathematical operations. It can take from 20 to 200 times the time a normal function call costs depending of how deeply the class has been derived (measured on a pentium II computer). Try to make as few new objects you can and recycle them if possible (altough it can lead to strange code).[[br]]
    32110Given the case, that you have to create a new object, try to make it like this:
    33111{{{
     
    40118}
    41119}}}
    42 To free the memory is very important, if the function is called multiple times! But know, that deleting uses much time again. So if there is a possibliliy of reusing the old function. In time critical parts of the code (like in-game) you can think about creating the objects in initialisation time and delete them after the time-critical part.[br]
     120To free the memory is very important, if the function is called multiple times! But know, that deleting uses much time again. So if there is a possibliliy of reusing the old function. In time critical parts of the code (like in-game) you can think about creating the objects in initialisation time and delete them after the time-critical part.[[br]]
    43121If you write it the following way, you don't have to delete it:
    44122{{{
     
    53131void SomeClass::wantsObjectReference(Object* reference)
    54132{
    55   /* do something with the reference */
    56 }
    57 
    58 void ExampleClass::badBadBad()
     133    myReference_ = reference; // Store the reference for later usage
     134}
     135
     136void ExampleClass::badBadBad(SomeClass* sc)
    59137{
    60138  Object obj;                      /* this is only a local reference automatically deleted after function return */
    61   SomeClass* sc = new SomeClass(); /* creation of a new object needs much time, avoid it if possible - here we need it */
    62139  sc->wantObjectReference(&obj);   /* BAD BAD BAD BAD!!!!! */
    63   delete sc;
    64140}
    65141}}}
     
    69145void SomeClass::wantsObjectReference(Object* reference)
    70146{
    71   /* do something with the reference */
     147    myReference_ = reference; // Store the reference for later usage
    72148}
    73149
    74150void ExampleClass::badBadBad()
    75151{
    76   Object* obj = new Object*();     /* this is only a local reference! automatically deleted after function return */
    77   SomeClass* sc = new SomeClass(); /* creation of a new object needs much time, avoid it if possible - here we need it */
    78   sc->wantObjectReference(obj);   
    79   delete sc;                       /* remember that creating and deleting object need VERY much time*/
    80 }
    81 }}}
     152  Object* obj = new Object*();     /* now the object is created with 'new' and won't be deleted after function return */
     153  sc->wantObjectReference(obj);
     154}
     155}}}
     156Of course SomeClass must now delete the object reference if it isn't needed anymore.
    82157 
    83158== Redundant code ==
     
    94169}
    95170}}}
    96 Now what's wrong here is the local variable. When the temporary object is made on the first line, the constructor is called and the object initialized. But we didn't want that to happen! We assign new values anyways in the next lines. Always keep in mind the time wasted when creating objects. [br]
    97 The copy constructor is called again in the end of the function, as returnVector is a local variable. This just shows why this style is very bad. [br]
    98 A problem which lies hidden is the problem of parameter. As the parameter is a copy of the original argument, we get another useless object construction. [br]
     171Now what's wrong here is the local variable. When the temporary object is made on the first line, the constructor is called and the object initialized. But we didn't want that to happen! We assign new values anyways in the next lines. Always keep in mind the time wasted when creating objects. [[br]]
     172The copy constructor is called again in the end of the function, as returnVector is a local variable. This just shows why this style is very bad. [[br]]
     173A problem which lies hidden is the problem of parameter. As the parameter is a copy of the original argument, we get another useless object construction. [[br]]
    99174A better way would be:
    100175{{{
     
    114189}
    115190}}}
    116 you're wasting much time in the loop dereferencing.[br]
     191you're wasting much time in the loop dereferencing.[[br]]
    117192Instead you could do this:
    118193{{{