Tiny But Super Optimizations -
Crayder - 28.04.2016
In this thread I'll point out some very small optimizations that can make a huge difference in speed in the long run.
Most of these are very minor, negligible speed differences. The point is THERE ARE DIFFERENCES. There are a lot of situations where these would help majorly. Sure these cases are rare, but they do exist and I've encountered them a lot!
Bare in mind, this thread is still no where near being complete.
I bet you didn't know that "+= 1" and "var = var + 1" were both twice as fast as "++", so read on.
(Note: lines preceded by a semi-colon in the assembly are comments.)
____________________________________________
Here is a great example to start us off.
Float vectors: Arrays vs Multiple Variables.
I've seen so many people doing things like this:
Instead of doing this:
pawn Code:
new Float:tX, Float:tY, Float:tZ
What's wrong with that? Well look here:
This compiler turns that into the following assembly output:
Code:
const.pri 1
stor.s.pri fffffff4
stor.s.pri fffffff8
stor.s.pri fffffffc
While for this:
The compiler does this:
Code:
addr.pri ffffffe8
push.pri
addr.pri ffffffe8
add.c 4
push.pri
addr.pri ffffffe8
add.c 8
move.alt
const.pri 1
stor.i
pop.alt
stor.i
pop.alt
stor.i
I'm not going to walk you through the assembly, but I think it's obvious which one is better. It doesn't matter if you chain them or not, the arrays will always be slower. Just to prove my point here is the timing of each of these:
Quote:
Timing "accessing and setting singles"...
Mean = 136.00ns
Mode = 135.00ns
Median = 136.00ns
Range = 4.00ns
Timing "accessing and setting array"...
Mean = 233.00ns
Mode = 232.00ns
Median = 233.00ns
Range = 3.00ns
|
____________________________________________
Now for the rest of them.
- Variable definitions: Chained Definitions vs Defining Each
What people are doing:
pawn Code:
new tmp1;
new tmp2;
new tmp3;
new tmp4;
new tmp5;
What people should be doing more often:
pawn Code:
new tmp1, tmp2, tmp3, tmp4, tmp5;
Assembly for what people are doing:
pawn Code:
break
push.c 0
break
push.c 0
break
push.c 0
break
push.c 0
break
push.c 0
Assembly for what people should be doing more often:
pawn Code:
push.c 0
push.c 0
push.c 0
push.c 0
push.c 0
So basically, the break's (';') are almost doubling the time it takes! Don't believe me? Well, look at the time comparison:
Quote:
Timing "new chain"...
Mean = 114.00ns
Mode = 114.00ns
Median = 114.00ns
Range = 2.00ns
Timing "new each"...
Mean = 221.00ns
Mode = 222.00ns
Median = 222.00ns
Range = 3.00ns
|
It's a shame that PAWN does this, but it is a fact we must face.
- Setting Variables: Chain Assignments vs Assigning Each
What people are doing:
pawn Code:
tmp1 = 17;
tmp2 = 17;
tmp3 = 17;
tmp4 = 17;
tmp5 = 17;
What people should be doing more often:
pawn Code:
tmp1 = tmp2 = tmp3 = tmp4 = tmp5 = 17;
Assembly for what people are doing:
pawn Code:
break
const.pri 11
stor.s.pri fffffffc
break
const.pri 11
stor.s.pri fffffff8
break
const.pri 11
stor.s.pri fffffff4
break
const.pri 11
stor.s.pri fffffff0
break
const.pri 11
stor.s.pri ffffffec
Assembly for what people should be doing more often:
pawn Code:
const.pri 11
stor.s.pri ffffffec
stor.s.pri fffffff0
stor.s.pri fffffff4
stor.s.pri fffffff8
stor.s.pri fffffffc
So, 6 lines versus 15, which one is fastest?
Quote:
Timing "set chain"...
Mean = 121.00ns
Mode = 118.00ns
Median = 119.00ns
Range = 18.00ns
Timing "set each"...
Mean = 219.00ns
Mode = 217.00ns
Median = 217.00ns
Range = 9.00ns
|
6 lines, obviously. Start chaining your variable asignments if you are setting them to the same value!
- If Lines: Chained vs Many
What people are doing:
pawn Code:
if(tmp1 == 1)
if(tmp2 == 1)
if(tmp3 == 1)
if(tmp4 == 1)
if(tmp5 == 1)
{}
What people should be doing more often:
pawn Code:
if(tmp1 == 1 && tmp2 == 1 && tmp3 == 1 && tmp4 == 1 && tmp5 == 1) {}
Assembly for what people are doing:
pawn Code:
break
load.s.pri fffffffc
eq.c.pri 1
jzer 3
break
load.s.pri fffffff8
eq.c.pri 1
jzer 4
break
load.s.pri fffffff4
eq.c.pri 1
jzer 5
break
load.s.pri fffffff0
eq.c.pri 1
jzer 6
break
load.s.pri ffffffec
eq.c.pri 1
jzer 7
Assembly for what people should be doing more often:
pawn Code:
break
load.s.pri fffffffc
eq.c.pri 1
jzer 1
load.s.pri fffffff8
eq.c.pri 1
jzer 1
load.s.pri fffffff4
eq.c.pri 1
jzer 1
load.s.pri fffffff0
eq.c.pri 1
jzer 1
load.s.pri ffffffec
eq.c.pri 1
jzer 1
So by sight, it's the breaks (each if section this time) again!
Quote:
Timing "if chain"...
Mean = 164.00ns
Mode = 163.00ns
Median = 164.00ns
Range = 3.00ns
Timing "if lot"...
Mean = 230.00ns
Mode = 228.00ns
Median = 228.00ns
Range = 16.00ns
|
They are slowing us down more than we think!
- Value Testing: Switch vs "If =="
What people are doing:
pawn Code:
if(tmp == 2 ) {}
else if(tmp == 5 ) {}
else if(tmp == 8 ) {}
else if(tmp == 11) {}
else if(tmp == 14) {}
else if(tmp == 17) {}
else if(tmp == 20) {}
else if(tmp == 23) {}
else if(tmp == 26) {}
else if(tmp == 29) {}
else {}
What people should be doing more often:
pawn Code:
switch(tmp) {
case 2 : {}
case 5 : {}
case 8 : {}
case 11: {}
case 14: {}
case 17: {}
case 20: {}
case 23: {}
case 26: {}
case 29: {}
default: {}
}
Assembly for what people are doing:
pawn Code:
break
load.pri 0
eq.c.pri 2
jzer 0
jump 1
l.0
break
load.pri 0
eq.c.pri 5
jzer 2
jump 3
l.2
break
load.pri 0
eq.c.pri 8
jzer 4
jump 5
l.4
break
load.pri 0
eq.c.pri b
jzer 6
jump 7
l.6
break
load.pri 0
eq.c.pri e
jzer 8
jump 9
l.8
break
load.pri 0
eq.c.pri 11
jzer a
jump b
l.a
break
load.pri 0
eq.c.pri 14
jzer c
jump d
l.c
break
load.pri 0
eq.c.pri 17
jzer e
jump f
l.e
break
load.pri 0
eq.c.pri 1a
jzer 10
jump 11
l.10
break
load.pri 0
eq.c.pri 1d
jzer 12
jump 13
l.12
l.13
l.11
l.f
l.d
l.b
l.9
l.7
l.5
l.3
l.1
Assembly for what people should be doing more often:
pawn Code:
break
load.pri 0
switch 0
l.2
jump 1
l.3
jump 1
l.4
jump 1
l.5
jump 1
l.6
jump 1
l.7
jump 1
l.8
jump 1
l.9
jump 1
l.a
jump 1
l.b
jump 1
l.c
jump 1
l.0
casetbl
case a c
case 2 2
case 5 3
case 8 4
case b 5
case e 6
case 11 7
case 14 8
case 17 9
case 1a a
case 1d b
l.1
There is actually a lot more to this, this is just a basic example. Switches with ranges and things are way more optimized than any logic if test. And the timings...
Quote:
Timing "if-elseif-else"...
Mean = 408.00ns
Mode = 407.00ns
Median = 407.00ns
Range = 19.00ns
Timing "switch"...
Mean = 100.00ns
Mode = 97.00ns
Median = 99.00ns
Range = 12.00ns
|
Yeah, 4 times the speed difference. And again, as I said, this is just a basic example. A more complex example would have an even greater difference.
To be continued...
(so please don't bother replying yet)
Re: Tiny But Super Optimizations -
iGetty - 01.05.2016
This is nice mate. People can learn bits from this.
Re: Tiny But Super Optimizations -
lolumadd_ - 01.05.2016
Quote:
tmp1 = tmp2 = tmp3 = tmp4 = tmp5 = 17;
|
I didn't even know you could have multiple assignments within a single statement in Pawn. Mind blown.
Re: Tiny But Super Optimizations -
Mauzen - 01.05.2016
Nice to see that stuff actually tested.
Heres another one (that most people probably already are aware of):
pawn Code:
new Float:value = 5.0;
// Slow
value = value / 2;
// converts to
// value = value / float(2);
// Faster
value = value / 2.0;
Also applies to any other operations connecting a float and an integer.
Ive once measured the time for that, but it was years ago and I have no idea if the post even still exists in the forum.
Re: Tiny But Super Optimizations -
AmigaBlizzard - 01.05.2016
PHP Code:
enum TPlayerData
{
UserID,
Name[25],
Password[130],
IP[16],
GPCI[130],
PasswordAttempts,
bool:LoggedIn,
bool:InClassSelection,
// Player data
Money,
Score,
AdminLevel,
Speed
}
new APlayerData[MAX_PLAYERS][TPlayerData];
Consider this enum structure.
Most people do this when clearing all data in a player's account when a player disconnects or connects (to be sure the new player won't get data from the previous player):
PHP Code:
APlayerData[playerid][UserID] = 0;
APlayerData[playerid][Name][0] = 0;
APlayerData[playerid][Password][0] = 0;
APlayerData[playerid][IP][0] = 0;
APlayerData[playerid][GPCI][0] = 0;
APlayerData[playerid][PasswordAttempts] = 0;
APlayerData[playerid][LoggedIn] = false;
APlayerData[playerid][InClassSelection] = false;
APlayerData[playerid][Money] = 0;
APlayerData[playerid][Score] = 0;
APlayerData[playerid][AdminLevel] = 0;
APlayerData[playerid][Speed] = 0;
While it's alot easier to do this:
PHP Code:
new temp[TPlayerData];
APlayerData[playerid] = temp;
No need for hundreds of lines of code to reset your entire structure one variable at a time and no risk about forgetting to reset one of them.
Just reset them all at once.
I have no idea if it's faster and if it is, how much faster.
I never tested the speed of it, but it surely is less code and less risk to clear all your vars.
Re: Tiny But Super Optimizations -
Crayder - 02.05.2016
Quote:
Originally Posted by Mauzen
Nice to see that stuff actually tested.
Heres another one (that most people probably already are aware of):
pawn Code:
new Float:value = 5.0;
// Slow value = value / 2; // converts to // value = value / float(2);
// Faster value = value / 2.0;
Also applies to any other operations connecting a float and an integer.
Ive once measured the time for that, but it was years ago and I have no idea if the post even still exists in the forum.
|
I already addressed that actually, I just haven't put it in the post yet. I have a lot more tests I didn't toss in the post yet.
Re: Tiny But Super Optimizations -
PrO.GameR - 02.05.2016
Okay so apparently we can bother posting now =P
Here's a question and at the same time could be a part for this thread.
Is it faster using Macros instead of functions if possible? (as far as my knowledge goes it is in most cases, but would really like to know)
PHP Code:
GetHousePos(houseid,&Float:x,&Float:y,&Float:z)
{
x=HouseI[houseid][X];
y=HouseI[houseid][Y];
z=HouseI[houseid][Z];
return 1;
}
could this be turned to (well it compiles that far I know):
PHP Code:
#define GetHousePos(%0,%1,%2,%3) (%1=HouseI[%0][X],%2=HouseI[%0][Y],%3=HouseI[%0][Z])
and which one is faster?
Re: Tiny But Super Optimizations -
Vince - 02.05.2016
Boohoo, 100 nanoseconds difference. Readability should always take precedence over such extremely negligible improvements.
Respuesta: Tiny But Super Optimizations -
aoEXE - 02.05.2016
I think it is up to each if applies or not, just as it is not bad to know it. I created the code, I read the code, I understand my code. If I did to share it, maybe yes I care a little more readability before optimization exaggerated.
This is just to know what is faster.
Re: Tiny But Super Optimizations -
Darkwood17 - 02.05.2016
Код:
if (a == 1 || a == 2 || a == 3 || a == 4 || a == 5)
Isn't it faster to do this:
Код:
switch (a)
{
case 1, 2, 3, 4, 5:
{
// Do something
}
}
Re: Tiny But Super Optimizations -
Crayder - 02.05.2016
Quote:
Originally Posted by Vince
Boohoo, 100 nanoseconds difference. Readability should always take precedence over such extremely negligible improvements.
|
Quote:
Originally Posted by Jay_
Completely agree. This whole optimization thing is major overkill. I think it originated from Y_Less in that huge code optimazitions thread that was later proven redundant when it was benchmarked.
|
Yes, no shit the speeds here are very negligible. As I mentioned before. The point is that there is a difference. These tiny speed differences can very well matter in certain situations, though.
Quote:
Originally Posted by Darkwood17
Код:
if (a == 1 || a == 2 || a == 3 || a == 4 || a == 5)
Isn't it faster to do this:
Код:
switch (a)
{
case 1, 2, 3, 4, 5:
{
// Do something
}
}
|
As I said, this thread is to be continued. I've only put up some of my tests so far. I have lots more that I have already tested but haven't put in the thread yet. That includes if vs switch (one of the more extreme speed differences, totally different operations).
@PrO.GameR, function calls themselves are extremely slow compared to statements. That's obvious.
Re: Tiny But Super Optimizations -
Konstantinos - 02.05.2016
Quote:
Originally Posted by Darkwood17
Код:
if (a == 1 || a == 2 || a == 3 || a == 4 || a == 5)
Isn't it faster to do this:
Код:
switch (a)
{
case 1, 2, 3, 4, 5:
{
// Do something
}
}
|
Which can also written as:
---
Some are minor but it's always good to know even if the difference is not even noticeable.
Anyway, one thing I mostly see in threads about scripting help is the declaration of variables inside loops.
Re: Tiny But Super Optimizations -
Yashas - 02.05.2016
Quote:
Originally Posted by Vince
Boohoo, 100 nanoseconds difference. Readability should always take precedence over such extremely negligible improvements.
|
Quote:
Originally Posted by Jay_
Completely agree. This whole optimization thing is major overkill. I think it originated from Y_Less in that huge code optimazitions thread that was later proven redundant when it was benchmarked.
|
Coincidently, all the optimizations mentioned in this topic atm improve readability.
Which one is ugly?
Код:
new Float:pos[3];
GetPlayerPos(0, pos[0], pos[1], pos[2]);
OR
Код:
new Float:X, Float:Y, Float:Z;
GetPlayerPos(0, X, Y, Z);
This is the most annoying way to declare variables. Of course if one tells the compiler to stop compiling with debug information, the optimization would make no difference (assuming so since the sole purpose of break is to help the internal debugger)
Код:
new tmp1;
new tmp2;
new tmp3;
new tmp4;
new tmp5;
Код:
new tmp1, tmp2, tmp3, tmp4, tmp5;
Which is better?
Код:
tmp1 = 17;
tmp2 = 17;
tmp3 = 17;
tmp4 = 17;
tmp5 = 17;
tmp1 = tmp2 = tmp3 = tmp4 = tmp5 = 17;
and what is wrong with this one?
Код:
if(tmp1 == 1)
if(tmp2 == 1)
if(tmp3 == 1)
if(tmp4 == 1)
if(tmp5 == 1)
{}
if(tmp1 == 1 && tmp2 == 1 && tmp3 == 1 && tmp4 == 1 && tmp5 == 1) {}
These optimizations though tiny actually make the code more readable. There is no reason why someone shouldn't do these optimizations.
Maybe someday in future, I will make a neat topic which will list optimizations that really make a "big" improvement which are actually based on "smart ideas" rather than coding techniques.
Re: Tiny But Super Optimizations -
Mauzen - 02.05.2016
Quote:
Originally Posted by Vince
Boohoo, 100 nanoseconds difference. Readability should always take precedence over such extremely negligible improvements.
|
Whats 100 nanoseconds? Actually a lot, considering that it means "twice as fast" in these cases. Ive done a lot of optimizations like this a while ago for a highly complex math job that couldnt be done in a plugin, and without saving some micros here and some hundred nanos there the function would have been way too slow to be used.
Sure, cases that really need that stuff are rare, but I dont see the problem in using these optimizations in places where it doesnt hurt the readability.
Re: Tiny But Super Optimizations -
Slice - 02.05.2016
Quote:
Originally Posted by Jay_
Completely agree. This whole optimization thing is major overkill. I think it originated from Y_Less in that huge code optimazitions thread that was later proven redundant when it was benchmarked.
|
Well he says himself that he completely agrees with that. I suppose people didn't realize the optimizations aren't needed in most cases, and should only be used if there are hot spots in your code (e.g. a loop that's ran thousands of times).
Re: Tiny But Super Optimizations -
Macluawn - 03.05.2016
Quote:
Originally Posted by Mauzen
Whats 100 nanoseconds? Actually a lot, considering that it means "twice as fast" in these cases.
|
It's the difference between light travelling 30 meters and 60 meters.. You won`t notice it.
Re: Tiny But Super Optimizations -
Crayder - 03.05.2016
Quote:
Originally Posted by Macluawn
It's the difference between light travelling 30 meters and 60 meters.. You won`t notice it.
|
Except in certain cases you WILL notice it. Same applies to both light and these opt's.
Re: Tiny But Super Optimizations -
SyS - 04.05.2016
This thread can be useful to me as i code like mess
Re: Tiny But Super Optimizations -
Crayder - 04.05.2016
Quote:
Originally Posted by Sreyas
This thread can be useful to me as i code like mess
|
This thread is nothing about your mess. It's about tiny optimizations that many people will find extremely useful in many circumstances.
For your mess, you just need to learn how to write code. You clearly got the brunt of it down, just keep paying attention to how it's supposed to be done. Learn some other languages too, that will actually help a lot. Seeing how things are done in multiple languages will give you a great baseline style.
Re: Tiny But Super Optimizations -
SyS - 04.05.2016
Quote:
Originally Posted by Crayder
This thread is nothing about your mess. It's about tiny optimizations that many people will find extremely useful in many circumstances.
For your mess, you just need to learn how to write code. You clearly got the brunt of it down, just keep paying attention to how it's supposed to be done. Learn some other languages too, that will actually help a lot. Seeing how things are done in multiple languages will give you a great baseline style.
|
-_- that was not i meant for your info i know how to script in c++(u dont need to teach me that),pawn(ofcourse ),SQL ,sort of python and little bit Java .I just said my codes are not pretty printed (yeah i meant that most of the things in this thread are not optimzations they are just pretty printing)