Changeset e7f9a09 in mainline
- Timestamp:
- 2019-01-21T13:20:31Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d17cf8c
- Parents:
- 94ebebf
- Location:
- uspace/app/hbench
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/hbench/csv.c
r94ebebf re7f9a09 62 62 * nothing. 63 63 * 64 * @param stopwatchPerformance data of the entry.64 * @param run Performance data of the entry. 65 65 * @param run_index Run index, use negative values for warm-up. 66 66 * @param bench Benchmark information. 67 67 * @param workload_size Workload size. 68 68 */ 69 void csv_report_add_entry(bench meter_t *meter, int run_index,69 void csv_report_add_entry(bench_run_t *run, int run_index, 70 70 benchmark_t *bench, uint64_t workload_size) 71 71 { … … 76 76 fprintf(csv_output, "%s,%d,%" PRIu64 ",%lld\n", 77 77 bench->name, run_index, workload_size, 78 (long long) stopwatch_get_nanos(& meter->stopwatch));78 (long long) stopwatch_get_nanos(&run->stopwatch)); 79 79 } 80 80 -
uspace/app/hbench/doc/doxygroups.h
r94ebebf re7f9a09 19 19 * benchmark function to the benchmark_t. 20 20 * 21 * The benchmarking function has to accept fourarguments:22 * @li bench meter_t: call benchmeter_start and benchmeter_stop around the21 * The benchmarking function has to accept two arguments: 22 * @li bench_run_t: call bench_run_start and bench_run_stop around the 23 23 * actual benchmarking code 24 24 * @li uint64_t: size of the workload - typically number of inner loops in 25 25 * your benchmark (used to self-calibrate benchmark size) 26 * @li char * and size_t giving you access to buffer for storing error message27 * if the benchmark fails (return false from the function itself then)28 26 * 29 27 * Typically, the structure of the function is following: 30 28 * @code{c} 31 * static bool runner(benchmeter_t *meter, uint64_t size, 32 * char *error, size_t error_size) 29 * static bool runner(bench_run_t *run, uint64_t size) 33 30 * { 34 * bench meter_start(meter);31 * bench_run_start(run); 35 32 * for (uint64_t i = 0; i < size; i++) { 36 33 * // measured action 34 * if (something_fails) { 35 * return bench_run_fail(run, "oops: %s (%d)", str_error(rc), rc); 36 * } 37 37 * } 38 * bench meter_stop(meter);38 * bench_run_stop(run); 39 39 * 40 40 * return true; -
uspace/app/hbench/fs/dirread.c
r94ebebf re7f9a09 44 44 * that the corresponding blocks would be cached after first run. 45 45 */ 46 static bool runner(benchmeter_t *meter, uint64_t size, 47 char *error, size_t error_size) 46 static bool runner(bench_run_t *run, uint64_t size) 48 47 { 49 48 const char *path = bench_param_get("dirname", "/"); 50 49 51 bench meter_start(meter);50 bench_run_start(run); 52 51 for (uint64_t i = 0; i < size; i++) { 53 52 DIR *dir = opendir(path); 54 53 if (dir == NULL) { 55 snprintf(error, error_size, "failed to open %s for reading: %s",54 return bench_run_fail(run, "failed to open %s for reading: %s", 56 55 path, str_error(errno)); 57 return false;58 56 } 59 57 … … 65 63 closedir(dir); 66 64 } 67 bench meter_stop(meter);65 bench_run_stop(run); 68 66 69 67 return true; -
uspace/app/hbench/fs/fileread.c
r94ebebf re7f9a09 45 45 * corresponding blocks would be cached after first run. 46 46 */ 47 static bool runner(benchmeter_t *meter, uint64_t size, 48 char *error, size_t error_size) 47 static bool runner(bench_run_t *run, uint64_t size) 49 48 { 50 49 const char *path = bench_param_get("filename", "/data/web/helenos.png"); … … 52 51 char *buf = malloc(BUFFER_SIZE); 53 52 if (buf == NULL) { 54 snprintf(error, error_size, "failed to allocate %dB buffer", BUFFER_SIZE); 55 return false; 53 return bench_run_fail(run, "failed to allocate %dB buffer", BUFFER_SIZE); 56 54 } 57 55 … … 60 58 FILE *file = fopen(path, "r"); 61 59 if (file == NULL) { 62 snprintf(error, error_size, "failed to open %s for reading: %s",60 bench_run_fail(run, "failed to open %s for reading: %s", 63 61 path, str_error(errno)); 64 62 ret = false; … … 66 64 } 67 65 68 bench meter_start(meter);66 bench_run_start(run); 69 67 for (uint64_t i = 0; i < size; i++) { 70 68 int rc = fseek(file, 0, SEEK_SET); 71 69 if (rc != 0) { 72 snprintf(error, error_size, "failed to rewind %s: %s",70 bench_run_fail(run, "failed to rewind %s: %s", 73 71 path, str_error(errno)); 74 72 ret = false; … … 78 76 fread(buf, 1, BUFFER_SIZE, file); 79 77 if (ferror(file)) { 80 snprintf(error, error_size, "failed to read from %s: %s",78 bench_run_fail(run, "failed to read from %s: %s", 81 79 path, str_error(errno)); 82 80 ret = false; … … 85 83 } 86 84 } 87 bench meter_stop(meter);85 bench_run_stop(run); 88 86 89 87 leave_close: -
uspace/app/hbench/hbench.h
r94ebebf re7f9a09 38 38 39 39 #include <errno.h> 40 #include <stdarg.h> 40 41 #include <stdbool.h> 42 #include <stdio.h> 41 43 #include <perf.h> 42 44 43 /** Simple wrapper around system stopwatch. 45 /** Single run information. 46 * 47 * Used to store both performance information (now, only wall-clock 48 * time) as well as information about error. 49 * 50 * Use proper access functions when modifying data inside this structure. 44 51 * 45 52 * Eventually, we could collection of hardware counters etc. without … … 48 55 typedef struct { 49 56 stopwatch_t stopwatch; 50 } benchmeter_t; 57 char *error_buffer; 58 size_t error_buffer_size; 59 } bench_run_t; 51 60 52 static inline void benchmeter_init(benchmeter_t *meter) 61 static inline void bench_run_init(bench_run_t *run, char *error_buffer, 62 size_t error_buffer_size) 53 63 { 54 stopwatch_init(&meter->stopwatch); 64 stopwatch_init(&run->stopwatch); 65 run->error_buffer = error_buffer; 66 run->error_buffer_size = error_buffer_size; 55 67 } 56 68 57 static inline void bench meter_start(benchmeter_t *meter)69 static inline void bench_run_start(bench_run_t *run) 58 70 { 59 stopwatch_start(& meter->stopwatch);71 stopwatch_start(&run->stopwatch); 60 72 } 61 73 62 static inline void bench meter_stop(benchmeter_t *meter)74 static inline void bench_run_stop(bench_run_t *run) 63 75 { 64 stopwatch_stop(& meter->stopwatch);76 stopwatch_stop(&run->stopwatch); 65 77 } 66 78 67 typedef bool (*benchmark_entry_t)(benchmeter_t *, uint64_t, 68 char *, size_t); 69 typedef bool (*benchmark_helper_t)(char *, size_t); 79 static inline bool bench_run_fail(bench_run_t *run, const char *fmt, ...) 80 { 81 va_list args; 82 va_start(args, fmt); 83 vsnprintf(run->error_buffer, run->error_buffer_size, fmt, args); 84 va_end(args); 85 86 return false; 87 } 88 89 typedef bool (*benchmark_entry_t)(bench_run_t *, uint64_t); 90 typedef bool (*benchmark_helper_t)(bench_run_t *); 70 91 71 92 typedef struct { … … 81 102 82 103 extern errno_t csv_report_open(const char *); 83 extern void csv_report_add_entry(bench meter_t *, int, benchmark_t *, uint64_t);104 extern void csv_report_add_entry(bench_run_t *, int, benchmark_t *, uint64_t); 84 105 extern void csv_report_close(void); 85 106 -
uspace/app/hbench/ipc/ns_ping.c
r94ebebf re7f9a09 38 38 #include "../hbench.h" 39 39 40 static bool runner(benchmeter_t *meter, uint64_t niter, 41 char *error, size_t error_size) 40 static bool runner(bench_run_t *run, uint64_t niter) 42 41 { 43 bench meter_start(meter);42 bench_run_start(run); 44 43 45 44 for (uint64_t count = 0; count < niter; count++) { … … 47 46 48 47 if (rc != EOK) { 49 snprintf(error, error_size, 50 "failed sending ping message: %s (%d)", 48 return bench_run_fail(run, "failed sending ping message: %s (%d)", 51 49 str_error(rc), rc); 52 return false;53 50 } 54 51 } 55 52 56 bench meter_stop(meter);53 bench_run_stop(run); 57 54 58 55 return true; -
uspace/app/hbench/ipc/ping_pong.c
r94ebebf re7f9a09 40 40 static ipc_test_t *test = NULL; 41 41 42 static bool setup( char *error, size_t error_size)42 static bool setup(bench_run_t *run) 43 43 { 44 44 errno_t rc = ipc_test_create(&test); 45 45 if (rc != EOK) { 46 snprintf(error, error_size,46 return bench_run_fail(run, 47 47 "failed contacting IPC test server (have you run /srv/test/ipc-test?): %s (%d)", 48 48 str_error(rc), rc); 49 return false;50 49 } 51 50 … … 53 52 } 54 53 55 static bool teardown( char *error, size_t error_size)54 static bool teardown(bench_run_t *run) 56 55 { 57 56 ipc_test_destroy(test); … … 59 58 } 60 59 61 static bool runner(benchmeter_t *meter, uint64_t niter, 62 char *error, size_t error_size) 60 static bool runner(bench_run_t *run, uint64_t niter) 63 61 { 64 bench meter_start(meter);62 bench_run_start(run); 65 63 66 64 for (uint64_t count = 0; count < niter; count++) { … … 68 66 69 67 if (rc != EOK) { 70 snprintf(error, error_size, 71 "failed sending ping message: %s (%d)", 68 return bench_run_fail(run, "failed sending ping message: %s (%d)", 72 69 str_error(rc), rc); 73 return false;74 70 } 75 71 } 76 72 77 bench meter_stop(meter);73 bench_run_stop(run); 78 74 79 75 return true; -
uspace/app/hbench/main.c
r94ebebf re7f9a09 53 53 #define MAX_ERROR_STR_LENGTH 1024 54 54 55 static void short_report(bench meter_t *meter, int run_index,55 static void short_report(bench_run_t *info, int run_index, 56 56 benchmark_t *bench, uint64_t workload_size) 57 57 { 58 csv_report_add_entry( meter, run_index, bench, workload_size);59 60 usec_t duration_usec = NSEC2USEC(stopwatch_get_nanos(& meter->stopwatch));58 csv_report_add_entry(info, run_index, bench, workload_size); 59 60 usec_t duration_usec = NSEC2USEC(stopwatch_get_nanos(&info->stopwatch)); 61 61 62 62 printf("Completed %" PRIu64 " operations in %llu us", 63 63 workload_size, duration_usec); 64 64 if (duration_usec > 0) { 65 double nanos = stopwatch_get_nanos(& meter->stopwatch);65 double nanos = stopwatch_get_nanos(&info->stopwatch); 66 66 double thruput = (double) workload_size / (nanos / 1000000000.0l); 67 67 printf(", %.0f ops/s.\n", thruput); … … 111 111 * 112 112 */ 113 static void compute_stats(bench meter_t *meter, size_t stopwatch_count,113 static void compute_stats(bench_run_t *runs, size_t run_count, 114 114 uint64_t workload_size, double precision, double *out_duration_avg, 115 115 double *out_duration_sigma, double *out_thruput_avg) … … 119 119 double nanos_sum2 = 0.0; 120 120 121 for (size_t i = 0; i < stopwatch_count; i++) {122 double nanos = stopwatch_get_nanos(& meter[i].stopwatch);121 for (size_t i = 0; i < run_count; i++) { 122 double nanos = stopwatch_get_nanos(&runs[i].stopwatch); 123 123 double thruput = (double) workload_size / nanos; 124 124 … … 127 127 nanos_sum2 += nanos * nanos; 128 128 } 129 *out_duration_avg = nanos_sum / stopwatch_count;129 *out_duration_avg = nanos_sum / run_count; 130 130 double sigma2 = (nanos_sum2 - nanos_sum * (*out_duration_avg)) / 131 ((double) stopwatch_count - 1);131 ((double) run_count - 1); 132 132 // FIXME: implement sqrt properly 133 133 *out_duration_sigma = estimate_square_root(sigma2, precision); 134 *out_thruput_avg = 1.0 / (inv_thruput_sum / stopwatch_count);135 } 136 137 static void summary_stats(bench meter_t *meter, size_t meter_count,134 *out_thruput_avg = 1.0 / (inv_thruput_sum / run_count); 135 } 136 137 static void summary_stats(bench_run_t *runs, size_t run_count, 138 138 benchmark_t *bench, uint64_t workload_size) 139 139 { 140 140 double duration_avg, duration_sigma, thruput_avg; 141 compute_stats( meter, meter_count, workload_size, 0.001,141 compute_stats(runs, run_count, workload_size, 0.001, 142 142 &duration_avg, &duration_sigma, &thruput_avg); 143 143 … … 145 145 "%.0f ops/s; Samples: %zu\n", 146 146 workload_size, duration_avg / 1000.0, duration_sigma / 1000.0, 147 thruput_avg * 1000000000.0, meter_count);147 thruput_avg * 1000000000.0, run_count); 148 148 } 149 149 … … 152 152 printf("Warm up and determine workload size...\n"); 153 153 154 /* 155 * We share this buffer across all runs as we know that it is 156 * used only on failure (and we abort after first error). 157 */ 154 158 char *error_msg = malloc(MAX_ERROR_STR_LENGTH + 1); 155 159 if (error_msg == NULL) { … … 159 163 str_cpy(error_msg, MAX_ERROR_STR_LENGTH, ""); 160 164 165 bench_run_t helper_run; 166 bench_run_init(&helper_run, error_msg, MAX_ERROR_STR_LENGTH); 167 161 168 bool ret = true; 162 169 163 170 if (bench->setup != NULL) { 164 ret = bench->setup( error_msg, MAX_ERROR_STR_LENGTH);171 ret = bench->setup(&helper_run); 165 172 if (!ret) { 166 173 goto leave_error; … … 180 187 workload_size = ((uint64_t) 1) << bits; 181 188 182 benchmeter_t meter; 183 benchmeter_init(&meter); 184 185 bool ok = bench->entry(&meter, workload_size, 186 error_msg, MAX_ERROR_STR_LENGTH); 189 bench_run_t run; 190 bench_run_init(&run, error_msg, MAX_ERROR_STR_LENGTH); 191 192 bool ok = bench->entry(&run, workload_size); 187 193 if (!ok) { 188 194 goto leave_error; 189 195 } 190 short_report(& meter, -1, bench, workload_size);191 192 nsec_t duration = stopwatch_get_nanos(& meter.stopwatch);196 short_report(&run, -1, bench, workload_size); 197 198 nsec_t duration = stopwatch_get_nanos(&run.stopwatch); 193 199 if (duration > SEC2NSEC(MIN_DURATION_SECS)) { 194 200 break; … … 198 204 printf("Workload size set to %" PRIu64 ", measuring %d samples.\n", workload_size, NUM_SAMPLES); 199 205 200 bench meter_t *meter = calloc(NUM_SAMPLES, sizeof(benchmeter_t));201 if ( meter== NULL) {206 bench_run_t *runs = calloc(NUM_SAMPLES, sizeof(bench_run_t)); 207 if (runs == NULL) { 202 208 snprintf(error_msg, MAX_ERROR_STR_LENGTH, "failed allocating memory"); 203 209 goto leave_error; 204 210 } 205 211 for (int i = 0; i < NUM_SAMPLES; i++) { 206 benchmeter_init(&meter[i]); 207 208 bool ok = bench->entry(&meter[i], workload_size, 209 error_msg, MAX_ERROR_STR_LENGTH); 212 bench_run_init(&runs[i], error_msg, MAX_ERROR_STR_LENGTH); 213 214 bool ok = bench->entry(&runs[i], workload_size); 210 215 if (!ok) { 211 free( meter);216 free(runs); 212 217 goto leave_error; 213 218 } 214 short_report(& meter[i], i, bench, workload_size);215 } 216 217 summary_stats( meter, NUM_SAMPLES, bench, workload_size);219 short_report(&runs[i], i, bench, workload_size); 220 } 221 222 summary_stats(runs, NUM_SAMPLES, bench, workload_size); 218 223 printf("\nBenchmark completed\n"); 219 224 220 free( meter);225 free(runs); 221 226 222 227 goto leave; … … 228 233 leave: 229 234 if (bench->teardown != NULL) { 230 bool ok = bench->teardown( error_msg, MAX_ERROR_STR_LENGTH);235 bool ok = bench->teardown(&helper_run); 231 236 if (!ok) { 232 237 printf("Error: %s\n", error_msg); -
uspace/app/hbench/malloc/malloc1.c
r94ebebf re7f9a09 36 36 #include "../hbench.h" 37 37 38 static bool runner(benchmeter_t *meter, uint64_t size, 39 char *error, size_t error_size) 38 static bool runner(bench_run_t *run, uint64_t size) 40 39 { 41 bench meter_start(meter);40 bench_run_start(run); 42 41 for (uint64_t i = 0; i < size; i++) { 43 42 void *p = malloc(1); 44 43 if (p == NULL) { 45 snprintf(error, error_size,44 return bench_run_fail(run, 46 45 "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")", 47 46 i, size); 48 return false;49 47 } 50 48 free(p); 51 49 } 52 bench meter_stop(meter);50 bench_run_stop(run); 53 51 54 52 return true; -
uspace/app/hbench/malloc/malloc2.c
r94ebebf re7f9a09 35 35 #include "../hbench.h" 36 36 37 static bool runner(benchmeter_t *meter, uint64_t niter, 38 char *error, size_t error_size) 37 static bool runner(bench_run_t *run, uint64_t niter) 39 38 { 40 bench meter_start(meter);39 bench_run_start(run); 41 40 42 41 void **p = malloc(niter * sizeof(void *)); 43 42 if (p == NULL) { 44 snprintf(error, error_size, 45 "failed to allocate backend array (%" PRIu64 "B)", 43 return bench_run_fail(run, "failed to allocate backend array (%" PRIu64 "B)", 46 44 niter * sizeof(void *)); 47 return false;48 45 } 49 46 … … 51 48 p[count] = malloc(1); 52 49 if (p[count] == NULL) { 53 snprintf(error, error_size,54 "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")",55 count, niter);56 50 for (uint64_t j = 0; j < count; j++) { 57 51 free(p[j]); 58 52 } 59 53 free(p); 60 return false; 54 return bench_run_fail(run, 55 "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")", 56 count, niter); 61 57 } 62 58 } … … 67 63 free(p); 68 64 69 bench meter_stop(meter);65 bench_run_stop(run); 70 66 71 67 return true; -
uspace/app/hbench/synch/fibril_mutex.c
r94ebebf re7f9a09 65 65 } 66 66 67 static bool runner(benchmeter_t *meter, uint64_t size, 68 char *error, size_t error_size) 67 static bool runner(bench_run_t *run, uint64_t size) 69 68 { 70 69 shared_t shared; … … 76 75 fibril_add_ready(other); 77 76 78 bench meter_start(meter);77 bench_run_start(run); 79 78 for (uint64_t i = 0; i < size; i++) { 80 79 fibril_mutex_lock(&shared.mutex); … … 82 81 fibril_mutex_unlock(&shared.mutex); 83 82 } 84 bench meter_stop(meter);83 bench_run_stop(run); 85 84 86 85 while (!atomic_load(&shared.done)) {
Note:
See TracChangeset
for help on using the changeset viewer.