in unittest/lib/perf.cpp [617:694]
double measureKeyPerfGivenStack( SIZE_T keySize,
PerfKeyFn keyFn,
PerfCleanFn cleanFn,
int * pNRuns )
{
PBYTE buf1 = g_perfBuffer + 0*PERF_BUFFER_SIZE + (g_rng.sizet( PERF_BUFFER_SIZE ) & ~0xf);
PBYTE buf2 = g_perfBuffer + 2*PERF_BUFFER_SIZE + (g_rng.sizet( PERF_BUFFER_SIZE ) & ~0xf);
PBYTE buf3 = g_perfBuffer + 4*PERF_BUFFER_SIZE + (g_rng.sizet( PERF_BUFFER_SIZE ) & ~0xf);
//PBYTE buf4 = g_perfBuffer + 6*PERF_BUFFER_SIZE + (g_rng.sizet( PERF_BUFFER_SIZE ) & ~0xf);
double durations[ MEASUREMENTS_PER_RESULT ];
int runs = *pNRuns;
int i=0;
ULONGLONG time0, time1, time2;
time0 = GET_PERF_CLOCK();
FIXED_TIME_LOOP();
time1 = GET_PERF_CLOCK();
double fixedBefore = (double) (time1 - time0);
while( i < MEASUREMENTS_PER_RESULT )
{
time0 = GET_PERF_CLOCK();
for( int j=0; j<runs; j++ )
{
(*keyFn)( buf1, buf2, buf3, keySize );
(*cleanFn)( buf1, buf2, buf3 );
}
time1 = GET_PERF_CLOCK();
FIXED_TIME_LOOP();
time2 = GET_PERF_CLOCK();
double fixedAfter = (double) (time2 - time1);
double measurementScaleFactor = ((double) FIXED_TIME_LOOP_EXPECTED_CYCLES * 2) / (fixedBefore + fixedAfter);
double fixedRatio = fixedBefore > fixedAfter ? fixedBefore / fixedAfter : fixedAfter / fixedBefore;
fixedBefore = fixedAfter; // now use this after measurement as the next before measurement
if( g_perfClockScaling && fixedRatio > 1.01f )
{
// Something changed in timing between before and after, rerun this run
continue;
}
ULONGLONG duration = time1 - time0;
if( duration < g_minMeasurementClockTime )
{
//
// The measurement was too short, restart & double the # runs we do.
//
i = 0;
runs <<= 1;
CHECK( runs <= MAX_RUNS_PER_MEASUREMENT, "Measurement too fast" );
continue;
}
durations[i] = (double) duration;
if( g_perfClockScaling )
{
durations[i] *= measurementScaleFactor;
}
++i;
}
qsort( durations, MEASUREMENTS_PER_RESULT, sizeof( durations[0] ), compareDouble );
//
// We return the one-third percentile point to compensate for expected slow-downs.
//
double res = (double) durations[MEASUREMENTS_PER_RESULT/3];
res -= g_perfMeasurementOverhead;
res /= runs;
res *= g_perfScaleFactor;
res -= g_perfRunOverhead;
*pNRuns = runs;
return res;
}