advantis
3/30/2012 - 10:15 AM

Measure code execution time

Measure code execution time

//
//  Copyright © 2012 Yuri Kotov
//

#import <mach/mach_time.h>
#import <Foundation/Foundation.h>

uint64_t ADVGetExecutionTime(void(^block)())
{
    NSCAssert(block, @"'block' parameter can't be nil");

    static mach_timebase_info_data_t timebase = {};

    uint64_t start = mach_absolute_time();
    block();
    uint64_t end = mach_absolute_time();

    if (0 == timebase.denom)
    {
        mach_timebase_info(&timebase);
    }

    return (end - start) * timebase.numer / timebase.denom;
}

uint64_t ADVGetMedianExecutionTime(size_t iterations, void(^block)())
{
    NSCAssert(0 < iterations, @"'iterations' parameter must be positive");

    size_t size = iterations * sizeof(uint64_t);
    uint64_t *samples = malloc(size);
    if (!samples)
    {
        fprintf(stderr, "%s: Unable to allocate %zu bytes", __func__, size);
        return UINT64_MAX;
    }

    for (size_t i = 0; i < iterations; ++i)
    {
        samples[i] = ADVGetExecutionTime(block);
    }

    qsort_b(samples, iterations, sizeof(uint64_t), ^(const void *a, const void *b) {
        return (int)(*(uint64_t*)a - *(uint64_t*)b);
    });

    uint64_t mid = iterations / 2;
    uint64_t result = (iterations & 1) ? samples[mid] : (samples[mid] + samples[mid + 1]) / 2;

    free(samples);

    return result;
}

uint64_t ADVGetExecutionStats(size_t iterations, uint64_t *deviation, void(^block)())
{
    // TODO: Implement this function
    return 0;
}
//
//  Copyright © 2012 Yuri Kotov
//

/*!
    @function   ADVGetExecutionTime
    @abstract   Measure code execution time
    @param      block
                code block to execute
    @result     elapsed time (in nanoseconds)
*/
extern uint64_t ADVGetExecutionTime(void(^block)());

/*!
    @function   ADVGetMedianExecutionTime
    @abstract   Measure median code execution time
    @param      iterations
                number of iterations
    @param      block
                code block to execute
    @result     median elapsed time (in nanoseconds) or UINT64_MAX (in case of failure)
*/
extern uint64_t ADVGetMedianExecutionTime(size_t iterations, void(^block)());


/*!
    @function   ADVGetMedianExecutionTime
    @abstract   Measure code execution time stats, e.g. "52100 ns (±150 ns)"
    @param      iterations
                number of iterations
    @param      deviation
                standard deviation (returned by reference)
    @param      block
                code block to execute
    @result     median elapsed time (in nanoseconds) or UINT64_MAX (in case of failure)
*/
extern uint64_t ADVGetExecutionStats(size_t iterations, uint64_t *deviation, void(^block)());