]> git.proxmox.com Git - mirror_ovs.git/blob - lib/perf-counter.h
b5b72e5ebbb70165d911186fdb367a962fddce3b
[mirror_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 * Function instruction counter sample point Usage
48 * ================================================
49 *
50 * There are two macros provided:
51 *
52 * Macro 'PERF_FUNCTON_COUNT_BEGIN' needs to be inserted towards the
53 * beginning of the function where local variables are declared.
54 *
55 * Macro 'PERF_FUNCTON_COUNT_END' needs to appear in the same function,
56 * some where below 'PERF_FUNCTION_COUNT_BEGIN', usually towards of
57 * a function.
58 *
59 * For example:
60 *
61 * void my_func() {
62 * int some_local_variable;
63 *
64 * PERF_FUNCTION_COUNT_BEGIN;
65 *
66 * < implementation >
67 *
68 * PERF_FUNCTION_COUNT_END
69 * }
70 *
71 * This will maintain the number of times 'my_func()' is called, total
72 * number of instructions '<implementation>' executed during all those calls.
73 *
74 * Currently there are two limitation:
75 * 1). At most one pair can appear in the same variable scope.
76 * 2). The Macros use function name as the counter name for display.
77 * Thus, all functions in one annotation session are required to
78 * have unique names.
79 *
80 * Note, there is no requirement for those macros to be balanced.
81 * For example:
82 *
83 * void my_func(int i){
84 *
85 * PERF_FUNCTION_COUNT_BEGIN;
86 *
87 * if (i == 300) {
88 * PERF_FUNCTION_COUNT_END;
89 * return;
90 * } else {
91 * <some code>
92 * }
93 * }
94 * will work just fine.
95 */
96
97 #ifdef __linux__
98 struct perf_counter {
99 const char *name;
100 bool once;
101 uint64_t n_events;
102 uint64_t total_count;
103 };
104
105 #define PERF_COUNTER_ONCE_INITIALIZER(name) \
106 { \
107 name, \
108 false, \
109 0, \
110 0, \
111 }
112
113 void perf_counters_init(void);
114 void perf_counters_destroy(void);
115 void perf_counters_clear(void);
116
117 uint64_t perf_counter_read(uint64_t *counter);
118 void perf_counter_accumulate(struct perf_counter *counter,
119 uint64_t start_count);
120 char *perf_counters_to_string(void);
121
122 /* User access macros. */
123 #define PERF_FUNCTION_BEGIN \
124 static struct perf_counter x__ = PERF_COUNTER_ONCE_INITIALIZER(__func__); \
125 uint64_t start_count__ = perf_counter_read(&start_count__); \
126
127 #define PERF_FUNCTION_END \
128 perf_counter_accumulate(&x__, start_count__);
129
130 #else
131
132 #define PERF_FUNCTON_COUNT_BEGIN
133 #define PERF_FUNCTON_COUNT_END
134 #endif
135
136 #endif