Changes in / [7acd787:b9f1585] in mainline
- Location:
- uspace
- Files:
-
- 6 added
- 4 deleted
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/perf/Makefile
r7acd787 rb9f1585 34 34 35 35 SOURCES = \ 36 benchlist.c \ 36 37 perf.c \ 37 38 ipc/ns_ping.c \ -
uspace/app/perf/ipc/ns_ping.c
r7acd787 rb9f1585 27 27 */ 28 28 29 #include <math.h>30 29 #include <stdio.h> 31 #include <stdlib.h>32 #include <time.h>33 30 #include <ns.h> 34 31 #include <async.h> 35 32 #include <errno.h> 33 #include <str_error.h> 34 #include "../benchlist.h" 36 35 #include "../perf.h" 37 36 38 #define MIN_DURATION_SECS 10 39 #define NUM_SAMPLES 10 37 static bool runner(stopwatch_t *stopwatch, uint64_t niter, 38 char *error, size_t error_size) 39 { 40 stopwatch_start(stopwatch); 40 41 41 static errno_t ping_pong_measure(uint64_t niter, uint64_t *rduration) 42 { 43 struct timespec start; 44 uint64_t count; 42 for (uint64_t count = 0; count < niter; count++) { 43 errno_t rc = ns_ping(); 45 44 46 getuptime(&start); 47 48 for (count = 0; count < niter; count++) { 49 errno_t retval = ns_ping(); 50 51 if (retval != EOK) { 52 printf("Error sending ping message.\n"); 53 return EIO; 45 if (rc != EOK) { 46 snprintf(error, error_size, 47 "failed sending ping message: %s (%d)", 48 str_error(rc), rc); 49 return false; 54 50 } 55 51 } 56 52 57 struct timespec now; 58 getuptime(&now); 53 stopwatch_stop(stopwatch); 59 54 60 *rduration = ts_sub_diff(&now, &start) / 1000; 61 return EOK; 55 return true; 62 56 } 63 57 64 static void ping_pong_report(uint64_t niter, uint64_t duration) 65 { 66 printf("Completed %" PRIu64 " round trips in %" PRIu64 " us", 67 niter, duration); 68 69 if (duration > 0) { 70 printf(", %" PRIu64 " rt/s.\n", niter * 1000 * 1000 / duration); 71 } else { 72 printf(".\n"); 73 } 74 } 75 76 const char *bench_ns_ping(void) 77 { 78 errno_t rc; 79 uint64_t duration; 80 uint64_t dsmp[NUM_SAMPLES]; 81 82 printf("Warm up and determine work size...\n"); 83 84 struct timespec start; 85 getuptime(&start); 86 87 uint64_t niter = 1; 88 89 while (true) { 90 rc = ping_pong_measure(niter, &duration); 91 if (rc != EOK) 92 return "Failed."; 93 94 ping_pong_report(niter, duration); 95 96 if (duration >= MIN_DURATION_SECS * 1000000) 97 break; 98 99 niter *= 2; 100 } 101 102 printf("Measure %d samples...\n", NUM_SAMPLES); 103 104 int i; 105 106 for (i = 0; i < NUM_SAMPLES; i++) { 107 rc = ping_pong_measure(niter, &dsmp[i]); 108 if (rc != EOK) 109 return "Failed."; 110 111 ping_pong_report(niter, dsmp[i]); 112 } 113 114 double sum = 0.0; 115 116 for (i = 0; i < NUM_SAMPLES; i++) 117 sum += (double)niter / ((double)dsmp[i] / 1000000.0l); 118 119 double avg = sum / NUM_SAMPLES; 120 121 double qd = 0.0; 122 double d; 123 for (i = 0; i < NUM_SAMPLES; i++) { 124 d = (double)niter / ((double)dsmp[i] / 1000000.0l) - avg; 125 qd += d * d; 126 } 127 128 double stddev = qd / (NUM_SAMPLES - 1); // XXX sqrt 129 130 printf("Average: %.0f rt/s Std.dev^2: %.0f rt/s Samples: %d\n", 131 avg, stddev, NUM_SAMPLES); 132 133 return NULL; 134 } 58 benchmark_t bench_ns_ping = { 59 .name = "ns_ping", 60 .desc = "Name service IPC ping-pong benchmark", 61 .entry = &runner, 62 .setup = NULL, 63 .teardown = NULL 64 }; -
uspace/app/perf/ipc/ping_pong.c
r7acd787 rb9f1585 27 27 */ 28 28 29 #include <math.h>30 29 #include <stdio.h> 31 #include <stdlib.h>32 #include <time.h>33 30 #include <ipc_test.h> 34 31 #include <async.h> 35 32 #include <errno.h> 33 #include <str_error.h> 34 #include "../benchlist.h" 36 35 #include "../perf.h" 37 36 38 #define MIN_DURATION_SECS 10 39 #define NUM_SAMPLES 10 37 static ipc_test_t *test = NULL; 40 38 41 static errno_t ping_pong_measure(ipc_test_t *test, uint64_t niter, 42 uint64_t *rduration) 39 static bool setup(char *error, size_t error_size) 43 40 { 44 struct timespec start; 45 uint64_t count; 41 errno_t rc = ipc_test_create(&test); 42 if (rc != EOK) { 43 snprintf(error, error_size, 44 "failed contacting IPC test server: %s (%d)", 45 str_error(rc), rc); 46 return false; 47 } 46 48 47 getuptime(&start); 49 return true; 50 } 48 51 49 for (count = 0; count < niter; count++) { 50 errno_t retval = ipc_test_ping(test); 52 static bool teardown(char *error, size_t error_size) 53 { 54 ipc_test_destroy(test); 55 return true; 56 } 51 57 52 if (retval != EOK) { 53 printf("Error sending ping message.\n"); 54 return EIO; 58 static bool runner(stopwatch_t *stopwatch, uint64_t niter, 59 char *error, size_t error_size) 60 { 61 stopwatch_start(stopwatch); 62 63 for (uint64_t count = 0; count < niter; count++) { 64 errno_t rc = ipc_test_ping(test); 65 66 if (rc != EOK) { 67 snprintf(error, error_size, 68 "failed sending ping message: %s (%d)", 69 str_error(rc), rc); 70 return false; 55 71 } 56 72 } 57 73 58 struct timespec now; 59 getuptime(&now); 74 stopwatch_stop(stopwatch); 60 75 61 *rduration = ts_sub_diff(&now, &start) / 1000; 62 return EOK; 76 return true; 63 77 } 64 78 65 static void ping_pong_report(uint64_t niter, uint64_t duration) 66 { 67 printf("Completed %" PRIu64 " round trips in %" PRIu64 " us", 68 niter, duration); 69 70 if (duration > 0) { 71 printf(", %" PRIu64 " rt/s.\n", niter * 1000 * 1000 / duration); 72 } else { 73 printf(".\n"); 74 } 75 } 76 77 const char *bench_ping_pong(void) 78 { 79 errno_t rc; 80 uint64_t duration; 81 uint64_t dsmp[NUM_SAMPLES]; 82 ipc_test_t *test; 83 const char *msg; 84 85 rc = ipc_test_create(&test); 86 if (rc != EOK) 87 return "Failed contacting IPC test server."; 88 89 printf("Warm up and determine work size...\n"); 90 91 struct timespec start; 92 getuptime(&start); 93 94 uint64_t niter = 1; 95 96 while (true) { 97 rc = ping_pong_measure(test, niter, &duration); 98 if (rc != EOK) { 99 msg = "Failed."; 100 goto error; 101 } 102 103 ping_pong_report(niter, duration); 104 105 if (duration >= MIN_DURATION_SECS * 1000000) 106 break; 107 108 niter *= 2; 109 } 110 111 printf("Measure %d samples...\n", NUM_SAMPLES); 112 113 int i; 114 115 for (i = 0; i < NUM_SAMPLES; i++) { 116 rc = ping_pong_measure(test, niter, &dsmp[i]); 117 if (rc != EOK) { 118 msg = "Failed."; 119 goto error; 120 } 121 122 ping_pong_report(niter, dsmp[i]); 123 } 124 125 double sum = 0.0; 126 127 for (i = 0; i < NUM_SAMPLES; i++) 128 sum += (double)niter / ((double)dsmp[i] / 1000000.0l); 129 130 double avg = sum / NUM_SAMPLES; 131 132 double qd = 0.0; 133 double d; 134 for (i = 0; i < NUM_SAMPLES; i++) { 135 d = (double)niter / ((double)dsmp[i] / 1000000.0l) - avg; 136 qd += d * d; 137 } 138 139 double stddev = qd / (NUM_SAMPLES - 1); // XXX sqrt 140 141 printf("Average: %.0f rt/s Std.dev^2: %.0f rt/s Samples: %d\n", 142 avg, stddev, NUM_SAMPLES); 143 144 ipc_test_destroy(test); 145 return NULL; 146 error: 147 ipc_test_destroy(test); 148 return msg; 149 } 79 benchmark_t bench_ping_pong = { 80 .name = "ping_pong", 81 .desc = "IPC ping-pong benchmark", 82 .entry = &runner, 83 .setup = &setup, 84 .teardown = &teardown 85 }; -
uspace/app/perf/malloc/malloc1.c
r7acd787 rb9f1585 30 30 #include <stdio.h> 31 31 #include <stdlib.h> 32 #include <time.h> 33 #include <errno.h> 32 #include "../benchlist.h" 34 33 #include "../perf.h" 35 34 36 #define MIN_DURATION_SECS 10 37 #define NUM_SAMPLES 10 38 39 static errno_t malloc1_measure(uint64_t niter, uint64_t *rduration) 35 static bool runner(stopwatch_t *stopwatch, uint64_t size, 36 char *error, size_t error_size) 40 37 { 41 struct timespec start; 42 uint64_t count; 43 void *p; 44 45 getuptime(&start); 46 47 for (count = 0; count < niter; count++) { 48 p = malloc(1); 49 if (p == NULL) 50 return ENOMEM; 38 stopwatch_start(stopwatch); 39 for (uint64_t i = 0; i < size; i++) { 40 void *p = malloc(1); 41 if (p == NULL) { 42 snprintf(error, error_size, 43 "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")", 44 i, size); 45 return false; 46 } 51 47 free(p); 52 48 } 49 stopwatch_stop(stopwatch); 53 50 54 struct timespec now; 55 getuptime(&now); 56 57 *rduration = ts_sub_diff(&now, &start) / 1000; 58 return EOK; 51 return true; 59 52 } 60 53 61 static void malloc1_report(uint64_t niter, uint64_t duration) 62 { 63 printf("Completed %" PRIu64 " allocations and deallocations in %" PRIu64 " us", 64 niter, duration); 65 66 if (duration > 0) { 67 printf(", %" PRIu64 " cycles/s.\n", niter * 1000 * 1000 / duration); 68 } else { 69 printf(".\n"); 70 } 71 } 72 73 const char *bench_malloc1(void) 74 { 75 errno_t rc; 76 uint64_t duration; 77 uint64_t dsmp[NUM_SAMPLES]; 78 const char *msg; 79 80 printf("Warm up and determine work size...\n"); 81 82 struct timespec start; 83 getuptime(&start); 84 85 uint64_t niter = 1; 86 87 while (true) { 88 rc = malloc1_measure(niter, &duration); 89 if (rc != EOK) { 90 msg = "Failed."; 91 goto error; 92 } 93 94 malloc1_report(niter, duration); 95 96 if (duration >= MIN_DURATION_SECS * 1000000) 97 break; 98 99 niter *= 2; 100 } 101 102 printf("Measure %d samples...\n", NUM_SAMPLES); 103 104 int i; 105 106 for (i = 0; i < NUM_SAMPLES; i++) { 107 rc = malloc1_measure(niter, &dsmp[i]); 108 if (rc != EOK) { 109 msg = "Failed."; 110 goto error; 111 } 112 113 malloc1_report(niter, dsmp[i]); 114 } 115 116 double sum = 0.0; 117 118 for (i = 0; i < NUM_SAMPLES; i++) 119 sum += (double)niter / ((double)dsmp[i] / 1000000.0l); 120 121 double avg = sum / NUM_SAMPLES; 122 123 double qd = 0.0; 124 double d; 125 for (i = 0; i < NUM_SAMPLES; i++) { 126 d = (double)niter / ((double)dsmp[i] / 1000000.0l) - avg; 127 qd += d * d; 128 } 129 130 double stddev = qd / (NUM_SAMPLES - 1); // XXX sqrt 131 132 printf("Average: %.0f cycles/s Std.dev^2: %.0f cycles/s Samples: %d\n", 133 avg, stddev, NUM_SAMPLES); 134 135 return NULL; 136 error: 137 return msg; 138 } 54 benchmark_t bench_malloc1 = { 55 .name = "malloc1", 56 .desc = "User-space memory allocator benchmark, repeatedly allocate one block", 57 .entry = &runner, 58 .setup = NULL, 59 .teardown = NULL 60 }; -
uspace/app/perf/malloc/malloc2.c
r7acd787 rb9f1585 27 27 */ 28 28 29 #include < math.h>29 #include <stdlib.h> 30 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <time.h> 33 #include <errno.h> 31 #include "../benchlist.h" 34 32 #include "../perf.h" 35 33 36 #define MIN_DURATION_SECS 10 37 #define NUM_SAMPLES 10 34 static bool runner(stopwatch_t *stopwatch, uint64_t niter, 35 char *error, size_t error_size) 36 { 37 stopwatch_start(stopwatch); 38 38 39 static errno_t malloc2_measure(uint64_t niter, uint64_t *rduration) 40 { 41 struct timespec start; 42 uint64_t count; 43 void **p; 44 45 getuptime(&start); 46 47 p = malloc(niter * sizeof(void *)); 48 if (p == NULL) 49 return ENOMEM; 50 51 for (count = 0; count < niter; count++) { 52 p[count] = malloc(1); 53 if (p[count] == NULL) 54 return ENOMEM; 39 void **p = malloc(niter * sizeof(void *)); 40 if (p == NULL) { 41 snprintf(error, error_size, 42 "failed to allocate backend array (%" PRIu64 "B)", 43 niter * sizeof(void *)); 44 return false; 55 45 } 56 46 57 for (count = 0; count < niter; count++) 47 for (uint64_t count = 0; count < niter; count++) { 48 p[count] = malloc(1); 49 if (p[count] == NULL) { 50 snprintf(error, error_size, 51 "failed to allocate 1B in run %" PRIu64 " (out of %" PRIu64 ")", 52 count, niter); 53 for (uint64_t j = 0; j < count; j++) { 54 free(p[j]); 55 } 56 free(p); 57 return false; 58 } 59 } 60 61 for (uint64_t count = 0; count < niter; count++) 58 62 free(p[count]); 59 63 60 64 free(p); 61 65 62 struct timespec now; 63 getuptime(&now); 66 stopwatch_stop(stopwatch); 64 67 65 *rduration = ts_sub_diff(&now, &start) / 1000; 66 return EOK; 68 return true; 67 69 } 68 70 69 static void malloc2_report(uint64_t niter, uint64_t duration) 70 { 71 printf("Completed %" PRIu64 " allocations and deallocations in %" PRIu64 " us", 72 niter, duration); 73 74 if (duration > 0) { 75 printf(", %" PRIu64 " cycles/s.\n", niter * 1000 * 1000 / duration); 76 } else { 77 printf(".\n"); 78 } 79 } 80 81 const char *bench_malloc2(void) 82 { 83 errno_t rc; 84 uint64_t duration; 85 uint64_t dsmp[NUM_SAMPLES]; 86 const char *msg; 87 88 printf("Warm up and determine work size...\n"); 89 90 struct timespec start; 91 getuptime(&start); 92 93 uint64_t niter = 1; 94 95 while (true) { 96 rc = malloc2_measure(niter, &duration); 97 if (rc != EOK) { 98 msg = "Failed."; 99 goto error; 100 } 101 102 malloc2_report(niter, duration); 103 104 if (duration >= MIN_DURATION_SECS * 1000000) 105 break; 106 107 niter *= 2; 108 } 109 110 printf("Measure %d samples...\n", NUM_SAMPLES); 111 112 int i; 113 114 for (i = 0; i < NUM_SAMPLES; i++) { 115 rc = malloc2_measure(niter, &dsmp[i]); 116 if (rc != EOK) { 117 msg = "Failed."; 118 goto error; 119 } 120 121 malloc2_report(niter, dsmp[i]); 122 } 123 124 double sum = 0.0; 125 126 for (i = 0; i < NUM_SAMPLES; i++) 127 sum += (double)niter / ((double)dsmp[i] / 1000000.0l); 128 129 double avg = sum / NUM_SAMPLES; 130 131 double qd = 0.0; 132 double d; 133 for (i = 0; i < NUM_SAMPLES; i++) { 134 d = (double)niter / ((double)dsmp[i] / 1000000.0l) - avg; 135 qd += d * d; 136 } 137 138 double stddev = qd / (NUM_SAMPLES - 1); // XXX sqrt 139 140 printf("Average: %.0f cycles/s Std.dev^2: %.0f cycles/s Samples: %d\n", 141 avg, stddev, NUM_SAMPLES); 142 143 return NULL; 144 error: 145 return msg; 146 } 71 benchmark_t bench_malloc2 = { 72 .name = "malloc2", 73 .desc = "User-space memory allocator benchmark, allocate many small blocks", 74 .entry = &runner, 75 .setup = NULL, 76 .teardown = NULL 77 }; -
uspace/app/perf/perf.c
r7acd787 rb9f1585 1 1 /* 2 2 * Copyright (c) 2018 Jiri Svoboda 3 * Copyright (c) 2018 Vojtech Horky 3 4 * All rights reserved. 4 5 * … … 34 35 */ 35 36 37 #include <assert.h> 38 #include <math.h> 36 39 #include <stdio.h> 37 40 #include <stddef.h> 38 41 #include <stdlib.h> 39 42 #include <str.h> 43 #include <time.h> 44 #include <errno.h> 45 #include <perf.h> 46 #include <types/casting.h> 40 47 #include "perf.h" 41 42 benchmark_t benchmarks[] = { 43 #include "ipc/ns_ping.def" 44 #include "ipc/ping_pong.def" 45 #include "malloc/malloc1.def" 46 #include "malloc/malloc2.def" 47 { NULL, NULL, NULL } 48 }; 48 #include "benchlist.h" 49 50 #define MIN_DURATION_SECS 10 51 #define NUM_SAMPLES 10 52 #define MAX_ERROR_STR_LENGTH 1024 53 54 static void short_report(stopwatch_t *stopwatch, int run_index, 55 benchmark_t *bench, uint64_t workload_size) 56 { 57 usec_t duration_usec = NSEC2USEC(stopwatch_get_nanos(stopwatch)); 58 59 printf("Completed %" PRIu64 " operations in %llu us", 60 workload_size, duration_usec); 61 if (duration_usec > 0) { 62 double nanos = stopwatch_get_nanos(stopwatch); 63 double thruput = (double) workload_size / (nanos / 1000000000.0l); 64 printf(", %.0f ops/s.\n", thruput); 65 } else { 66 printf(".\n"); 67 } 68 } 69 70 /* 71 * This is a temporary solution until we have proper sqrt() implementation 72 * in libmath. 73 * 74 * The algorithm uses Babylonian method [1]. 75 * 76 * [1] https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method 77 */ 78 static double estimate_square_root(double value, double precision) 79 { 80 double estimate = 1.; 81 double prev_estimate = estimate + 10 * precision; 82 83 while (fabs(estimate - prev_estimate) > precision) { 84 prev_estimate = estimate; 85 estimate = (prev_estimate + value / prev_estimate) / 2.; 86 } 87 88 return estimate; 89 } 90 91 /* 92 * Compute available statistics from given stopwatches. 93 * 94 * We compute normal mean for average duration of the workload and geometric 95 * mean for average thruput. Note that geometric mean is necessary to compute 96 * average throughput correctly - consider the following example: 97 * - we run always 60 operations, 98 * - first run executes in 30 s (i.e. 2 ops/s) 99 * - and second one in 10 s (6 ops/s). 100 * Then, naively, average throughput would be (2+6)/2 = 4 [ops/s]. However, we 101 * actually executed 60 + 60 ops in 30 + 10 seconds. So the actual average 102 * throughput is 3 ops/s (which is exactly what geometric mean means). 103 * 104 */ 105 static void compute_stats(stopwatch_t *stopwatch, size_t stopwatch_count, 106 uint64_t workload_size, double precision, double *out_duration_avg, 107 double *out_duration_sigma, double *out_thruput_avg) 108 { 109 double inv_thruput_sum = 0.0; 110 double nanos_sum = 0.0; 111 double nanos_sum2 = 0.0; 112 113 for (size_t i = 0; i < stopwatch_count; i++) { 114 double nanos = stopwatch_get_nanos(&stopwatch[i]); 115 double thruput = (double) workload_size / nanos; 116 117 inv_thruput_sum += 1.0 / thruput; 118 nanos_sum += nanos; 119 nanos_sum2 += nanos * nanos; 120 } 121 *out_duration_avg = nanos_sum / stopwatch_count; 122 double sigma2 = (nanos_sum2 - nanos_sum * (*out_duration_avg)) / 123 ((double) stopwatch_count - 1); 124 // FIXME: implement sqrt properly 125 *out_duration_sigma = estimate_square_root(sigma2, precision); 126 *out_thruput_avg = 1.0 / (inv_thruput_sum / stopwatch_count); 127 } 128 129 static void summary_stats(stopwatch_t *stopwatch, size_t stopwatch_count, 130 benchmark_t *bench, uint64_t workload_size) 131 { 132 double duration_avg, duration_sigma, thruput_avg; 133 compute_stats(stopwatch, stopwatch_count, workload_size, 0.001, 134 &duration_avg, &duration_sigma, &thruput_avg); 135 136 printf("Average: %" PRIu64 " ops in %.0f us (sd %.0f us); " 137 "%.0f ops/s; Samples: %zu\n", 138 workload_size, duration_avg / 1000.0, duration_sigma / 1000.0, 139 thruput_avg * 1000000000.0, stopwatch_count); 140 } 49 141 50 142 static bool run_benchmark(benchmark_t *bench) 51 143 { 52 /* Execute the benchmarl */ 53 const char *ret = bench->entry(); 54 55 if (ret == NULL) { 56 printf("\nBenchmark completed\n"); 57 return true; 58 } 59 60 printf("\n%s\n", ret); 61 return false; 144 printf("Warm up and determine workload size...\n"); 145 146 char *error_msg = malloc(MAX_ERROR_STR_LENGTH + 1); 147 if (error_msg == NULL) { 148 printf("Out of memory!\n"); 149 return false; 150 } 151 str_cpy(error_msg, MAX_ERROR_STR_LENGTH, ""); 152 153 bool ret = true; 154 155 if (bench->setup != NULL) { 156 ret = bench->setup(error_msg, MAX_ERROR_STR_LENGTH); 157 if (!ret) { 158 goto leave_error; 159 } 160 } 161 162 /* 163 * Find workload size that is big enough to last few seconds. 164 * We also check that uint64_t is big enough. 165 */ 166 uint64_t workload_size = 0; 167 for (size_t bits = 0; bits <= 64; bits++) { 168 if (bits == 64) { 169 str_cpy(error_msg, MAX_ERROR_STR_LENGTH, "Workload too small even for 1 << 63"); 170 goto leave_error; 171 } 172 workload_size = ((uint64_t) 1) << bits; 173 174 stopwatch_t stopwatch = STOPWATCH_INITIALIZE_STATIC; 175 176 bool ok = bench->entry(&stopwatch, workload_size, 177 error_msg, MAX_ERROR_STR_LENGTH); 178 if (!ok) { 179 goto leave_error; 180 } 181 short_report(&stopwatch, -1, bench, workload_size); 182 183 nsec_t duration = stopwatch_get_nanos(&stopwatch); 184 if (duration > SEC2NSEC(MIN_DURATION_SECS)) { 185 break; 186 } 187 } 188 189 printf("Workload size set to %" PRIu64 ", measuring %d samples.\n", workload_size, NUM_SAMPLES); 190 191 stopwatch_t *stopwatch = calloc(NUM_SAMPLES, sizeof(stopwatch_t)); 192 if (stopwatch == NULL) { 193 snprintf(error_msg, MAX_ERROR_STR_LENGTH, "failed allocating memory"); 194 goto leave_error; 195 } 196 for (int i = 0; i < NUM_SAMPLES; i++) { 197 stopwatch_init(&stopwatch[i]); 198 199 bool ok = bench->entry(&stopwatch[i], workload_size, 200 error_msg, MAX_ERROR_STR_LENGTH); 201 if (!ok) { 202 free(stopwatch); 203 goto leave_error; 204 } 205 short_report(&stopwatch[i], i, bench, workload_size); 206 } 207 208 summary_stats(stopwatch, NUM_SAMPLES, bench, workload_size); 209 printf("\nBenchmark completed\n"); 210 211 free(stopwatch); 212 213 goto leave; 214 215 leave_error: 216 printf("Error: %s\n", error_msg); 217 ret = false; 218 219 leave: 220 if (bench->teardown != NULL) { 221 bool ok = bench->teardown(error_msg, MAX_ERROR_STR_LENGTH); 222 if (!ok) { 223 printf("Error: %s\n", error_msg); 224 ret = false; 225 } 226 } 227 228 free(error_msg); 229 230 return ret; 62 231 } 63 232 64 233 static int run_benchmarks(void) 65 234 { 66 benchmark_t *bench; 67 unsigned int i = 0; 68 unsigned int n = 0; 235 unsigned int count_ok = 0; 236 unsigned int count_fail = 0; 69 237 70 238 char *failed_names = NULL; … … 72 240 printf("\n*** Running all benchmarks ***\n\n"); 73 241 74 for ( bench = benchmarks; bench->name != NULL; bench++) {75 printf("%s (%s)\n", bench ->name, bench->desc);76 if (run_benchmark(bench )) {77 i++;242 for (size_t it = 0; it < benchmark_count; it++) { 243 printf("%s (%s)\n", benchmarks[it]->name, benchmarks[it]->desc); 244 if (run_benchmark(benchmarks[it])) { 245 count_ok++; 78 246 continue; 79 247 } 80 248 81 249 if (!failed_names) { 82 failed_names = str_dup(bench ->name);250 failed_names = str_dup(benchmarks[it]->name); 83 251 } else { 84 252 char *f = NULL; 85 asprintf(&f, "%s, %s", failed_names, bench ->name);253 asprintf(&f, "%s, %s", failed_names, benchmarks[it]->name); 86 254 if (!f) { 87 255 printf("Out of memory.\n"); … … 91 259 failed_names = f; 92 260 } 93 n++; 94 } 95 96 printf("\nCompleted, %u benchmarks run, %u succeeded.\n", i + n, i); 261 count_fail++; 262 } 263 264 printf("\nCompleted, %u benchmarks run, %u succeeded.\n", 265 count_ok + count_fail, count_ok); 97 266 if (failed_names) 98 267 printf("Failed benchmarks: %s\n", failed_names); 99 268 100 return n;269 return count_fail; 101 270 } 102 271 … … 104 273 { 105 274 size_t len = 0; 106 benchmark_t *bench; 107 for (bench = benchmarks; bench->name != NULL; bench++) { 108 if (str_length(bench->name) > len) 109 len = str_length(bench->name); 110 } 111 112 unsigned int _len = (unsigned int) len; 113 if ((_len != len) || (((int) _len) < 0)) { 114 printf("Command length overflow\n"); 115 return; 116 } 117 118 for (bench = benchmarks; bench->name != NULL; bench++) 119 printf("%-*s %s\n", _len, bench->name, bench->desc); 120 121 printf("%-*s Run all benchmarks\n", _len, "*"); 275 for (size_t i = 0; i < benchmark_count; i++) { 276 size_t len_now = str_length(benchmarks[i]->name); 277 if (len_now > len) 278 len = len_now; 279 } 280 281 assert(can_cast_size_t_to_int(len) && "benchmark name length overflow"); 282 283 for (size_t i = 0; i < benchmark_count; i++) 284 printf("%-*s %s\n", (int) len, benchmarks[i]->name, benchmarks[i]->desc); 285 286 printf("%-*s Run all benchmarks\n", (int) len, "*"); 122 287 } 123 288 … … 135 300 } 136 301 137 benchmark_t *bench; 138 for (bench = benchmarks; bench->name != NULL; bench++) { 139 if (str_cmp(argv[1], bench->name) == 0) { 140 return (run_benchmark(bench) ? 0 : -1); 302 for (size_t i = 0; i < benchmark_count; i++) { 303 if (str_cmp(argv[1], benchmarks[i]->name) == 0) { 304 return (run_benchmark(benchmarks[i]) ? 0 : -1); 141 305 } 142 306 } -
uspace/app/perf/perf.h
r7acd787 rb9f1585 37 37 38 38 #include <stdbool.h> 39 #include <perf.h> 39 40 40 typedef const char *(*benchmark_entry_t)(void); 41 typedef bool (*benchmark_entry_t)(stopwatch_t *, uint64_t, 42 char *, size_t); 43 typedef bool (*benchmark_helper_t)(char *, size_t); 41 44 42 45 typedef struct { … … 44 47 const char *desc; 45 48 benchmark_entry_t entry; 49 benchmark_helper_t setup; 50 benchmark_helper_t teardown; 46 51 } benchmark_t; 47 48 extern const char *bench_malloc1(void);49 extern const char *bench_malloc2(void);50 extern const char *bench_ns_ping(void);51 extern const char *bench_ping_pong(void);52 53 extern benchmark_t benchmarks[];54 52 55 53 #endif -
uspace/app/tester/tester.c
r7acd787 rb9f1585 35 35 */ 36 36 37 #include <assert.h> 37 38 #include <stdio.h> 38 39 #include <stddef.h> … … 40 41 #include <str.h> 41 42 #include <io/log.h> 43 #include <types/casting.h> 42 44 #include "tester.h" 43 45 … … 144 146 } 145 147 146 unsigned int _len = (unsigned int) len; 147 if ((_len != len) || (((int) _len) < 0)) { 148 printf("Command length overflow\n"); 149 return; 150 } 148 assert(can_cast_size_t_to_int(len) && "test name length overflow"); 151 149 152 150 for (test = tests; test->name != NULL; test++) 153 printf("%-*s %s%s\n", _len, test->name, test->desc,151 printf("%-*s %s%s\n", (int) len, test->name, test->desc, 154 152 (test->safe ? "" : " (unsafe)")); 155 153 156 printf("%-*s Run all safe tests\n", _len, "*");154 printf("%-*s Run all safe tests\n", (int) len, "*"); 157 155 } 158 156 -
uspace/lib/c/Makefile
r7acd787 rb9f1585 189 189 TEST_SOURCES = \ 190 190 test/adt/circ_buf.c \ 191 test/casting.c \ 191 192 test/fibril/timer.c \ 192 193 test/main.c \ … … 196 197 test/stdio/scanf.c \ 197 198 test/odict.c \ 199 test/perf.c \ 198 200 test/perm.c \ 199 201 test/qsort.c \ -
uspace/lib/c/test/main.c
r7acd787 rb9f1585 32 32 PCUT_INIT; 33 33 34 PCUT_IMPORT(casting); 34 35 PCUT_IMPORT(circ_buf); 35 36 PCUT_IMPORT(fibril_timer); … … 37 38 PCUT_IMPORT(mem); 38 39 PCUT_IMPORT(odict); 40 PCUT_IMPORT(perf); 39 41 PCUT_IMPORT(perm); 40 42 PCUT_IMPORT(qsort);
Note:
See TracChangeset
for help on using the changeset viewer.