Jump to content

  • Log In with Google      Sign In   
  • Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.


Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


I have two functions that do the same thing. Which one is faster?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
19 replies to this topic

#1 black_darkness   Members   -  Reputation: 280

Like
0Likes
Like

Posted 02 January 2013 - 04:07 AM

I want to make my program run faster. I know pointers are quick but does using pointers in this following example increase or decrease speed?

If this is faster I plan on doing something similar with all my functions to increase the speed of my program.

 

Example 1. This is the first function returning type Entity.

 

This is the call.

</p><div>*hero = hero->hero_turning(*hero,'d',mv);</div>

 

This is the function

 

</p><div>Entity Entity::hero_turning(Entity hero, char facing1, vector<Tile> mv) {</div>
<div> </div>
<div>if (hero.is_swing_hoe == false) {</div>
<div> </div>
<div>if(hero.facing != facing1) {</div>
<div>hero.facing = facing1;</div>
<div>hero.wait_time = 0;</div>
<div>}</div>
<div> </div>
<div>else if (hero.can_pass(hero.facing,mv,hero)&& hero.wait_time > 3) {</div>
<div>hero.frame = 1;</div>
<div>hero.move_animation = true;</div>
<div>}</div>
<div>}</div>
<div>return hero;</div>
<div>}</div>

 

 

Example 2. This one uses pointers and the function is void and doesn't return anything.

 

This is the call.

hero->hero_turning(hero,'u',mv);

 

This is the function

void Entity::hero_turning(Entity * hero, char facing1, vector<Tile> mv) {
    if (hero->is_swing_hoe == false) {
                    
        if(hero->facing != facing1) {
            hero->facing = facing1;
            hero->wait_time = 0;
        }
        else if (hero->can_pass(hero->facing,mv,*hero)&& hero->wait_time > 3) {
            hero->frame = 1;
            hero->move_animation = true;
        }
    }
}



Sponsor:

#2 Zaoshi Kaba   Crossbones+   -  Reputation: 4636

Like
1Likes
Like

Posted 02 January 2013 - 04:24 AM

1st one is likely to be slower because Entity is copies. You couldn't copy vector<Tile> either, just pass reference/pointer.



#3 GeneralQuery   Crossbones+   -  Reputation: 1263

Like
1Likes
Like

Posted 02 January 2013 - 04:24 AM

Blindly making micro optimisations is not the solution. However, as you are modifying hero it doesn't make sense to pass by value then return the result a la function 1. This is less about "changing things because you want your program to run faster" and more about choosing the right tool for the right job in the first place. But back to my original point, if you are achieving sub-optimal framerates then there are almost certainly bigger fish to fry that will deliver real, tangible performance benefits. Profile first, identify bottlenecks THEN optimise.

#4 NewDisplayName   Members   -  Reputation: 359

Like
-2Likes
Like

Posted 02 January 2013 - 04:52 AM

There is a reason why second method (using pointers) is faster than the first one.

Processor doesn't have to calculate the memory offset of each member of the structure when using pointers which makes things run faster.

From personal experience, generally everyone knows why pointers are fast, but few people understand why.

But, like GeneralQuery mentioned above, optimisation is bound by many more factors and world peace is a myth.

However, for the question at hand, go ahead and use the second one.



#5 Olof Hedman   Crossbones+   -  Reputation: 2955

Like
3Likes
Like

Posted 02 January 2013 - 05:11 AM

I don't really get why you feel like you have to pass in Entity hero at all.
Smells like a design problem, my guess is that your "Entity" class tries to do way too much. (SRP violation)

That said, option one has a lot of potential problems, also problems that is not performance related, so its often not a good idea.
You certainly should not pass the vector<Tile> by value, but as a reference as mentioned.

Ignoring the design problems, in this case I would use a const Entity& for the parameter.
const references are your friend.

Edit: fixed bad formatting by broken post editor

Edited by Olof Hedman, 02 January 2013 - 05:12 AM.


#6 Trienco   Crossbones+   -  Reputation: 2224

Like
5Likes
Like

Posted 02 January 2013 - 05:17 AM

Am I the only one being very confused by the fact that passing a the Entity hero as a parameter to its own member function seems extremely weird and pointless? This basically feels less like it should be "which is faster" and more "somebody please explain the point of member functions".

 

Your member function already has access to all the members of hero, so why would you pass it at all? Take the second one, remove every last "hero->" (or replace with "this->", depending on preference) and stop passing the object as a parameter to itself.


f@dzhttp://festini.device-zero.de

#7 ifthen   Members   -  Reputation: 820

Like
6Likes
Like

Posted 02 January 2013 - 05:18 AM

