netdev-dpdk: fix mbuf leaks
[cascardo/ovs.git] / lib / perf-counter.h
1 /*
2  * Copyright (c) 2015 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __PERF_COUNTER_H
18 #define __PERF_COUNTER_H 1
19
20 /* Motivation
21  * ==========
22  *
23  * It is sometimes desirable to gain performance insights of a program
24  * by using hardware counters.  Recent Linux kernels started to support
25  * a set of portable API for configuring and access those counter across
26  * multiple platforms.
27  *
28  * APIs provided by perf-counter.h provides a set of APIs that are
29  * semi-integrated into OVS user spaces. The infrastructure that initializes,
30  * cleanup, display and clear them at run time is provided. However the
31  * sample points are not. A programmer needs insert sample points when needed.
32  *
33  * Since there is no pre configured sample points, there is no run time
34  * over head for the released product.
35  *
36  * Limitations
37  * ===========
38  * - Hard coded to sample CPU cycle count in user space only.
39  * - Only one counter is sampled.
40  * - Useful macros are only provided for function profiling.
41  * - show and clear command applies to all counters, there is no way
42  *   to select a sub-set of counter.
43  *
44  * Those are not fundamental limits, but only limited by current
45  * implementation.
46  *
47  * Usage:
48  * =======
49  *
50  * Adding performance counter is easy. Simply use the following macro to
51  * wrap around the expression you are interested in measuring.
52  *
53  * PERF(name, expr).
54  *
55  * The 'expr' is a set of C expressions you are interested in measuring.
56  * 'name' is the counter name.
57  *
58  * For example, if we are interested in performance of perf_func():
59  *
60  *    int perf_func() {
61  *        <implemenation>
62  *    }
63  *
64  *    void func() {
65  *        int rt;
66  *
67  *        ...
68  *        PERF("perf_func", rt = perf_func());
69  *
70  *        return rt;
71  *    }
72  *
73  *
74  * This will maintain the number of times 'perf_func()' is called, total
75  * number of instructions '<implementation>' plus function call overhead
76  * executed.
77  *
78  */
79
80 #if defined(__linux__) && defined(HAVE_LINUX_PERF_EVENT_H)
81 struct perf_counter {
82     const char *name;
83     bool once;
84     uint64_t n_events;
85     uint64_t total_count;
86 };
87
88 #define PERF_COUNTER_ONCE_INITIALIZER(name)  \
89     {                                        \
90         name,                                \
91         false,                               \
92         0,                                   \
93         0,                                   \
94     }
95
96 void perf_counters_init(void);
97 void perf_counters_destroy(void);
98 void perf_counters_clear(void);
99
100 uint64_t perf_counter_read(uint64_t *counter);
101 void perf_counter_accumulate(struct perf_counter *counter,
102                              uint64_t start_count);
103 char *perf_counters_to_string(void);
104
105 /* User access macros. */
106 #define PERF(name, expr) \
107       { \
108           static struct perf_counter c = PERF_COUNTER_ONCE_INITIALIZER(name);\
109           uint64_t start_count = perf_counter_read(&start_count); \
110                                                                   \
111           expr;                                                   \
112                                                                   \
113           perf_counter_accumulate(&c, start_count);               \
114       }
115 #else
116 #define PERF(name, expr) { expr; }
117
118 static inline void perf_counters_init(void) {}
119 static inline void perf_counters_destroy(void) {}
120 static inline void perf_counters_clear(void) {}
121 static inline char *
122 perf_counters_to_string(void)
123 {
124     return xstrdup("Not Supported on this platform. Only available on Linux (version >= 2.6.32)");
125 }
126
127 #endif
128
129 #endif