]> git.proxmox.com Git - mirror_ovs.git/blame - lib/perf-counter.h
netdev-offload-tc: Use single 'once' variable for probing tc features
[mirror_ovs.git] / lib / perf-counter.h
CommitLineData
619c3a42
AZ
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 *
73ec82bf
AZ
47 * Usage:
48 * =======
619c3a42 49 *
73ec82bf
AZ
50 * Adding performance counter is easy. Simply use the following macro to
51 * wrap around the expression you are interested in measuring.
619c3a42 52 *
73ec82bf 53 * PERF(name, expr).
619c3a42 54 *
73ec82bf
AZ
55 * The 'expr' is a set of C expressions you are interested in measuring.
56 * 'name' is the counter name.
619c3a42 57 *
73ec82bf 58 * For example, if we are interested in performance of perf_func():
619c3a42 59 *
73ec82bf
AZ
60 * int perf_func() {
61 * <implemenation>
619c3a42
AZ
62 * }
63 *
73ec82bf
AZ
64 * void func() {
65 * int rt;
619c3a42 66 *
73ec82bf
AZ
67 * ...
68 * PERF("perf_func", rt = perf_func());
619c3a42 69 *
73ec82bf
AZ
70 * return rt;
71 * }
619c3a42 72 *
619c3a42 73 *
73ec82bf
AZ
74 * This will maintain the number of times 'perf_func()' is called, total
75 * number of instructions '<implementation>' plus function call overhead
76 * executed.
619c3a42 77 *
619c3a42
AZ
78 */
79
8790a8b4 80#if defined(__linux__) && defined(HAVE_LINUX_PERF_EVENT_H)
619c3a42
AZ
81struct 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
96void perf_counters_init(void);
97void perf_counters_destroy(void);
98void perf_counters_clear(void);
99
100uint64_t perf_counter_read(uint64_t *counter);
101void perf_counter_accumulate(struct perf_counter *counter,
102 uint64_t start_count);
103char *perf_counters_to_string(void);
104
105/* User access macros. */
73ec82bf
AZ
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 }
619c3a42 115#else
e8154139 116#define PERF(name, expr) { expr; }
d663136e
AZ
117
118static inline void perf_counters_init(void) {}
119static inline void perf_counters_destroy(void) {}
120static inline void perf_counters_clear(void) {}
121static inline char *
122perf_counters_to_string(void)
123{
9a6156bb 124 return xstrdup("Not Supported on this platform. Only available on Linux (version >= 2.6.32)");
d663136e
AZ
125}
126
619c3a42
AZ
127#endif
128
129#endif