Please read a book about C++. You are calling a METHOD (as opposed to function). A method belongs to an object. Therefore, you can access a pointer to object you are calling your method from using keyword 'this'. So you can write
void Entity::turning(char facing1, vector<Tile> mv) {
    if (this->is_swing_hoe == false) {
                            if(this->facing != facing1) {
            this->facing = facing1;            this->wait_time = 0;
        }
        else if (this->can_pass(this->facing,mv,this)&& this->wait_time > 3) {
            this->frame = 1;            this->move_animation = true;
        }
    }
}
and 'this' will correspond to 'hero' if you call it like
hero->turning('d',mv);
Even better, you can remove all the 'this->' from above code. Your compiler knows that in methods, if you write a name of a variable you declared in the class of the object, that is the variable to use (if you didn't write a conflicting declaration in the method, of course).

You also should not pass a std::vector variable by value (that means, not using a pointer or, preferably, a reference). Why? Because your program needs to make a new copy of that vector. That means it must manually copy all the objects (in your case, tiles) your std::vector stores.
In fact, if you think about it, what should the Entity know? It should know on which map it is and its position. If you implement the Map class (which should probably have a vector of tiles), you can use something like
void Entity::turning(char facing1) {        
//not sure what THIS code does, but it is yours, so I won't modify it (except showing the 'OOP way')
    if (is_swing_hoe == false) {
        if(facing != facing1) {
            facing = facing1;
            wait_time = 0;
        }
        //suppose that map can extract all the needed information from the entity using getters
         else if (map->can_pass(this, facing1)&& wait_time > 3) {
            frame = 1;
            move_animation = true;
        }
    }
}
Voila! The function is much more readable. As a rule of thumb, you should always think twice before starting working on a new feature. How will I represent it? Who (which class) will use it? How should I implement it? If you ask and answer all the questions that come to your mind, you will find yourself writing much cleaner (and bug-free) code.

Edited by ifthen, 02 January 2013 - 05:20 AM.


#8 black_darkness   Members   -  Reputation: 280

Like
1Likes
Like

Posted 02 January 2013 - 05:48 AM

Please read a book about C++. You are calling a METHOD (as opposed to function). A method belongs to an object. Therefore, you can access a pointer to object you are calling your method from using keyword 'this'. So you can write

 

I did read a book but I started getting confused so I started making this game so I could get some experience in order to understand the book better. This was a really helpful post thank you.



#9 black_darkness   Members   -  Reputation: 280

Like
0Likes
Like

Posted 02 January 2013 - 07:33 AM

Please read a book about C++. You are calling a METHOD (as opposed to function). A method belongs to an object. Therefore, you can access a pointer to object you are calling your method from using keyword 'this'. So you can write

void Entity::turning(char facing1, vector<Tile> mv) {
    if (this->is_swing_hoe == false) {
                            if(this->facing != facing1) {
            this->facing = facing1;            this->wait_time = 0;
        }
        else if (this->can_pass(this->facing,mv,this)&& this->wait_time > 3) {
            this->frame = 1;            this->move_animation = true;
        }
    }
}
and 'this' will correspond to 'hero' if you call it like
hero->turning('d',mv);
Even better, you can remove all the 'this->' from above code. Your compiler knows that in methods, if you write a name of a variable you declared in the class of the object, that is the variable to use (if you didn't write a conflicting declaration in the method, of course).

You also should not pass a std::vector variable by value (that means, not using a pointer or, preferably, a reference). Why? Because your program needs to make a new copy of that vector. That means it must manually copy all the objects (in your case, tiles) your std::vector stores.
In fact, if you think about it, what should the Entity know? It should know on which map it is and its position. If you implement the Map class (which should probably have a vector of tiles), you can use something like
void Entity::turning(char facing1) {        
//not sure what THIS code does, but it is yours, so I won't modify it (except showing the 'OOP way')
    if (is_swing_hoe == false) {
        if(facing != facing1) {
            facing = facing1;
            wait_time = 0;
        }
        //suppose that map can extract all the needed information from the entity using getters
         else if (map->can_pass(this, facing1)&& wait_time > 3) {
            frame = 1;
            move_animation = true;
        }
    }
}
Voila! The function is much more readable. As a rule of thumb, you should always think twice before starting working on a new feature. How will I represent it? Who (which class) will use it? How should I implement it? If you ask and answer all the questions that come to your mind, you will find yourself writing much cleaner (and bug-free) code.

 

 

Okay another question. I am implementing your suggestions but I have a problem. I do not know if it would be efficient for me to include the data type Map as a variable in Entity.



#10 Nanook   Members   -  Reputation: 505

Like
2Likes
Like

Posted 02 January 2013 - 08:02 AM

Please read a book about C++. You are calling a METHOD (as opposed to function). A method belongs to an object. Therefore, you can access a pointer to object you are calling your method from using keyword 'this'. So you can write

 

 

I did read a book but I started getting confused so I started making this game so I could get some experience in order to understand the book better. This was a really helpful post thank you.

 

If the book got you confused you probably want to write something less complex than a game ;) If its a decent intro book it should have exercises you can work with.. The book will give you answers to all these questions and a lot more and you will understand it on a much better level.



#11 larspensjo   Members   -  Reputation: 1557

Like
0Likes
Like

Posted 02 January 2013 - 08:03 AM

I do not know if it would be efficient for me to include the data type Map as a variable in Entity.
If you mean std::map, then it is most probably not efficient to use it as a copy, and a reference ('&') is more effective.

Either use "const std::map<T1,T2> &arg" if you only want to use it to look up values, or use "std::map<T1,T2> &arg" if you need to change the map.

If this map is part of the Entity class, then you should define it as a member of the Entity class instead, and you will have immediate access to it that way (no need to access it as an argument).

A word about efficiency: the standard procedure is to first make the general design, then benchmark to find the bottlenecks, and last thing to optimize. Otherwise, there is a high risk that you spend effort on optimizing things that have no real effect on the application, or even worse, create bad design.

Edited by larspensjo, 02 January 2013 - 08:05 AM.

Current project: Ephenation.
Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/

#12 swiftcoder   Senior Moderators   -  Reputation: 10409

Like
1Likes
Like

Posted 02 January 2013 - 11:09 AM

There is a reason why second method (using pointers) is faster than the first one.
Processor doesn't have to calculate the memory offset of each member of the structure when using pointers which makes things run faster.
From personal experience, generally everyone knows why pointers are fast, but few people understand why.

 

Late to the party, but no, that is not why pointers are faster.

 

The pointer version of the function is faster only because it accesses and modifies the initial object in place, whereas the non-pointer version copies the entire object twice (once when passed as a parameter by-value, and once when returned by-value).


Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]


