GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tracepoint.hpp
1 /*
2  * Copyright (c) 2009 Carnegie Mellon University.
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an "AS
13  * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14  * express or implied. See the License for the specific language
15  * governing permissions and limitations under the License.
16  *
17  * For more about this software visit:
18  *
19  * http://www.graphlab.ml.cmu.edu
20  *
21  */
22 
23 
24 #ifndef GRAPHLAB_UTIL_TRACEPOINT_HPP
25 #define GRAPHLAB_UTIL_TRACEPOINT_HPP
26 #include <iostream>
27 #include <vector>
28 #include <string>
29 #include <graphlab/util/timer.hpp>
30 #include <graphlab/util/branch_hints.hpp>
31 #include <graphlab/parallel/atomic.hpp>
32 #include <graphlab/parallel/atomic_ops.hpp>
33 
34 namespace graphlab{
35 
36 struct trace_count{
37  std::string name;
38  std::string description;
39  bool print_on_destruct;
40  graphlab::atomic<unsigned long long> count;
41  graphlab::atomic<unsigned long long> total;
42  unsigned long long minimum;
43  unsigned long long maximum;
44  inline trace_count(std::string name = "",
45  std::string description = "",
46  bool print_on_destruct = true):
47  name(name),
48  description(description),
49  print_on_destruct(print_on_destruct),
50  count(0),
51  total(0),
52  minimum(std::numeric_limits<unsigned long long>::max()),
53  maximum(0) { }
54 
55  /**
56  * Initializes the tracer with a name, a description
57  * and whether to print on destruction
58  */
59  inline void initialize(std::string n,
60  std::string desc,
61  bool print_out = true) {
62  name = n;
63  description = desc;
64  print_on_destruct = print_out;
65  }
66 
67  /**
68  * Adds an event time to the trace
69  */
70  inline void incorporate(unsigned long long val) __attribute__((always_inline)) {
71  count.inc();
72  total.inc(val);
73  while(1) {
74  unsigned long long m = minimum;
75  if (__likely__(val > m || graphlab::atomic_compare_and_swap(minimum, m, val))) break;
76  }
77  while(1) {
78  unsigned long long m = maximum;
79  if (__likely__(val < m || graphlab::atomic_compare_and_swap(maximum, m, val))) break;
80  }
81  }
82 
83  /**
84  * Adds the counts in a second tracer to the current tracer.
85  */
86  inline void incorporate(const trace_count &val) __attribute__((always_inline)) {
87  count.inc(val.count.value);
88  total.inc(val.total.value);
89  while(1) {
90  unsigned long long m = minimum;
91  if (__likely__(val.minimum > m || graphlab::atomic_compare_and_swap(minimum, m, val.minimum))) break;
92  }
93  while(1) {
94  unsigned long long m = maximum;
95  if (__likely__(val.maximum < m || graphlab::atomic_compare_and_swap(maximum, m, val.maximum))) break;
96  }
97  }
98 
99  /**
100  * Adds the counts in a second tracer to the current tracer.
101  */
102  inline trace_count& operator+=(trace_count &val) {
103  incorporate(val);
104  return *this;
105  }
106 
107  /**
108  * Destructor. Will print to cout if initialize() is called
109  * with "true" as the 3rd argument
110  */
111  ~trace_count();
112 
113  /**
114  * Prints the tracer counts
115  */
116  void print(std::ostream& out, unsigned long long tpersec = 0) const;
117 };
118 
119 } // namespace
120 
121 /**
122  * DECLARE_TRACER(name)
123  * creates a tracing object with a given name. This creates a variable
124  * called "name" which is of type trace_count. and is equivalent to:
125  *
126  * graphlab::trace_count name;
127  *
128  * The primary reason to use this macro instead of just writing
129  * the code above directly, is that the macro is ignored and compiles
130  * to nothing when tracepoints are disabled.
131  *
132  *
133  * INITIALIZE_TRACER(name, desc)
134  * The object with name "name" created by DECLARE_TRACER must be in scope.
135  * This initializes the tracer "name" with a description, and
136  * configures the tracer to print when the tracer "name" is destroyed.
137  *
138  *
139  * INITIALIZE_TRACER_NO_PRINT(name, desc)
140  * The object with name "name" created by DECLARE_TRACER must be in scope.
141  * This initializes the tracer "name" with a description, and
142  * configures the tracer to NOT print when the tracer "name" is destroyed.
143  *
144  * BEGIN_TRACEPOINT(name)
145  * END_TRACEPOINT(name)
146  * The object with name "name" created by DECLARE_TRACER must be in scope.
147  * Times a block of code. Every END_TRACEPOINT must be matched with a
148  * BEGIN_TRACEPOINT within the same scope. Tracepoints are parallel.
149  *
150 
151 
152 Example Usage:
153  DECLARE_TRACER(classname_someevent)
154  INITIALIZE_TRACER(classname_someevent, "hello world");
155  Then later on...
156  BEGIN_TRACEPOINT(classname_someevent)
157  ...
158  END_TRACEPOINT(classname_someevent)
159  *
160 */
161 
162 
163 #ifdef USE_TRACEPOINT
164 #define DECLARE_TRACER(name) graphlab::trace_count name;
165 
166 #define INITIALIZE_TRACER(name, description) name.initialize(#name, description);
167 #define INITIALIZE_TRACER_NO_PRINT(name, description) name.initialize(#name, description, false);
168 
169 #define BEGIN_TRACEPOINT(name) unsigned long long __ ## name ## _trace_ = rdtsc();
170 #define END_TRACEPOINT(name) name.incorporate(rdtsc() - __ ## name ## _trace_);
171 #define END_AND_BEGIN_TRACEPOINT(endname, beginname) unsigned long long __ ## beginname ## _trace_ = rdtsc(); \
172  endname.incorporate(__ ## beginname ## _trace_ - __ ## endname ## _trace_);
173 
174 #define CREATE_ACCUMULATING_TRACEPOINT(name) graphlab::trace_count __ ## name ## _acc_trace_; \
175  unsigned long long __ ## name ## _acc_trace_elem_;
176 #define BEGIN_ACCUMULATING_TRACEPOINT(name) __ ## name ## _acc_trace_elem_ = rdtsc();
177 #define END_ACCUMULATING_TRACEPOINT(name) __ ## name ## _acc_trace_.incorporate(rdtsc() - __ ## name ## _acc_trace_elem_);
178 
179 #define END_AND_BEGIN_ACCUMULATING_TRACEPOINT(endname, beginname) __ ## beginname ## _acc_trace_elem_ = rdtsc(); \
180  __ ## endname ## _acc_trace_.incorporate(__ ## beginname ## _acc_trace_elem_ - __ ## endname ## _acc_trace_elem_)
181 
182 #define STORE_ACCUMULATING_TRACEPOINT(name) name.incorporate(__ ## name ## _acc_trace_);
183 #else
184 #define DECLARE_TRACER(name)
185 #define INITIALIZE_TRACER(name, description)
186 #define INITIALIZE_TRACER_NO_PRINT(name, description)
187 
188 #define BEGIN_TRACEPOINT(name)
189 #define END_TRACEPOINT(name)
190 
191 #define CREATE_ACCUMULATING_TRACEPOINT(name)
192 #define BEGIN_ACCUMULATING_TRACEPOINT(name)
193 #define END_ACCUMULATING_TRACEPOINT(name)
194 #define STORE_ACCUMULATING_TRACEPOINT(name)
195 
196 #define END_AND_BEGIN_ACCUMULATING_TRACEPOINT(endname, beginname)
197 #define END_AND_BEGIN_TRACEPOINT(endname, beginname)
198 #endif
199 
200 #endif