1/** 2 * \file 3 * \brief Bench library initialization. 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <limits.h> 17#include <barrelfish/barrelfish.h> 18#include <bench/bench.h> 19#include <bench/bench_arch.h> 20 21static cycles_t tsc_overhead; 22 23static uint8_t bench_is_initialized = 0; 24 25/** 26 * \brief Measure overhead of taking timestamp 27 */ 28static void measure_tsc(void) 29{ 30 uint64_t begin; 31 uint64_t end; 32 33 begin = bench_tsc(); 34 for(int i = 0; i < 1000; i++) { 35 end = bench_tsc(); 36 } 37 38 tsc_overhead = (end - begin) / 1000; 39} 40 41/** 42 * \brief Initialize benchmarking library 43 * 44 * \bug x86 specific 45 */ 46void bench_init(void) 47{ 48 if (bench_is_initialized) { 49 return; 50 } 51 52 bench_arch_init(); 53 54 /* Measure overhead of taking timestamps */ 55 measure_tsc(); 56 57 bench_is_initialized = 1; 58} 59 60/** 61 * Return the measured tsc overhead 62 */ 63cycles_t bench_tscoverhead(void) 64{ 65 if (!bench_is_initialized) { 66 bench_init(); 67 } 68 return tsc_overhead; 69} 70 71/** 72 * \brief computes the differences of two time stamps with respecting overflow 73 * 74 * This function also accounts for the overhead when taking timestamps 75 * 76 * \param tsc_start timestamp of start 77 * \param tsc_end timestamp of end 78 * 79 * \return elaped cycles 80 */ 81cycles_t bench_time_diff(cycles_t tsc_start, cycles_t tsc_end) 82{ 83 if (!bench_is_initialized) { 84 bench_init(); 85 } 86 87 cycles_t result; 88 if (tsc_end < tsc_start) { 89 result = (LONG_MAX - tsc_start) + tsc_end - bench_tscoverhead(); 90 } else { 91 result = (tsc_end - tsc_start - bench_tscoverhead()); 92 } 93 return result; 94} 95 96/** 97 * \brief Compute averages 98 * 99 * If certain datapoints should be ignored, they should be marked with 100 * #BENCH_IGNORE_WATERMARK 101 */ 102cycles_t bench_avg(cycles_t *array, size_t len) 103{ 104 cycles_t sum = 0; 105 size_t count = 0; 106 107 // Discarding some initial observations 108 for (size_t i = len >> 3; i < len; i++) { 109 if (array[i] != BENCH_IGNORE_WATERMARK) { 110 sum += array[i]; 111 count++; 112 } 113 } 114 115 return sum / count; 116} 117 118/** 119 * \brief Compute variance 120 * 121 * If certain datapoints should be ignored, they should be marked with 122 * #BENCH_IGNORE_WATERMARK 123 */ 124cycles_t bench_variance(cycles_t *array, size_t len) 125{ 126 cycles_t avg = bench_avg(array, len); 127 128 cycles_t sum = 0; 129 size_t count = 0; 130 131 // Discard some initial observations 132 for (size_t i = len >> 3; i < len; i++) { 133 if (array[i] != BENCH_IGNORE_WATERMARK) { 134 sum += array[i] * array[i]; 135 count++; 136 } 137 } 138 139 return (sum / count) - (avg * avg); 140} 141 142/** 143 * \brief computes the standard deviation s^2 of the sample data 144 * 145 * \param array array of data to analyze 146 * \param len size of the array 147 * \param correction apply Bessel's correction (using N-1 instead of N) 148 * \param ret_avg returns the average of the sample 149 * \param ret_stddev returns the standard deviation squared of the sample 150 */ 151void bench_stddev(cycles_t *array, size_t len, uint8_t correction, 152 cycles_t *ret_avg, cycles_t *ret_stddev) 153{ 154 cycles_t avg = bench_avg(array, len); 155 156 cycles_t sum = 0; 157 size_t count = 0; 158 /// discard some initiali observations 159 for (size_t i = len >> 3; i < len; i++) { 160 if (array[i] != BENCH_IGNORE_WATERMARK) { 161 cycles_t subsum = array[i] - avg; 162 sum += (subsum * subsum); 163 count++; 164 } 165 } 166 167 168 169 cycles_t std_dev = 0; 170 if (correction && count > 1) { 171 std_dev = sum / (count - 1); 172 } else { 173 std_dev = sum / count; 174 } 175 176 if (ret_avg) { 177 *ret_avg = avg; 178 } 179 180 if (ret_stddev) { 181 *ret_stddev = std_dev; 182 } 183} 184 185 186 187/** 188 * \brief Compute minimum 189 * 190 * If certain datapoints should be ignored, they should be marked with 191 * #BENCH_IGNORE_WATERMARK 192 */ 193cycles_t bench_min(cycles_t *array, size_t len) 194{ 195 size_t i = len >> 3; 196 cycles_t min = (cycles_t) -1ULL; 197 198 for (; i < len; i++) { 199 if (array[i] != BENCH_IGNORE_WATERMARK && array[i] < min) { 200 min = array[i]; 201 } 202 } 203 204 return min; 205} 206 207/** 208 * \brief Compute maximum 209 * 210 * If certain datapoints should be ignored, they should be marked with 211 * #BENCH_IGNORE_WATERMARK 212 */ 213cycles_t bench_max(cycles_t *array, size_t len) 214{ 215 size_t i = len >> 3; 216 cycles_t max = 0; 217 218 for (; i < len; i++) { 219 if (array[i] != BENCH_IGNORE_WATERMARK && array[i] > max) { 220 max = array[i]; 221 } 222 } 223 224 return max; 225} 226