#13 NewDisplayName   Members   -  Reputation: 359

Like
-3Likes
Like

Posted 02 January 2013 - 11:27 AM

There is a reason why second method (using pointers) is faster than the first one.
Processor doesn't have to calculate the memory offset of each member of the structure when using pointers which makes things run faster.
From personal experience, generally everyone knows why pointers are fast, but few people understand why.

 

Late to the party, but no, that is not why pointers are faster.

 

The pointer version of the function is faster only because it accesses and modifies the initial object in place, whereas the non-pointer version copies the entire object twice (once when passed as a parameter by-value, and once when returned by-value).

 

That's just another reason, and not the only reason. Two people can still be right with different facts sir, doesn't mean one needs to diss the other. cool.png



#14 swiftcoder   Senior Moderators   -  Reputation: 10409

Like
7Likes
Like

Posted 02 January 2013 - 11:49 AM

That's just another reason, and not the only reason. Two people can still be right with different facts sir, doesn't mean one needs to diss the other. 

 

While the philosopher in me applauds your application of the Heisenberg uncertainty principle, you are however blatantly incorrect in this instance.

 

Accessing a member variable in a structure requires the calculation of an offset, regardless of whether you are accessing the structure directly, or via a pointer to its location. And in both cases, this calculation will almost always be done ahead of time by the compiler, and evaluate to a simple add/offset operation at runtime.

 

If you don't believe me, try writing both versions of the function in assembly: you'll note that one accesses an object stored on the stack by loading the memory location at an offset from the stack/frame pointer. As far as the hardware is concerned, there is no distinction between a structure in your local stack frame versus referenced from elsewhere (unless the structure fits entirely in registers, or unless the load operation triggers a page fault, in either of which cases the copying version of the function will likely be faster anyway).


Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]


#15 NewDisplayName   Members   -  Reputation: 359

Like
-4Likes
Like

Posted 02 January 2013 - 11:57 AM

Even though what you're saying is highly debatable (and trust me, I have tried fiddling with pointers way too much over all these years) lets just leave it at that.

I have absolutely no intention of entering this debate, following in the footsteps of many of our esteemed predecessors.

To each his own. cheers.



#16 Alpha_ProgDes   Crossbones+   -  Reputation: 4692

Like
3Likes
Like

Posted 02 January 2013 - 01:02 PM

While the philosopher in me applauds your application of the Heisenberg uncertainty principle

 

This line. Classic. It alone deserves a +1.


Beginner in Game Development? Read here.
 
