pcp
[Top] [All Lists]

[PATCH 1/2] pmdas/perfevent: Add a perf derived event for current memory

To: pcp@xxxxxxxxxxx
Subject: [PATCH 1/2] pmdas/perfevent: Add a perf derived event for current memory bandwidth
From: Hemant Kumar <hemant@xxxxxxxxxxxxxxxxxx>
Date: Mon, 16 May 2016 02:48:25 +0530
Cc: nathans@xxxxxxxxxx
Delivered-to: pcp@xxxxxxxxxxx
Adds a derived perfevent current_bandwidth to perfevent.conf file. This
metric gives the current memory bandwidth usage for a system. Currently,
only x86 counters are added.

  # pminfo | grep current_bandwidth
  perfevent.derived.current_bandwidth.value

  # pmval perfevent.derived.current_bandwidth.value

  metric:    perfevent.derived.current_bandwidth.value
  host:      <some_host>
  semantics: cumulative counter (converting to rate)
  units:     count (converting to count / sec)
  samples:   all

              cpu0                  cpu8
              78.47                541.0
              77.66                562.1
             641.4                 232.2
             232.7                 859.4
              67.59                944.5
            3.719E+04             3.710E+04
            4.084E+04             4.077E+04
            4.042E+04             4.039E+04
            1.128E+04             1.126E+04
            1.421E+04             1.427E+04
...

This patch also makes some changes to code, to allow other perf derived
events to be defined even if one or more derived events fail to
register. So, if the current_derived derived event fails to register due
to unavailability of some of its base counters, we log an error to
perfevent.log and continue registering other derived events.

Some data structure definitions have been moved from perfinterface.c to
perfinterface.h to allow them to be used in qa/perfevent.

Signed-off-by: Hemant Kumar <hemant@xxxxxxxxxxxxxxxxxx>
---
 src/pmdas/perfevent/perfevent.conf  | 10 ++++++
 src/pmdas/perfevent/perfinterface.c | 68 ++++++-------------------------------
 src/pmdas/perfevent/perfinterface.h | 49 ++++++++++++++++++++++++++
 3 files changed, 70 insertions(+), 57 deletions(-)

diff --git a/src/pmdas/perfevent/perfevent.conf 
b/src/pmdas/perfevent/perfevent.conf
index 5cd78a8..7e754bf 100644
--- a/src/pmdas/perfevent/perfevent.conf
+++ b/src/pmdas/perfevent/perfevent.conf
@@ -258,6 +258,16 @@ INSTRUCTION_RETIRED
 UNHALTED_REFERENCE_CYCLES
 LLC_MISSES
 
+[current_bandwidth:derived]
+snbep_unc_imc0::UNC_M_CAS_COUNT:RD node perf_scale
+snbep_unc_imc1::UNC_M_CAS_COUNT:RD node perf_scale
+snbep_unc_imc2::UNC_M_CAS_COUNT:RD node perf_scale
+snbep_unc_imc3::UNC_M_CAS_COUNT:RD node perf_scale
+snbep_unc_imc0::UNC_M_CAS_COUNT:WR node perf_scale
+snbep_unc_imc1::UNC_M_CAS_COUNT:WR node perf_scale
+snbep_unc_imc2::UNC_M_CAS_COUNT:WR node perf_scale
+snbep_unc_imc3::UNC_M_CAS_COUNT:WR node perf_scale
+
 # Fallthough case: the perf PMU is the generic one that is likely to be always
 # present.  The cycles and instructions counters likewise should be there
 [perf]
diff --git a/src/pmdas/perfevent/perfinterface.c 
b/src/pmdas/perfevent/perfinterface.c
index e265f77..d6e3a33 100644
--- a/src/pmdas/perfevent/perfinterface.c
+++ b/src/pmdas/perfevent/perfinterface.c
@@ -37,56 +37,10 @@
 #define EVENT_TYPE_PERF 0
 #define EVENT_TYPE_RAPL 1
 
-typedef struct eventcpuinfo_t_ {
-    uint64_t values[3];
-    uint64_t previous[3];
-    int type;
-    int fd;
-    perf_event_attr_t hw; /* perf_event_attr struct passed to 
perf_event_open() */
-    int idx; /* opaque libpfm event identifier */
-    char *fstr; /* fstr from library, must be freed */
-    rapl_data_t rapldata;
-    int cpu;
-} eventcpuinfo_t;
-
 #define RAW_VALUE 0
 #define TIME_ENABLED 1
 #define TIME_RUNNING 2
 
