Replace the original PERF_FUNCTION_BEGIN and PERF_FUNCTION_END pair
with a single PERF macro. This design is also more flexible, removing
the restriction of have only one measurement per function.

The next patch will make use of this macro.

Signed-off-by: Andy Zhou <az...@nicira.com>
---
 lib/perf-counter.c | 13 ++++++----
 lib/perf-counter.h | 75 +++++++++++++++++++++---------------------------------
 2 files changed, 37 insertions(+), 51 deletions(-)

diff --git a/lib/perf-counter.c b/lib/perf-counter.c
index 8c859cc..d8c0532 100644
--- a/lib/perf-counter.c
+++ b/lib/perf-counter.c
@@ -31,7 +31,7 @@
 #include "shash.h"
 #include "util.h"
 
-static struct shash perf_counters;
+static struct shash perf_counters = SHASH_INITIALIZER(&perf_counters);
 static int fd__ = 0;
 
 uint64_t
@@ -59,10 +59,11 @@ perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
 
 /* Set up perf event counters to read user space instruction counters
  * only for this process, on all cpus.   */
-static void
+static int
 perf_event_setup(void)
 {
     struct perf_event_attr pe;
+    int fd;
 
     memset(&pe, 0, sizeof(struct perf_event_attr));
     pe.type = PERF_TYPE_HARDWARE;
@@ -72,11 +73,13 @@ perf_event_setup(void)
     pe.exclude_kernel = 1;
     pe.exclude_hv = 1;
 
-    fd__ = perf_event_open(&pe, 0, -1, -1, 0);
-    if (fd__ > 0) {
+    fd = perf_event_open(&pe, 0, -1, -1, 0);
+    if (fd > 0) {
         ioctl(fd__, PERF_EVENT_IOC_RESET, 0);
         ioctl(fd__, PERF_EVENT_IOC_ENABLE, 0);
     }
+
+    return fd;
 }
 
 static void
@@ -159,7 +162,7 @@ void
 perf_counters_init(void)
 {
     shash_init(&perf_counters);
-    perf_event_setup();
+    fd__ = perf_event_setup();
 }
 
 void
diff --git a/lib/perf-counter.h b/lib/perf-counter.h
index 23365de..ca3aaba 100644
--- a/lib/perf-counter.h
+++ b/lib/perf-counter.h
@@ -44,54 +44,37 @@
  * Those are not fundamental limits, but only limited by current
  * implementation.
  *
- * Function instruction counter sample point Usage
- * ================================================
+ * Usage:
+ * =======
  *
- * There are two macros provided:
+ * Adding performance counter is easy. Simply use the following macro to
+ * wrap around the expression you are interested in measuring.
  *
- * Macro 'PERF_FUNCTON_COUNT_BEGIN' needs to be inserted towards the
- * beginning of the function where local variables are declared.
+ * PERF(name, expr).
  *
- * Macro 'PERF_FUNCTON_COUNT_END' needs to appear in the same function,
- * some where below 'PERF_FUNCTION_COUNT_BEGIN', usually towards of
- * a function.
+ * The 'expr' is a set of C expressions you are interested in measuring.
+ * 'name' is the counter name.
  *
- * For example:
+ * For example, if we are interested in performance of perf_func():
  *
- *    void my_func() {
- *      int some_local_variable;
- *
- *      PERF_FUNCTION_COUNT_BEGIN;
- *
- *      < implementation >
- *
- *      PERF_FUNCTION_COUNT_END
+ *    int perf_func() {
+ *        <implemenation>
  *    }
  *
- * This will maintain the number of times 'my_func()' is called, total
- * number of instructions '<implementation>' executed during all those calls.
+ *    void func() {
+ *        int rt;
  *
- * Currently there are two limitation:
- * 1). At most one pair can appear in the same variable scope.
- * 2). The Macros use function name as the counter name for display.
- *     Thus, all functions in one annotation session are required to
- *     have unique names.
+ *        ...
+ *        PERF("perf_func", rt = perf_func());
  *
- * Note, there is no requirement for those macros to be balanced.
- * For example:
+ *        return rt;
+ *    }
  *
- *    void my_func(int i){
  *
- *      PERF_FUNCTION_COUNT_BEGIN;
+ * This will maintain the number of times 'perf_func()' is called, total
+ * number of instructions '<implementation>' plus function call overhead
+ * executed.
  *
- *      if (i == 300) {
- *          PERF_FUNCTION_COUNT_END;
- *          return;
- *      } else {
- *           <some code>
- *      }
- *    }
- * will work just fine.
  */
 
 #if defined(__linux__) && defined(HAVE_LINUX_PERF_EVENT_H)
@@ -120,17 +103,17 @@ void perf_counter_accumulate(struct perf_counter *counter,
 char *perf_counters_to_string(void);
 
 /* User access macros. */
-#define PERF_FUNCTION_BEGIN \
-    static struct perf_counter x__ = PERF_COUNTER_ONCE_INITIALIZER(__func__); \
-    uint64_t start_count__ = perf_counter_read(&start_count__);               \
-
-#define PERF_FUNCTION_END \
-    perf_counter_accumulate(&x__, start_count__);
-
+#define PERF(name, expr) \
+      { \
+          static struct perf_counter c = PERF_COUNTER_ONCE_INITIALIZER(name);\
+          uint64_t start_count = perf_counter_read(&start_count); \
+                                                                  \
+          expr;                                                   \
+                                                                  \
+          perf_counter_accumulate(&c, start_count);               \
+      }
 #else
-
-#define PERF_FUNCTON_BEGIN
-#define PERF_FUNCTON_END
+#define PERF(name, expr)
 
 static inline void perf_counters_init(void) {}
 static inline void perf_counters_destroy(void) {}
-- 
1.9.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to