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