PDA

View Full Version : C++ questions


Branks
01-12-2005, 01:11 PM
hey, ive been breaking the emu source code again with the goal of some of it atleast being useable for everyone, currently im attempting to make the AA system a bit more flexable and swarm pets as well, my real goal is to master the language though by indirectly learning from whats in the source. since i know eq, i can see the goal of it and learn from seeing how its accomplished, however theres a lot of "why's" i cant understand so rather than searching the net and finding contradicting opinions on a lot of things im just going to ask here so anyone more experienced can comment or explain.

complier optimization with loop unrolling, ive read its best to try always useing variables which remain the same each function call in order for the compiler to be able to unroll the loop, however it seems this isnt often considered and i was curious if anyone knows if the reward of doing this is actually worth the little extra effort.

accessing multi dimensional arrays, ive heard this is slow enough to be avoided when its possible, however some situations such as Mob::SpellEffect which various cases within, will need to access the array which holds AA spell IDs and recourses of AA spell Ids, would it be better to store these commonly checked spell IDs in global variables? instead of accessing the array each pass?

on the note of the spell IDs above, if i were to declare a static integer to retrieve the spell ID from the array, to prevent it from being accessed every pass, since SpellEffect() is a method of the mob class would these static intergers be created for every instance of Mob() or would it be file scope of sorts? im pretty sure the answer is they would be created for every instance however lack of experience makes me curious and im unsure of any method in order to test this.

Global pointers which are later newed, are these deleted during shutdown?

Inline and virtual functions, i believe there is a bit of extra work thats done when calling a virtual function since it needs to check the scope of the function, so... well the situation is, i was considering removing GetAA() which is virtual, entirely from Mob() scope in order to inline it in Client(), would this be desireable at the cost of a 5 or so checks to IsClient()/CastToClient() in mob scope where AA Checks are required?

Limiting functions/methods, odd one but where do most of you draw the line on creating new ones, such as would you consider 2 large switches to be justifiable for the overhead of a function call? or where exatly is the commonly considered "ok" line between inline-able and a needed function/method when avoidable?

functions pointers, do they double the overhead for function calls, in that is it actually 2 functions which are called when used in case of a method? not sure i worded that one correctly so basicly im curious if they should be avoided, currently my method of handling the special attacks etc of some swarm pets was to create a method which the AI Loop calls, which calls a function pointer which is set during pet creation, would a switch be more desirable instead?

anyway, i know some of this is probably avaliable around the net however as mentioned theres a lot of conflicting opinions/information around so i assumed id ask the people whom may be useing any progress i eventually make, and i assume these are pretty common questions most people in my position may have so, cant hurt to have it here i guess, anyway thanks for your time.

Yodason
01-13-2005, 02:46 AM
I normally don't bother posting to these boards, but this is a interesting topic I like talking about. =) The real key is that you shouldn't be trying to optimize little syntaxtical things. Thats what the compiler is good for. Don't go through a ton of extra effort trying to optimize UNLESS you've already run a profiller such as vtune or what not. Chances are what you are trying to optimize is really negligable. Virtual points for example are a single pointer lookup. Granted, thats not something you want in a vector3 class or what not, but in a mob class its perfectly fine and will not effect performance at all. I don't see why a multidimensional array would have a high perforamncee penalty, but if it does just put it into a 1d array and offset by the col length. Inline is highly desirable, but remember its just a suggestion, the compiler doesn't nessesarily follow it. It does help some things (like vector classes. get variable functions, etc) but by and large if your doing stuff with loops or if statements, there isn't going to be a performance gain worth rewriting for even if the compiler does inline it. Feel free to use function pointers, I doubt what you are doing will have any effect and may even slow things down by not using them. THE BEST place to optimize is algorithms : I remember I once killed aoe lag disconnect here by just moving a single check for valid target before a huge switch loop. THATS where you make gains, not these little tweaks. I HIGHLY recommend getting a profiler like intel vtune before you do ANY optimizing at this level. I guarentee that there are much "sweeter" spots to optimize in eqemu then worrying about the performance of one pointer lookup (which is all a virtual function is. Its virtually (pardon the pun) free for 99.9% of cases). I hope this answered your question.

