Skip to main content
gamedev.net
🔒 Locked

Function Pointers in Classes - the cost

Started by Prozak 4 replies 400+ views
Original Post
Prozak
Prozak
Hi, because I want extensibility in my engine, sometimes i use function pointers, and some times i group them in a class. I dont use virtual classes cause in my opinion they''re overkill for what im doing, although, as allways, i see things as tools to be used where they make the job easier... Now, my main question is: Could function pointers, and function pointers in classes, if used "too" extensively (and i leave that a bit open to interpretation), be too "expensive" (in terms of optimization, speed, whatever) in a 3D engine, under the intel & clones platform? ...Or are function pointers too... how do i put it... in-grained into the x86 opcode architecture, that makes them cheap? Im open to suggestions and optimization tricks, even, and maybe especially, at the asm-level... with all that branch-predicting stuff that goes on in modern day processors (i stoepd programming asm in the 486)... Thanks for the inputs... Salsa cooked it, your eyes eat it!
[Hugo Ferreira][Positronic Dreams][Colibri 3D Engine][Entropy HL2 MOD][My DevDiary]
[Yann L.][Enginuity] [Penny Arcade] [MSDN][VS RoadMap][Humus][BSPs][UGP][NeHe]
"our stupidity allways comes back to bite us in the ass... in a white-shark sort of way..." - Prozak
antareus
antareus
As with everything, it depends, and the only way you can really get meaningful results is to profile it. Now, specific advice that comes to mind is that basic function pointers can thwart inlining...however, functors supposedly have a much better chance of being inlined. You could write an engine with all function pointers, just like you could write an engine without function pointers. Personally I can't even see where you'd want to use function pointers in an engine. I use them when you want user-code to be hooked into the engine at certain points. I don't think its entirely worth it to bend over backwards with a super-flexible engine if the engine isn't likely to be reused anyway.

However, for hobbyist projects, IMO you'd have to try to use them more than you think you should to even hit their limits. Most hobby projects never get completed. Use what you think will help you move towards completion and doesn't sacrifice too much performance.

As for the function pointers, it is dereferenced before it is called. Instead of the pointer containing an address of data to be manipulated, it is merely an address to jump to. X86 really has no notion of function pointers, just like it has no notion of datatypes it is storing.

[edited by - antareus on April 30, 2004 11:09:45 PM]
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
Prozak
Prozak
I use them in several key systems of the engine. My engine, Colibri, was designed from bottom up to be altered/enhanced from the outside, via scripts or plugins.

I use function pointers (FPs) in:
- Shader system (shaders can be registered from the outside. engine calls the active shader system via function pointers)

- Dinamic CodePath - engine looks at hardware capabilities and user selections, and defines the most apropriate codepath. (i really believe that FPs really speed up the engine in this section. here, you could have a single static functions, with lots of if.then.elses for each hardware profile, which, if performed per-frame would be more expensive than a single function pointer call per-frame)

- Decompression & Encryption (also FPs. there are template calls like: decompress(mem_location, mem_location, *parameters), but having it as a function pointer means that the compressor/encryptor can be changed in real-time, and even externally.

- Resource Loading (I use FPs here too. The user can register a function, let me give an example:
Register("res_load_3ds", "res_load", "3ds", res_load_3ds);

The function "res_load_3ds", which is used to load resources of type "mesh" from "3ds" files, was registered:
Name: res_load_3ds - just a string for id purposes
Type: res_load - this one loads resources (there is also res_save and other types)
Target: 3ds - files with this extension will be handled by this function.
Pointer: res_load_3ds - the actual function''s address.

This means that i can ship my Q3 map viewer, and other people can write importers for other types of maps, like Unreal or Quake2, or even quake4... from a plugin... and once the unreal level is required to be loaded, an apropriate handler function will be searched, and called...

I could go on about the easiness and flexibility that function pointers gives us (me)...

quote:
Most hobby projects never get completed.


Happy to not be in that group. IMO an engine is never complete...

Salsa cooked it, your eyes eat it!
[Hugo Ferreira][Positronic Dreams][Colibri 3D Engine][Entropy HL2 MOD][My DevDiary]
[Yann L.][Enginuity] [Penny Arcade] [MSDN][VS RoadMap][Humus][BSPs][UGP][NeHe]
"our stupidity allways comes back to bite us in the ass... in a white-shark sort of way..." - Prozak
snk_kid
snk_kid
using C++?, considered using functors before? i find its very powerful concept. An example of one that comes from my libaray of routines. Its a linear interloper, perfectly matches a functor's description from my point of view, it's generic can interlop any type that supports the "-, + *" operators:


#include <functional>

template< class arg, class result > class lerp : std::unary_function< arg, result > {
public:
lerp(const result&, const result&);
result operator()(const arg&) const;
private:
const result& _r1, _r2;
};

template< class arg, class result >
inline lerp< arg, result >::lerp(const result& r1, const result& r2): _r2(r2), _r1(r1) {}


template< class arg, class result >
inline result lerp< arg, result >::operator()(const arg& t) const {
return result(((1 - t) * _r1) + (t * _r2));
}


[edited by - snk_kid on May 1, 2004 2:12:30 PM]
Deebo
Deebo
A function pointer is simply just a pointer in your class (no different from using void* or char*) that contain the address of the function you have assigned it. Other than 4 bytes (assuming you are compiling in the "standard" 32-bit) there are no performance losses. But you will have to assign them valid address of functions you want to use before they can ever used.

BTW, do you mean pointers to functions within the class, or pointers to member functions within the class?
They are basically the same thing except for how you declare them.

Intro Engine
Miserable
Miserable
quote:
Original post by Deebo
A function pointer is simply just a pointer in your class (no different from using void* or char*) that contain the address of the function you have assigned it. Other than 4 bytes (assuming you are compiling in the "standard" 32-bit) there are no performance losses. But you will have to assign them valid address of functions you want to use before they can ever used.

There''s also the potential speed hit of dereferencing that extra pointer, as well as the fact that function inlining becomes impossible.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.