Closed TodorBalabanov closed 11 years ago
No method calls (esp math.pow) means faster code. Slightly harder to read IMHO, but much faster.
Btw, dealing with floats, I believe we should multiply by 0.1 rather than divide by 10.
Did you do some measurements using the game to show that these changes have a big impact on the game performance?
The impact is not so big, but it it has some improvement. Sure, I did some measurements, you can try it yourself: https://drive.google.com/file/d/0Bz5a6NKy7qNiZzM3QTNweFV5MTA/edit?usp=sharing
Floating point calculations are slower than integer. That is why it is better to divide by integer 10 than to multiply by floating 0.1f.
Thanks, so what are the measurements? I'm interested in hearing what the impact on the actual game is.
In 100 000 000 experiments for calculateUseCost(), on my computer, time usage is:
With Math.pow ->3653 ms Whithout Math.pow -> 138 ms
Math.pow can be pretty slow because of its implementation (usage of Taylor series):
"Yes, there are software algorithms for calculating sin too. Basically, calculating these kind of stuff with a digital computer is usually done using numerical methods like approximating the Taylor series representing the function.
Numerical methods can approximate functions to an arbitrary amount of accuracy and since the amount of accuracy you have in a floating number is finite, they suit these tasks pretty well." http://stackoverflow.com/questions/2284860/how-does-c-compute-sin-and-other-math-functions
That is why it is better to use multiplication when you are doing power of 2.
If you are able to replays most of the floating point calculations with integer calculations you will speed the whole game. It takes a lot of efforts to rewrite all formulas, but it can be useful.
See the original code of calculateUseCost():
Math.pow(Math.abs(averageHPBoost), 2)
First you are doing ABS and after that you are doing POW 2. If you miss ABS the result will be the same. You have extra calculation which is not needed. It takes CPU time even if it is small amount of CPU time.
Thanks for the measurements. Given your measurements, each calculateUseCost()
would take 36.53 nanoseconds using Math.pow()
, and 1.38 nanoseconds without Math.pow()
.
So for Andor's Trail, we currently have 53 items that have a use effect. This means that the time for running all those calculations would go from 53_36.53 = 1936 nanoseconds to 53_1.38 = 73 nanoseconds. That's a difference of 1863 nanoseconds (about 2 microseconds).
Do you think that making the game start about a millionth of a second faster justifies making the code slightly harder to read?
I do not know. It is only suggestion. Formula explanation can be written as comment. Mobile resources are limited it is wise to use them carefully.
While I agree it is not a HUGE improvement technically speaking, especially in a function executed only once at load-time, I think this is the kind of change that, if carried throughout the whole game code, could make AT roughly 10% faster (empiric estimation, but this kind of optimization on unoptimized code generally falls in that ballpark).
@TodorBalabanov : I really like your coding style, although not as much on this specific line. A comment would be nice indeed, but maybe having slightly less optimized but more readable code could be a nice trade-off (not factorizing the '30' part for example). Are you on your way to refactor all the AT code with your optimize-fu ?
@Zukero Thanks for the positive words. I am looking at the code and I am searching for small things which I can understand and I can improve a little bit. I am trying to get the full picture, but it will take time.
@oskarwiksten No problem, I understand the ideas for readability. You can close this pull request.
I should thank you to both of you that you are so responsive. I will use my chance to ask you one thing more.
I have students in Bulgaria. We were looking at these formulas:
final int costBoostHP = (int)(2770_Math.pow(Math.max(0,averageHPBoost), 2.5) + 450_averageHPBoost); final int costBoostAP = (int)(3100_Math.pow(Math.max(0,averageAPBoost), 2.5) + 300_averageAPBoost);
In order to check are my students capable to think I have asked them what is the meaning of the numbers (2770, 3100, 450, 300, 2.5) and how these numbers are selected? I have got really strange answers, but it was interesting to listen to them.
Why do you feel this way is better? Would you like to give a bit of background or explanation?