PDA

View Full Version : [Tutorial] Benchmarking



SergiuOfficial
17-06-17, 08:35
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!

Code:
START_BENCH( measure time );
FINISH_BENCH( name );

Example:
Code:
START_BENCH( 1000 );
{
floatdiv( 5412.4121234, 2412.1111 );
}
FINISH_BENCH( "floatdiv" );

Note!
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
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:
Code:
#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;} }{

After your code:
Code:
#define FINISH_BENCH(%0); }__b++;__c=GetTickCount();}printf(" Bench for "\
%0": executes, by average, %.2f times/ms.",floatdiv(__b,__a));}

Human-readable (only for reference)

The macros are compressed version of these snippets:

START_BENCH
Code:
{ // 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
}
}
{

FINISH_BENCH
Code:
´ }

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 ) )