-typedef struct event_t_ {
-    char *name;
-    eventcpuinfo_t *info;
-    int ncpus;
-} event_t;
-
-typedef struct event_list_t_ {
-    event_t *event;
-    double scale;
-    struct event_list_t_ *next;
-} event_list_t;
-
-typedef struct derived_event_t_ {
-    char *name;
-    event_list_t *event_list;
-} derived_event_t;
-
-typedef struct perfdata_t_
-{
-    int nevents;
-    event_t *events;
-
-    int nderivedevents;
-    derived_event_t *derived_events;
-
-    /* information about the architecture (number of cpus, numa nodes etc) */
-    archinfo_t *archinfo;
-
-    /* internal state to keep track of cpus for events added in 'round
-     * robin' mode */
-    int roundrobin_cpu_idx;
-    int roundrobin_nodecpu_idx;
-} perfdata_t;
-
 const char *perf_strerror(int err)
 {
     const char *ret = "Unknown error";
@@ -511,15 +465,6 @@ static int perf_setup_derived_event(perfdata_t *inst, 
pmcderived_t *derived_pmc)
         return -E_PERFEVENT_LOGIC;
     }
 
-    derived_events = realloc(derived_events,
-                             (nderivedevents + 1) * sizeof(*derived_events));
-    if (NULL == derived_events) {
-        free(inst->derived_events);
-        inst->nderivedevents = 0;
-        inst->derived_events = NULL;
-        return -E_PERFEVENT_REALLOC;
-    }
-
     /*
      * If a certain setting_list is not available, then we need to check if the
      * next one is available.
@@ -576,6 +521,7 @@ static int perf_setup_derived_event(perfdata_t *inst, 
pmcderived_t *derived_pmc)
                 ptr = ptr->next;
             }
         }
+
         /* There was a event mismatch in the curr list, so, discard this list 
*/
         if (clear_history)
             free_event_list(event_list);
@@ -592,7 +538,15 @@ static int perf_setup_derived_event(perfdata_t *inst, 
pmcderived_t *derived_pmc)
         return -E_PERFEVENT_LOGIC;
     }
 
-    tmp = event_list;
+    derived_events = realloc(derived_events,
+                             (nderivedevents + 1) * sizeof(*derived_events));
+    if (NULL == derived_events) {
+        free(inst->derived_events);
+        inst->nderivedevents = 0;
+        inst->derived_events = NULL;
+       free_event_list(event_list);
+        return -E_PERFEVENT_REALLOC;
+    }
 
     curr = derived_events + nderivedevents;
     curr->name = strdup(derived_pmc->name);
@@ -1190,7 +1144,7 @@ perfhandle_t *perf_event_create(const char *config_file)
             derivedpmc = &(perfconfig->derivedArr[i]);
             ret = perf_setup_derived_event(inst, derivedpmc);
             if (ret < 0)
-                return NULL;
+               fprintf(stderr, "Unable to setup deived event : %s\n", 
derivedpmc->name);
         }
     }
 
diff --git a/src/pmdas/perfevent/perfinterface.h 
b/src/pmdas/perfevent/perfinterface.h
index e471382..17f500b 100644
--- a/src/pmdas/perfevent/perfinterface.h
+++ b/src/pmdas/perfevent/perfinterface.h
@@ -17,6 +17,9 @@
 #define PERFINTERFACE_H_
 
 #include <stdint.h>
+#include <perfmon/pfmlib_perf_event.h>
+#include "rapl-interface.h"
+#include "architecture.h"
 
 typedef struct perf_data_t_
 {
@@ -53,6 +56,52 @@ typedef struct perf_derived_counter_t_
     perf_counter_list *counter_list;
 } perf_derived_counter;
 
+typedef struct eventcpuinfo_t_ {
+    uint64_t values[3];
+    uint64_t previous[3];
+    int type;
+    int fd;
+    perf_event_attr_t hw; /* perf_event_attr struct passed to 
perf_event_open() */
+    int idx; /* opaque libpfm event identifier */
+    char *fstr; /* fstr from library, must be freed */
+    rapl_data_t rapldata;
+    int cpu;
+} eventcpuinfo_t;
+
+typedef struct event_t_ {
+    char *name;
+    eventcpuinfo_t *info;
+    int ncpus;
+} event_t;
+
+typedef struct event_list_t_ {
+    event_t *event;
+    double scale;
+    struct event_list_t_ *next;
+} event_list_t;
+
+typedef struct derived_event_t_ {
+    char *name;
+    event_list_t *event_list;
+} derived_event_t;
+
+typedef struct perfdata_t_
+{
+    int nevents;
+    event_t *events;
+
+    int nderivedevents;
+    derived_event_t *derived_events;
+
+    /* information about the architecture (number of cpus, numa nodes etc) */
+    archinfo_t *archinfo;
+
+    /* internal state to keep track of cpus for events added in 'round
+     * robin' mode */
+    int roundrobin_cpu_idx;
+    int roundrobin_nodecpu_idx;
+} perfdata_t;
+
 typedef intptr_t perfhandle_t;
 
 perfhandle_t *perf_event_create(const char *configfile);
-- 
1.9.3

<Prev in Thread] Current Thread [Next in Thread>