Changes in / [b9f1585:7acd787] in mainline
- Location:
- uspace
- Files:
-
- 4 added
- 6 deleted
- 10 edited
-
app/perf/Makefile (modified) (1 diff)
-
app/perf/benchlist.c (deleted)
-
app/perf/benchlist.h (deleted)
-
app/perf/ipc/ns_ping.c (modified) (1 diff)
-
app/perf/ipc/ns_ping.def (added)
-
app/perf/ipc/ping_pong.c (modified) (1 diff)
-
app/perf/ipc/ping_pong.def (added)
-
app/perf/malloc/malloc1.c (modified) (1 diff)
-
app/perf/malloc/malloc1.def (added)
-
app/perf/malloc/malloc2.c (modified) (1 diff)
-
app/perf/malloc/malloc2.def (added)
-
app/perf/perf.c (modified) (6 diffs)
-
app/perf/perf.h (modified) (2 diffs)
-
app/tester/tester.c (modified) (3 diffs)
-
lib/c/Makefile (modified) (2 diffs)
-
lib/c/include/perf.h (deleted)
-
lib/c/include/types/casting.h (deleted)
-
lib/c/test/casting.c (deleted)
-
lib/c/test/main.c (modified) (2 diffs)
-
lib/c/test/perf.c (deleted)
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/perf/Makefile
rb9f1585 r7acd787 34 34 35 35 SOURCES = \ 36 benchlist.c \37 36 perf.c \ 38 37 ipc/ns_ping.c \ -
uspace/app/perf/ipc/ns_ping.c
rb9f1585 r7acd787 27 27 */ 28 28 29 #include <math.h> 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <time.h> 30 33 #include <ns.h> 31 34 #include <async.h> 32 35 #include <errno.h> 33 #include <str_error.h>34 #include "../benchlist.h"35 36 #include "../perf.h" 36 37 37 static bool runner(stopwatch_t *stopwatch, uint64_t niter, 38 char *error, size_t error_size) 38 #define MIN_DURATION_SECS 10 39 #define NUM_SAMPLES 10 40 41 static errno_t ping_pong_measure(uint64_t niter, uint64_t *rduration) 39 42 { 40 stopwatch_start(stopwatch); 43 struct timespec start; 44 uint64_t count; 41 45 42 for (uint64_t count = 0; count < niter; count++) { 43 errno_t rc = ns_ping(); 46 getuptime(&start); 44 47 45 if (rc != EOK) { 46 snprintf(error, error_size, 47 "failed sending ping message: %s (%d)", 48 str_error(rc), rc); 49 return false; 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; 50 54 } 51 55 } 52 56 53 stopwatch_stop(stopwatch); 57 struct timespec now; 58 getuptime(&now); 54 59 55 return true; 60 *rduration = ts_sub_diff(&now, &start) / 1000; 61 return EOK; 56 62 } 57 63 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 }; 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 } -
uspace/app/perf/ipc/ping_pong.c
rb9f1585 r7acd787 27 27 */ 28 28 29 #include <math.h> 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <time.h> 30 33 #include <ipc_test.h> 31 34 #include <async.h> 32 35 #include <errno.h> 33 #include <str_error.h>34 #include "../benchlist.h"35 36 #include "../perf.h" 36 37 37 static ipc_test_t *test = NULL; 38 #define MIN_DURATION_SECS 10 39 #define NUM_SAMPLES 10 38 40 39 static bool setup(char *error, size_t error_size) 41 static errno_t ping_pong_measure(ipc_test_t *test, uint64_t niter, 42 uint64_t *rduration) 40 43 { 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 } 44 struct timespec start; 45 uint64_t count; 48 46 49 return true; 50 } 47 getuptime(&start); 51 48 52 static bool teardown(char *error, size_t error_size) 53 { 54 ipc_test_destroy(test); 55 return true; 56 } 49 for (count = 0; count < niter; count++) { 50 errno_t retval = ipc_test_ping(test); 57 51 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; 52 if (retval != EOK) { 53 printf("Error sending ping message.\n"); 54 return EIO; 71 55 } 72 56 } 73 57 74 stopwatch_stop(stopwatch); 58 struct timespec now; 59 getuptime(&now); 75 60 76 return true; 61 *rduration = ts_sub_diff(&now, &start) / 1000; 62 return EOK; 77 63 } 78 64 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 }; 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 } -
uspace/app/perf/malloc/malloc1.c
rb9f1585 r7acd787 30 30 #include <stdio.h> 31 31 #include <stdlib.h> 32 #include "../benchlist.h" 32 #include <time.h> 33 #include <errno.h> 33 34 #include "../perf.h" 34 35 35 static bool runner(stopwatch_t *stopwatch, uint64_t size, 36 char *error, size_t error_size) 36 #define MIN_DURATION_SECS 10 37 #define NUM_SAMPLES 10 38 39 static errno_t malloc1_measure(uint64_t niter, uint64_t *rduration) 37 40 { 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 } 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; 47 51 free(p); 48 52 } 49 stopwatch_stop(stopwatch);50 53 51 return true; 54 struct timespec now; 55 getuptime(&now); 56 57 *rduration = ts_sub_diff(&now, &start) / 1000; 58 return EOK; 52 59 } 53 60 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 }; 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 } -
uspace/app/perf/malloc/malloc2.c
rb9f1585 r7acd787 27 27 */ 28 28 29 #include <math.h> 30 #include <stdio.h> 29 31 #include <stdlib.h> 30 #include < stdio.h>31 #include "../benchlist.h"32 #include <time.h> 33 #include <errno.h> 32 34 #include "../perf.h" 33 35 34 static bool runner(stopwatch_t *stopwatch, uint64_t niter, 35 char *error, size_t error_size) 36 #define MIN_DURATION_SECS 10 37 #define NUM_SAMPLES 10 38 39 static errno_t malloc2_measure(uint64_t niter, uint64_t *rduration) 36 40 { 37 stopwatch_start(stopwatch); 41 struct timespec start; 42 uint64_t count; 43 void **p; 38 44 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; 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; 45 55 } 46 56 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++) 57 for (count = 0; count < niter; count++) 62 58 free(p[count]); 63 59 64 60 free(p); 65 61 66 stopwatch_stop(stopwatch); 62 struct timespec now; 63 getuptime(&now); 67 64 68 return true; 65 *rduration = ts_sub_diff(&now, &start) / 1000; 66 return EOK; 69 67 } 70 68 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 }; 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 } -
uspace/app/perf/perf.c
rb9f1585 r7acd787 1 1 /* 2 2 * Copyright (c) 2018 Jiri Svoboda 3 * Copyright (c) 2018 Vojtech Horky4 3 * All rights reserved. 5 4 * … … 35 34 */ 36 35 37 #include <assert.h>38 #include <math.h>39 36 #include <stdio.h> 40 37 #include <stddef.h> 41 38 #include <stdlib.h> 42 39 #include <str.h> 43 #include <time.h>44 #include <errno.h>45 #include <perf.h>46 #include <types/casting.h>47 40 #include "perf.h" 48 #include "benchlist.h"49 41 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 } 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 }; 141 49 142 50 static bool run_benchmark(benchmark_t *bench) 143 51 { 144 printf("Warm up and determine workload size...\n"); 52 /* Execute the benchmarl */ 53 const char *ret = bench->entry(); 145 54 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 } 55 if (ret == NULL) { 56 printf("\nBenchmark completed\n"); 57 return true; 160 58 } 161 59 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; 60 printf("\n%s\n", ret); 61 return false; 231 62 } 232 63 233 64 static int run_benchmarks(void) 234 65 { 235 unsigned int count_ok = 0; 236 unsigned int count_fail = 0; 66 benchmark_t *bench; 67 unsigned int i = 0; 68 unsigned int n = 0; 237 69 238 70 char *failed_names = NULL; … … 240 72 printf("\n*** Running all benchmarks ***\n\n"); 241 73 242 for ( size_t it = 0; it < benchmark_count; it++) {243 printf("%s (%s)\n", bench marks[it]->name, benchmarks[it]->desc);244 if (run_benchmark(bench marks[it])) {245 count_ok++;74 for (bench = benchmarks; bench->name != NULL; bench++) { 75 printf("%s (%s)\n", bench->name, bench->desc); 76 if (run_benchmark(bench)) { 77 i++; 246 78 continue; 247 79 } 248 80 249 81 if (!failed_names) { 250 failed_names = str_dup(bench marks[it]->name);82 failed_names = str_dup(bench->name); 251 83 } else { 252 84 char *f = NULL; 253 asprintf(&f, "%s, %s", failed_names, bench marks[it]->name);85 asprintf(&f, "%s, %s", failed_names, bench->name); 254 86 if (!f) { 255 87 printf("Out of memory.\n"); … … 259 91 failed_names = f; 260 92 } 261 count_fail++;93 n++; 262 94 } 263 95 264 printf("\nCompleted, %u benchmarks run, %u succeeded.\n", 265 count_ok + count_fail, count_ok); 96 printf("\nCompleted, %u benchmarks run, %u succeeded.\n", i + n, i); 266 97 if (failed_names) 267 98 printf("Failed benchmarks: %s\n", failed_names); 268 99 269 return count_fail;100 return n; 270 101 } 271 102 … … 273 104 { 274 105 size_t len = 0; 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;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); 279 110 } 280 111 281 assert(can_cast_size_t_to_int(len) && "benchmark name length overflow"); 112 unsigned int _len = (unsigned int) len; 113 if ((_len != len) || (((int) _len) < 0)) { 114 printf("Command length overflow\n"); 115 return; 116 } 282 117 283 for ( size_t i = 0; i < benchmark_count; i++)284 printf("%-*s %s\n", (int) len, benchmarks[i]->name, benchmarks[i]->desc);118 for (bench = benchmarks; bench->name != NULL; bench++) 119 printf("%-*s %s\n", _len, bench->name, bench->desc); 285 120 286 printf("%-*s Run all benchmarks\n", (int)len, "*");121 printf("%-*s Run all benchmarks\n", _len, "*"); 287 122 } 288 123 … … 300 135 } 301 136 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); 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); 305 141 } 306 142 } -
uspace/app/perf/perf.h
rb9f1585 r7acd787 37 37 38 38 #include <stdbool.h> 39 #include <perf.h>40 39 41 typedef bool (*benchmark_entry_t)(stopwatch_t *, uint64_t, 42 char *, size_t); 43 typedef bool (*benchmark_helper_t)(char *, size_t); 40 typedef const char *(*benchmark_entry_t)(void); 44 41 45 42 typedef struct { … … 47 44 const char *desc; 48 45 benchmark_entry_t entry; 49 benchmark_helper_t setup;50 benchmark_helper_t teardown;51 46 } 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[]; 52 54 53 55 #endif -
uspace/app/tester/tester.c
rb9f1585 r7acd787 35 35 */ 36 36 37 #include <assert.h>38 37 #include <stdio.h> 39 38 #include <stddef.h> … … 41 40 #include <str.h> 42 41 #include <io/log.h> 43 #include <types/casting.h>44 42 #include "tester.h" 45 43 … … 146 144 } 147 145 148 assert(can_cast_size_t_to_int(len) && "test name length overflow"); 146 unsigned int _len = (unsigned int) len; 147 if ((_len != len) || (((int) _len) < 0)) { 148 printf("Command length overflow\n"); 149 return; 150 } 149 151 150 152 for (test = tests; test->name != NULL; test++) 151 printf("%-*s %s%s\n", (int)len, test->name, test->desc,153 printf("%-*s %s%s\n", _len, test->name, test->desc, 152 154 (test->safe ? "" : " (unsafe)")); 153 155 154 printf("%-*s Run all safe tests\n", (int)len, "*");156 printf("%-*s Run all safe tests\n", _len, "*"); 155 157 } 156 158 -
uspace/lib/c/Makefile
rb9f1585 r7acd787 189 189 TEST_SOURCES = \ 190 190 test/adt/circ_buf.c \ 191 test/casting.c \192 191 test/fibril/timer.c \ 193 192 test/main.c \ … … 197 196 test/stdio/scanf.c \ 198 197 test/odict.c \ 199 test/perf.c \200 198 test/perm.c \ 201 199 test/qsort.c \ -
uspace/lib/c/test/main.c
rb9f1585 r7acd787 32 32 PCUT_INIT; 33 33 34 PCUT_IMPORT(casting);35 34 PCUT_IMPORT(circ_buf); 36 35 PCUT_IMPORT(fibril_timer); … … 38 37 PCUT_IMPORT(mem); 39 38 PCUT_IMPORT(odict); 40 PCUT_IMPORT(perf);41 39 PCUT_IMPORT(perm); 42 40 PCUT_IMPORT(qsort);
Note:
See TracChangeset
for help on using the changeset viewer.
