Damjan Marion | e3e3555 | 2021-05-06 17:34:49 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: Apache-2.0 |
| 2 | * Copyright(c) 2021 Cisco Systems, Inc. |
| 3 | */ |
| 4 | |
| 5 | #include <vppinfra/format.h> |
Damjan Marion | d154a17 | 2021-07-13 21:12:41 +0200 | [diff] [blame] | 6 | #include <vppinfra/vector/test/test.h> |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 7 | #include <vppinfra/error.h> |
Damjan Marion | e3e3555 | 2021-05-06 17:34:49 +0200 | [diff] [blame] | 8 | |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 9 | test_main_t test_main; |
Damjan Marion | e3e3555 | 2021-05-06 17:34:49 +0200 | [diff] [blame] | 10 | |
| 11 | int |
Mohsin Kazmi | 8501060 | 2021-07-15 14:20:57 +0000 | [diff] [blame] | 12 | test_march_supported (clib_march_variant_type_t type) |
| 13 | { |
| 14 | #define _(s, n) \ |
| 15 | if (CLIB_MARCH_VARIANT_TYPE_##s == type) \ |
| 16 | return clib_cpu_march_priority_##s (); |
| 17 | foreach_march_variant |
| 18 | #undef _ |
| 19 | return 0; |
| 20 | } |
| 21 | |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 22 | clib_error_t * |
| 23 | test_funct (test_main_t *tm) |
Damjan Marion | e3e3555 | 2021-05-06 17:34:49 +0200 | [diff] [blame] | 24 | { |
Damjan Marion | e3e3555 | 2021-05-06 17:34:49 +0200 | [diff] [blame] | 25 | for (int i = 0; i < CLIB_MARCH_TYPE_N_VARIANTS; i++) |
| 26 | { |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 27 | test_registration_t *r = tm->registrations[i]; |
Damjan Marion | e3e3555 | 2021-05-06 17:34:49 +0200 | [diff] [blame] | 28 | |
Mohsin Kazmi | 8501060 | 2021-07-15 14:20:57 +0000 | [diff] [blame] | 29 | if (r == 0 || test_march_supported (i) < 0) |
Damjan Marion | e3e3555 | 2021-05-06 17:34:49 +0200 | [diff] [blame] | 30 | continue; |
| 31 | |
| 32 | fformat (stdout, "\nMultiarch Variant: %U\n", format_march_variant, i); |
| 33 | fformat (stdout, |
| 34 | "-------------------------------------------------------\n"); |
| 35 | while (r) |
| 36 | { |
| 37 | clib_error_t *err; |
Damjan Marion | 68843d1 | 2021-12-06 13:21:33 +0100 | [diff] [blame] | 38 | if (tm->filter && strstr (r->name, (char *) tm->filter) == 0) |
| 39 | goto next; |
Damjan Marion | e3e3555 | 2021-05-06 17:34:49 +0200 | [diff] [blame] | 40 | err = (r->fn) (0); |
| 41 | fformat (stdout, "%-50s %s\n", r->name, err ? "FAIL" : "PASS"); |
| 42 | if (err) |
| 43 | { |
| 44 | clib_error_report (err); |
| 45 | fformat (stdout, "\n"); |
| 46 | } |
Damjan Marion | 68843d1 | 2021-12-06 13:21:33 +0100 | [diff] [blame] | 47 | next: |
Damjan Marion | e3e3555 | 2021-05-06 17:34:49 +0200 | [diff] [blame] | 48 | r = r->next; |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | fformat (stdout, "\n"); |
| 53 | return 0; |
| 54 | } |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 55 | |
Damjan Marion | d5045e6 | 2022-04-06 21:16:37 +0200 | [diff] [blame] | 56 | #if 0 |
Damjan Marion | b97bec0 | 2021-12-12 21:43:56 +0000 | [diff] [blame] | 57 | static u8 * |
| 58 | format_test_perf_bundle_core_power (u8 *s, va_list *args) |
| 59 | { |
| 60 | test_perf_event_bundle_t __clib_unused *b = |
| 61 | va_arg (*args, test_perf_event_bundle_t *); |
| 62 | test_perf_t __clib_unused *tp = va_arg (*args, test_perf_t *); |
| 63 | u64 *data = va_arg (*args, u64 *); |
| 64 | |
| 65 | if (data) |
| 66 | s = format (s, "%7.1f %%", (f64) 100 * data[1] / data[0]); |
| 67 | else |
| 68 | s = format (s, "%9s", "Level 0"); |
| 69 | |
| 70 | if (data) |
| 71 | s = format (s, "%8.1f %%", (f64) 100 * data[2] / data[0]); |
| 72 | else |
| 73 | s = format (s, "%9s", "Level 1"); |
| 74 | |
| 75 | if (data) |
| 76 | s = format (s, "%7.1f %%", (f64) 100 * data[3] / data[0]); |
| 77 | else |
| 78 | s = format (s, "%9s", "Level 2"); |
| 79 | |
| 80 | return s; |
| 81 | } |
| 82 | |
Damjan Marion | b97bec0 | 2021-12-12 21:43:56 +0000 | [diff] [blame] | 83 | #ifdef __x86_64__ |
| 84 | #define PERF_INTEL_CODE(event, umask) ((event) | (umask) << 8) |
| 85 | , |
| 86 | { |
| 87 | .name = "core-power", |
| 88 | .desc = |
| 89 | "Core cycles where the core was running under specific turbo schedule.", |
| 90 | .type = PERF_TYPE_RAW, |
| 91 | .config[0] = PERF_INTEL_CODE (0x3c, 0x00), |
| 92 | .config[1] = PERF_INTEL_CODE (0x28, 0x07), |
| 93 | .config[2] = PERF_INTEL_CODE (0x28, 0x18), |
| 94 | .config[3] = PERF_INTEL_CODE (0x28, 0x20), |
| 95 | .config[4] = PERF_INTEL_CODE (0x28, 0x40), |
| 96 | .n_events = 5, |
| 97 | .format_fn = format_test_perf_bundle_core_power, |
| 98 | } |
| 99 | #endif |
| 100 | }; |
Damjan Marion | d5045e6 | 2022-04-06 21:16:37 +0200 | [diff] [blame] | 101 | #endif |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 102 | |
| 103 | #ifdef __linux__ |
| 104 | clib_error_t * |
| 105 | test_perf (test_main_t *tm) |
| 106 | { |
| 107 | clib_error_t *err = 0; |
Damjan Marion | d5045e6 | 2022-04-06 21:16:37 +0200 | [diff] [blame] | 108 | clib_perfmon_ctx_t _ctx, *ctx = &_ctx; |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 109 | |
Damjan Marion | d5045e6 | 2022-04-06 21:16:37 +0200 | [diff] [blame] | 110 | if ((err = clib_perfmon_init_by_bundle_name ( |
| 111 | ctx, "%s", tm->bundle ? (char *) tm->bundle : "default"))) |
| 112 | return err; |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 113 | |
Damjan Marion | f622bf4 | 2021-12-14 10:40:48 +0100 | [diff] [blame] | 114 | fformat (stdout, "Warming up...\n"); |
Damjan Marion | d5045e6 | 2022-04-06 21:16:37 +0200 | [diff] [blame] | 115 | clib_perfmon_warmup (ctx); |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 116 | |
| 117 | for (int i = 0; i < CLIB_MARCH_TYPE_N_VARIANTS; i++) |
| 118 | { |
| 119 | test_registration_t *r = tm->registrations[i]; |
| 120 | |
| 121 | if (r == 0 || test_march_supported (i) < 0) |
| 122 | continue; |
| 123 | |
| 124 | fformat (stdout, "\nMultiarch Variant: %U\n", format_march_variant, i); |
| 125 | fformat (stdout, |
| 126 | "-------------------------------------------------------\n"); |
| 127 | while (r) |
| 128 | { |
| 129 | if (r->perf_tests) |
| 130 | { |
| 131 | test_perf_t *pt = r->perf_tests; |
Damjan Marion | 68843d1 | 2021-12-06 13:21:33 +0100 | [diff] [blame] | 132 | if (tm->filter && strstr (r->name, (char *) tm->filter) == 0) |
| 133 | goto next; |
Damjan Marion | d5045e6 | 2022-04-06 21:16:37 +0200 | [diff] [blame] | 134 | |
| 135 | clib_perfmon_capture_group (ctx, "%s", r->name); |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 136 | do |
| 137 | { |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 138 | for (int i = 0; i < tm->repeat; i++) |
| 139 | { |
Damjan Marion | d5045e6 | 2022-04-06 21:16:37 +0200 | [diff] [blame] | 140 | pt->fd = ctx->group_fd; |
| 141 | clib_perfmon_reset (ctx); |
| 142 | pt->fn (pt); |
| 143 | clib_perfmon_capture (ctx, pt->n_ops, "%0s", pt->name); |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 144 | } |
| 145 | } |
| 146 | while ((++pt)->fn); |
| 147 | } |
Damjan Marion | 68843d1 | 2021-12-06 13:21:33 +0100 | [diff] [blame] | 148 | next: |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 149 | r = r->next; |
| 150 | } |
Damjan Marion | d5045e6 | 2022-04-06 21:16:37 +0200 | [diff] [blame] | 151 | fformat (stdout, "%U\n", format_perfmon_bundle, ctx); |
| 152 | clib_perfmon_clear (ctx); |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 153 | } |
| 154 | |
Damjan Marion | d5045e6 | 2022-04-06 21:16:37 +0200 | [diff] [blame] | 155 | clib_perfmon_free (ctx); |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 156 | return err; |
| 157 | } |
| 158 | #endif |
| 159 | |
| 160 | int |
| 161 | main (int argc, char *argv[]) |
| 162 | { |
| 163 | test_main_t *tm = &test_main; |
| 164 | unformat_input_t _i = {}, *i = &_i; |
| 165 | clib_mem_init (0, 64ULL << 20); |
| 166 | clib_error_t *err; |
| 167 | int perf = 0; |
| 168 | |
| 169 | /* defaults */ |
| 170 | tm->repeat = 3; |
| 171 | |
| 172 | unformat_init_command_line (i, argv); |
| 173 | |
| 174 | while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) |
| 175 | { |
| 176 | if (unformat (i, "perf")) |
| 177 | perf = 1; |
Damjan Marion | 68843d1 | 2021-12-06 13:21:33 +0100 | [diff] [blame] | 178 | else if (unformat (i, "filter %s", &tm->filter)) |
| 179 | ; |
Damjan Marion | b97bec0 | 2021-12-12 21:43:56 +0000 | [diff] [blame] | 180 | else if (unformat (i, "bundle %s", &tm->bundle)) |
| 181 | ; |
Damjan Marion | 3323e20 | 2021-12-02 11:28:57 +0100 | [diff] [blame] | 182 | else if (unformat (i, "repeat %d", &tm->repeat)) |
| 183 | ; |
| 184 | else |
| 185 | { |
| 186 | clib_warning ("unknown input '%U'", format_unformat_error, i); |
| 187 | exit (1); |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | if (perf) |
| 192 | err = test_perf (tm); |
| 193 | else |
| 194 | err = test_funct (tm); |
| 195 | |
| 196 | if (err) |
| 197 | { |
| 198 | clib_error_report (err); |
| 199 | fformat (stderr, "\n"); |
| 200 | return 1; |
| 201 | } |
| 202 | return 0; |
| 203 | } |
| 204 | |
| 205 | void * |
| 206 | test_mem_alloc (uword size) |
| 207 | { |
| 208 | void *rv; |
| 209 | size = round_pow2 (size, CLIB_CACHE_LINE_BYTES); |
| 210 | rv = clib_mem_alloc_aligned (size, CLIB_CACHE_LINE_BYTES); |
| 211 | clib_memset_u8 (rv, 0, size); |
| 212 | return rv; |
| 213 | } |
| 214 | |
| 215 | void * |
| 216 | test_mem_alloc_and_fill_inc_u8 (uword size, u8 start, u8 mask) |
| 217 | { |
| 218 | u8 *rv; |
| 219 | mask = mask ? mask : 0xff; |
| 220 | size = round_pow2 (size, CLIB_CACHE_LINE_BYTES); |
| 221 | rv = clib_mem_alloc_aligned (size, CLIB_CACHE_LINE_BYTES); |
| 222 | for (uword i = 0; i < size; i++) |
| 223 | rv[i] = ((u8) i + start) & mask; |
| 224 | return rv; |
| 225 | } |
| 226 | |
| 227 | void * |
| 228 | test_mem_alloc_and_splat (uword elt_size, uword n_elts, void *elt) |
| 229 | { |
| 230 | u8 *rv, *e; |
| 231 | uword data_size = elt_size * n_elts; |
| 232 | uword alloc_size = round_pow2 (data_size, CLIB_CACHE_LINE_BYTES); |
| 233 | e = rv = clib_mem_alloc_aligned (alloc_size, CLIB_CACHE_LINE_BYTES); |
| 234 | while (e - rv < data_size) |
| 235 | { |
| 236 | clib_memcpy_fast (e, elt, elt_size); |
| 237 | e += elt_size; |
| 238 | } |
| 239 | |
| 240 | if (data_size < alloc_size) |
| 241 | clib_memset_u8 (e, 0, alloc_size - data_size); |
| 242 | return rv; |
| 243 | } |
| 244 | |
| 245 | void |
| 246 | test_mem_free (void *p) |
| 247 | { |
| 248 | clib_mem_free (p); |
| 249 | } |