Branks
01-13-2005, 01:23 PM
i understand these questions are rather rediculous and petty but in my opinion its something that should be in the back of your mind at all times, so thats why i ask, and i know a profiler is the only real answer to some of them and that the answer varries between different machines.

im not really trying to optimize little syntaxtical things, its that no matter what compiler your using there are situations syntax prevents the compiler from being able to do any optimization, and thats parts of what im unsure of, i know inline is only a suggestion however ive also read its almost 100% impossible for a compiler to inline a virtual function, and a compiler cannot unroll a variable loop, so i was hoping we maybe had a hardcore assembly guru around who could say " i found loop setup time to be slower than 100 conditional checks", so i could keep that in mind and simply let a loop go 100 passes when it would sometimes only need 50, so that the compiler could unroll it.

in the case of GetAA() its called often enough i think inlining it would to benificial in any case since theres maybe 4 times ive found its called within Mob() scope.

the functions pointer thing, i know when calling functions it has to throw all currently used variables temporarily to the stack, or wherever it saves them so i was curious if function pointers made it do this as well, since thats a small but also needless thing to have 3 copies or so of variables around and i would know to prevent having a lot of arguements/parameters when using function pointers.

anyway, ill check into this vtune thing, never heard of it before, and thanks for the advice, im just trying to establish the commonly know performance mistakes, not trying to optimize really but these small things add up quickly.

also, the question about static variables declared within a class method, are these created for every instance of a class or does every instance of a class use the same method and therefor the static variables only exsist once?

animepimp
01-13-2005, 05:35 PM
accessing multi dimensional arrays, ive heard this is slow enough to be avoided when its possible, however some situations such as Mob::SpellEffect which various cases within, will need to access the array which holds AA spell IDs and recourses of AA spell Ids, would it be better to store these commonly checked spell IDs in global variables? instead of accessing the array each pass?

This has no overhead at all in C or C++. It may in Java or other languages, but in C the entire multidimensional array is stored linearly in one block of memory with each row immediately after the previous row. He said you could store it as a single dimensional array and refer to it with [column +(row*num_columns)] and you can if you want, but that is exactly what the program does when you put [row][column]. You can even declare it as two dimension and type cast it to one dimension and refer to it interchangably. So the only over head is a pointer look up and an addition and multiplication, if you worry over that then you should see a shrink.

also, the question about static variables declared within a class method, are these created for every instance of a class or does every instance of a class use the same method and therefor the static variables only exsist once?

I don't think you can declare a static variable inside a method, and even if you can it will do absolutely nothing because variables declared in a method cease to exist once the method stops running. Of course if you have two instances of the method running at the same time it may make them share the variables, but I have no idea.

Yodason
01-14-2005, 01:47 AM
This has no overhead at all in C or C++. It may in Java or other languages, but in C the entire multidimensional array is stored linearly in one block of memory with each row immediately after the previous row. He said you could store it as a single dimensional array and refer to it with [column +(row*num_columns)] and you can if you want, but that is exactly what the program does when you put [row][column]. You can even declare it as two dimension and type cast it to one dimension and refer to it interchangably. So the only over head is a pointer look up and an addition and multiplication, if you worry over that then you should see a shrink.
exactly.

I don't think you can declare a static variable inside a method, and even if you can it will do absolutely nothing because variables declared in a method cease to exist once the method stops running. Of course if you have two instances of the method running at the same time it may make them share the variables, but I have no idea. [Quote] Normally, variables defined local to a function disappear at the end of the function scope. When you call the function again, storage for the variables is created anew and the values are re-initialized. If you want a value to be extant throughout the life of a program, you can define a function