Super Mario Bros clone tutorial written in XNA 4.0 [MonoGame, ANX, and MonoXNA] by Scott Haley
 
If you have found any of the posts helpful, please show your appreciation by clicking the up arrow on those posts Posted Image
 
Spoiler

#17 ifthen   Members   -  Reputation: 820

Like
1Likes
Like

Posted 02 January 2013 - 02:28 PM

Okay another question. I am implementing your suggestions but I have a problem. I do not know if it would be efficient for me to include the data type Map as a variable in Entity.
The best way is to use a reference (it doesn't copy the data of object, but you use it in same way as an object, unlike a pointer). Making a reference a class member is a bit tricky (requires initializer lists), but this code does it:
//file Entity.h
#pragma once
//forward declaration of a map
//in C++, you can declare a class many times,
//but define it only once!
class Map;
class Entity {
  public:
    //you have to make a constructor with an initialization list
    //because the reference, unlike a pointer, must be defined at its initialization
     Entity(Map & _map) : map(_map) {
      //your constructor, blah blah blah
    }
    //note you can also use Entity(Map & map) : map(map) {...}, it has the same effect
    //(refer to footnote 1)
    void foo();
    protected:
      Map & map;
};

//file Map.h
#pragma once
#include "Entity.h"
class Map {
  void bar();
  //you can pass the current object as a parameter to a function using this
  Entity thisMapEntity() {
    return Entity(this);
  }
};

//file Entity.cpp
#include "Entity.h"
#include "Map.h"
Entity::foo() {
  //note you couldn't define foo in Entity.h,
  //because class Map wasn't defined yet,
  //just declared 

  //calls the entity's map's function "bar"
  map.bar();
}
Footnote 1

Edited by ifthen, 02 January 2013 - 02:31 PM.


#18 black_darkness   Members   -  Reputation: 280

Like
0Likes
Like

Posted 03 January 2013 - 01:32 AM

Okay another question. I am implementing your suggestions but I have a problem. I do not know if it would be efficient for me to include the data type Map as a variable in Entity.
The best way is to use a reference (it doesn't copy the data of object, but you use it in same way as an object, unlike a pointer). Making a reference a class member is a bit tricky (requires initializer lists), but this code does it:
//file Entity.h
#pragma once
//forward declaration of a map
//in C++, you can declare a class many times,
//but define it only once!
class Map;
class Entity {
  public:
    //you have to make a constructor with an initialization list
    //because the reference, unlike a pointer, must be defined at its initialization
     Entity(Map & _map) : map(_map) {
      //your constructor, blah blah blah
    }
    //note you can also use Entity(Map & map) : map(map) {...}, it has the same effect
    //(refer to footnote 1)
    void foo();
    protected:
      Map & map;
};

//file Map.h
#pragma once
#include "Entity.h"
class Map {
  void bar();
  //you can pass the current object as a parameter to a function using this
  Entity thisMapEntity() {
    return Entity(this);
  }
};

//file Entity.cpp
#include "Entity.h"
#include "Map.h"
Entity::foo() {
  //note you couldn't define foo in Entity.h,
  //because class Map wasn't defined yet,
  //just declared 

  //calls the entity's map's function "bar"
  map.bar();
}
Footnote 1

Thank you. This is good stuff.



#19 larspensjo   Members   -  Reputation: 1557

Like
2Likes
Like

Posted 03 January 2013 - 05:48 AM

Accessing a member variable in a structure requires the calculation of an offset, regardless of whether you are accessing the structure directly, or via a pointer to its location. And in both cases, this calculation will almost always be done ahead of time by the compiler, and evaluate to a simple add/offset operation at runtime.

 

In case of global parameters allocated by the linker, it should be possible to access member variables without using an offset operation at runtime. At least that is the way it was done in the C compiler I made at around 1984 for the NS32016, with a reservation for corrupt (wetware) memory.

 

When accessing members of structures allocated on the stack, however, a runtime offset operation should always be needed, to the FP or SP. So I suppose that is the normal case.


Current project: Ephenation.
Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/

#20 Khatharr   Crossbones+   -  Reputation: 3064

Like
0Likes
Like

Posted 03 January 2013 - 11:19 PM

While the philosopher in me applauds your application of the Heisenberg uncertainty principle, you are however blatantly incorrect in this instance.
And the LOL of the day award goes tooooooooooooooo....

Also, I recall from reading the 80386 manual that member offset access is optimized by use of a different addressing method in the hardware. Adding that to the cache I'd imagine that in the majority of cases the value (or call address) is already on hand when required.

Edited by Khatharr, 03 January 2013 - 11:26 PM.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS