30.01.2011, 10:11
Every day I see new faulty ways people benchmark their code, so I figured it'd be a good idea to make some sort of standard that allows easy comparison with other bench results.
I've recently revised my benchmarking macros where I added a "warmup" for highest possible precision. I'll get to that in a little bit.
Why benchmark?
Mainly to make sure your code doesn't cause any performance issues for the server.
How?
You can use my macros to make it really easy!
Example:
Note!
The results will be presented as following:
Bench for x: executes, by average, x times/ms.
What this means is how many times the code can run in one millisecond. This gives you a pretty good perspective!
First off, anything that executes more than 1 times/ms will be ok. It will probably make your server work hard when many players are on, or if the code is being used frequently.
If you're going to make functions other people can use, try keeping them above 50 times/ms.
For larger pieces of code used in callbacks or things like that, I'd say keep them above 20 times/ms.
The macros
Here are the macros you will be using.
Before your code:
After your code:
Human-readable (only for reference)
The macros are compressed version of these snippets:
START_BENCH
FINISH_BENCH
I've recently revised my benchmarking macros where I added a "warmup" for highest possible precision. I'll get to that in a little bit.
Why benchmark?
Mainly to make sure your code doesn't cause any performance issues for the server.
How?
You can use my macros to make it really easy!
pawn Код:
START_BENCH( measure time );
FINISH_BENCH( name );
pawn Код:
START_BENCH( 1000 );
{
floatdiv( 5412.4121234, 2412.1111 );
}
FINISH_BENCH( "floatdiv" );
- Try and place all of your code inside the benchmarking functions; declare variables and such in-between the macros as well.
- Use this only for testing - it will freeze your server for a couple seconds (depending on the time you test).
- Don't do anything (music, videos, being in-game, etc.) that could compromise the benchmarking results - you can survive 2 seconds without those things.
The results will be presented as following:
Bench for x: executes, by average, x times/ms.
What this means is how many times the code can run in one millisecond. This gives you a pretty good perspective!
First off, anything that executes more than 1 times/ms will be ok. It will probably make your server work hard when many players are on, or if the code is being used frequently.
If you're going to make functions other people can use, try keeping them above 50 times/ms.
For larger pieces of code used in callbacks or things like that, I'd say keep them above 20 times/ms.
The macros
Here are the macros you will be using.
Before your code:
pawn Код:
#define START_BENCH(%0); {new __a=%0,__b=0,__c,__d=GetTickCount(),__e=1;do{}\
while(__d==GetTickCount());__c=GetTickCount();__d=__c;while(__c-__d<__a||\
__e){if(__e){if(__c-__d>=__a){__e=0;__c=GetTickCount();do{}while(__c==\
GetTickCount());__c=GetTickCount();__d=__c;__b=0;}}{
pawn Код:
#define FINISH_BENCH(%0); }__b++;__c=GetTickCount();}printf(" Bench for "\
%0": executes, by average, %.2f times/ms.",floatdiv(__b,__a));}
The macros are compressed version of these snippets:
START_BENCH
pawn Код:
{ // Put all the benchmarking code inside a block so we can use it multiple times without "variable already exist" errors.
new
iMeasureTime = %0, // Number of milliseconds to run the code
iCount = 0, // Number of time the code was executed
iTick = GetTickCount( ), // Current tick
iStartTick, // The tick when the benchmarking started
bool:bWarmup = true // Warmup?
;
do { } while ( iTick == GetTickCount( ) ); // Wait and start right after the tick counter goes up (for precision)
iTick = GetTickCount( );
iStartTick = iTick;
while ( iTick - iStartTick < iMeasureTime || bWarmup ) // While the execution time hasn't exceeded iMeasureTime or warmup
{
if ( bWarmup ) // If we're in a warmup..
{
if ( iTick - iStartTick >= iMeasureTime ) // ..and the time has passed
{
bWarmup = false; // No more warmup
iTick = GetTickCount( );
do { } while ( iTick == GetTickCount( ) ); // Wait for the next tick
iTick = GetTickCount( );
iStartTick = iTick;
iCount = 0; // Reset the counter since we just did the warmup
}
}
{
pawn Код:
ґ }
iCount++; // Increase the count
iTick = GetTickCount( ); // Store the current tick in iTick
}
printf( " Bench for " %0 ": executes, by average, %.2f times/ms.", floatdiv( iCount, iMeasureTime ) ); // Print out the results
}