LCOV - code coverage report
Current view: top level - vppinfra/perfmon - perfmon.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 128 0.0 %
Date: 2023-07-05 22:20:52 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: Apache-2.0
       2             :  * Copyright(c) 2022 Cisco Systems, Inc.
       3             :  */
       4             : 
       5             : #include <vppinfra/format.h>
       6             : #include <vppinfra/error.h>
       7             : #include <vppinfra/perfmon/perfmon.h>
       8             : #include <vppinfra/format_table.h>
       9             : 
      10             : clib_perfmon_main_t clib_perfmon_main;
      11             : 
      12             : __clib_export clib_error_t *
      13           0 : clib_perfmon_init_by_bundle_name (clib_perfmon_ctx_t *ctx, char *fmt, ...)
      14             : {
      15           0 :   clib_perfmon_main_t *pm = &clib_perfmon_main;
      16           0 :   clib_perfmon_bundle_t *b = 0;
      17           0 :   int group_fd = -1;
      18           0 :   clib_error_t *err = 0;
      19             :   va_list va;
      20             :   char *bundle_name;
      21             : 
      22           0 :   struct perf_event_attr pe = {
      23             :     .size = sizeof (struct perf_event_attr),
      24             :     .disabled = 1,
      25             :     .exclude_kernel = 1,
      26             :     .exclude_hv = 1,
      27             :     .pinned = 1,
      28             :     .exclusive = 1,
      29             :     .read_format = (PERF_FORMAT_GROUP | PERF_FORMAT_TOTAL_TIME_ENABLED |
      30             :                     PERF_FORMAT_TOTAL_TIME_RUNNING),
      31             :   };
      32             : 
      33           0 :   va_start (va, fmt);
      34           0 :   bundle_name = (char *) va_format (0, fmt, &va);
      35           0 :   va_end (va);
      36           0 :   vec_add1 (bundle_name, 0);
      37             : 
      38           0 :   for (clib_perfmon_bundle_reg_t *r = pm->bundle_regs; r; r = r->next)
      39             :     {
      40           0 :       if (strncmp (r->bundle->name, bundle_name, vec_len (bundle_name) - 1))
      41           0 :         continue;
      42           0 :       b = r->bundle;
      43           0 :       break;
      44             :     }
      45             : 
      46           0 :   if (b == 0)
      47             :     {
      48           0 :       err = clib_error_return (0, "Unknown bundle '%s'", bundle_name);
      49           0 :       goto done;
      50             :     }
      51             : 
      52           0 :   clib_memset_u8 (ctx, 0, sizeof (clib_perfmon_ctx_t));
      53           0 :   vec_validate_init_empty (ctx->fds, b->n_events - 1, -1);
      54           0 :   ctx->bundle = b;
      55             : 
      56           0 :   for (int i = 0; i < b->n_events; i++)
      57             :     {
      58           0 :       pe.config = b->config[i];
      59           0 :       pe.type = b->type;
      60           0 :       int fd = syscall (__NR_perf_event_open, &pe, /* pid */ 0, /* cpu */ -1,
      61             :                         /* group_fd */ group_fd, /* flags */ 0);
      62           0 :       if (fd < 0)
      63             :         {
      64           0 :           err = clib_error_return_unix (0, "perf_event_open[%u]", i);
      65           0 :           goto done;
      66             :         }
      67             : 
      68           0 :       if (ctx->debug)
      69           0 :         fformat (stderr, "perf event %u open, fd %d\n", i, fd);
      70             : 
      71           0 :       if (group_fd == -1)
      72             :         {
      73           0 :           group_fd = fd;
      74           0 :           pe.pinned = 0;
      75           0 :           pe.exclusive = 0;
      76             :         }
      77             : 
      78           0 :       ctx->fds[i] = fd;
      79             :     }
      80             : 
      81           0 :   ctx->group_fd = group_fd;
      82           0 :   ctx->data = vec_new (u64, 3 + b->n_events);
      83           0 :   ctx->ref_clock = os_cpu_clock_frequency ();
      84           0 :   vec_validate (ctx->capture_groups, 0);
      85             : 
      86           0 : done:
      87           0 :   if (err)
      88           0 :     clib_perfmon_free (ctx);
      89             : 
      90           0 :   vec_free (bundle_name);
      91           0 :   return err;
      92             : }
      93             : 
      94             : __clib_export void
      95           0 : clib_perfmon_free (clib_perfmon_ctx_t *ctx)
      96             : {
      97           0 :   clib_perfmon_clear (ctx);
      98           0 :   vec_free (ctx->captures);
      99           0 :   vec_free (ctx->capture_groups);
     100             : 
     101           0 :   for (int i = 0; i < vec_len (ctx->fds); i++)
     102           0 :     if (ctx->fds[i] > -1)
     103           0 :       close (ctx->fds[i]);
     104           0 :   vec_free (ctx->fds);
     105           0 :   vec_free (ctx->data);
     106           0 : }
     107             : 
     108             : __clib_export void
     109           0 : clib_perfmon_clear (clib_perfmon_ctx_t *ctx)
     110             : {
     111           0 :   for (int i = 0; i < vec_len (ctx->captures); i++)
     112           0 :     vec_free (ctx->captures[i].desc);
     113           0 :   vec_reset_length (ctx->captures);
     114           0 :   for (int i = 0; i < vec_len (ctx->capture_groups); i++)
     115           0 :     vec_free (ctx->capture_groups[i].name);
     116           0 :   vec_reset_length (ctx->capture_groups);
     117           0 : }
     118             : 
     119             : __clib_export u64 *
     120           0 : clib_perfmon_capture (clib_perfmon_ctx_t *ctx, u32 n_ops, char *fmt, ...)
     121             : {
     122           0 :   u32 read_size = (ctx->bundle->n_events + 3) * sizeof (u64);
     123             :   clib_perfmon_capture_t *c;
     124             :   u64 d[CLIB_PERFMON_MAX_EVENTS + 3];
     125             :   va_list va;
     126             : 
     127           0 :   if ((read (ctx->group_fd, d, read_size) != read_size))
     128             :     {
     129           0 :       if (ctx->debug)
     130           0 :         fformat (stderr, "reading of %u bytes failed, %s (%d)\n", read_size,
     131           0 :                  strerror (errno), errno);
     132           0 :       return 0;
     133             :     }
     134             : 
     135           0 :   if (ctx->debug)
     136             :     {
     137           0 :       fformat (stderr, "read events: %lu enabled: %lu running: %lu ", d[0],
     138             :                d[1], d[2]);
     139           0 :       fformat (stderr, "data: [%lu", d[3]);
     140           0 :       for (int i = 1; i < ctx->bundle->n_events; i++)
     141           0 :         fformat (stderr, ", %lu", d[i + 3]);
     142           0 :       fformat (stderr, "]\n");
     143             :     }
     144             : 
     145           0 :   vec_add2 (ctx->captures, c, 1);
     146             : 
     147           0 :   va_start (va, fmt);
     148           0 :   c->desc = va_format (0, fmt, &va);
     149           0 :   va_end (va);
     150             : 
     151           0 :   c->n_ops = n_ops;
     152           0 :   c->group = vec_len (ctx->capture_groups) - 1;
     153           0 :   c->time_enabled = d[1];
     154           0 :   c->time_running = d[2];
     155           0 :   for (int i = 0; i < CLIB_PERFMON_MAX_EVENTS; i++)
     156           0 :     c->data[i] = d[i + 3];
     157             : 
     158           0 :   return ctx->data + vec_len (ctx->data) - ctx->bundle->n_events;
     159             : }
     160             : 
     161             : __clib_export void
     162           0 : clib_perfmon_capture_group (clib_perfmon_ctx_t *ctx, char *fmt, ...)
     163             : {
     164             :   clib_perfmon_capture_group_t *cg;
     165             :   va_list va;
     166             : 
     167           0 :   cg = vec_end (ctx->capture_groups) - 1;
     168             : 
     169           0 :   if (cg->name != 0)
     170           0 :     vec_add2 (ctx->capture_groups, cg, 1);
     171             : 
     172           0 :   va_start (va, fmt);
     173           0 :   cg->name = va_format (0, fmt, &va);
     174           0 :   va_end (va);
     175           0 :   ASSERT (cg->name);
     176           0 : }
     177             : 
     178             : __clib_export void
     179           0 : clib_perfmon_warmup (clib_perfmon_ctx_t *ctx)
     180             : {
     181           0 :   for (u64 i = 0; i < (u64) ctx->ref_clock; i++)
     182           0 :     asm volatile("" : : "r"(i * i) : "memory");
     183           0 : }
     184             : 
     185             : __clib_export u8 *
     186           0 : format_perfmon_bundle (u8 *s, va_list *args)
     187             : {
     188           0 :   clib_perfmon_ctx_t *ctx = va_arg (*args, clib_perfmon_ctx_t *);
     189             :   clib_perfmon_capture_t *c;
     190           0 :   clib_perfmon_capture_group_t *cg = 0;
     191           0 :   char **hdr = ctx->bundle->column_headers;
     192           0 :   table_t _t = {}, *t = &_t;
     193           0 :   u32 n_row = 0, col = 0;
     194             : 
     195           0 :   table_add_header_row (t, 0);
     196             : 
     197           0 :   for (char **h = ctx->bundle->column_headers; h[0]; h++)
     198           0 :     n_row++;
     199             : 
     200           0 :   vec_foreach (c, ctx->captures)
     201             :     {
     202           0 :       if (cg != ctx->capture_groups + c->group)
     203             :         {
     204           0 :           cg = ctx->capture_groups + c->group;
     205           0 :           table_format_cell (t, col, -1, "%v", cg->name);
     206           0 :           table_set_cell_align (t, col, -1, TTAA_LEFT);
     207           0 :           table_set_cell_fg_color (t, col, -1, TTAC_BRIGHT_RED);
     208             : 
     209           0 :           table_format_cell (t, col, 0, "Ops");
     210           0 :           table_set_cell_fg_color (t, col, 0, TTAC_BRIGHT_YELLOW);
     211             : 
     212           0 :           for (int i = 0; i < n_row; i++)
     213             :             {
     214           0 :               table_format_cell (t, col, i + 1, "%s", hdr[i]);
     215           0 :               table_set_cell_fg_color (t, col, i + 1, TTAC_BRIGHT_YELLOW);
     216             :             }
     217           0 :           col++;
     218             :         }
     219           0 :       table_format_cell (t, col, -1, "%v", c->desc);
     220           0 :       table_format_cell (t, col, 0, "%7u", c->n_ops);
     221           0 :       for (int i = 0; i < n_row; i++)
     222           0 :         table_format_cell (t, col, i + 1, "%U", ctx->bundle->format_fn, ctx, c,
     223             :                            i);
     224           0 :       col++;
     225             :     }
     226             : 
     227           0 :   s = format (s, "%U", format_table, t);
     228           0 :   table_free (t);
     229           0 :   return s;
     230             : }

Generated by: LCOV version 1.14