]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2011 New Dream Network | |
7 | * Copyright (C) 2017 OVH | |
8 | * | |
9 | * This is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License version 2.1, as published by the Free Software | |
12 | * Foundation. See file COPYING. | |
13 | * | |
14 | */ | |
15 | ||
7c673cae FG |
16 | #include "common/perf_counters.h" |
17 | #include "common/dout.h" | |
7c673cae FG |
18 | #include "common/valgrind.h" |
19 | ||
7c673cae FG |
20 | using std::ostringstream; |
21 | ||
22 | PerfCountersCollection::PerfCountersCollection(CephContext *cct) | |
23 | : m_cct(cct), | |
24 | m_lock("PerfCountersCollection") | |
25 | { | |
26 | } | |
27 | ||
28 | PerfCountersCollection::~PerfCountersCollection() | |
29 | { | |
30 | clear(); | |
31 | } | |
32 | ||
33 | void PerfCountersCollection::add(class PerfCounters *l) | |
34 | { | |
35 | Mutex::Locker lck(m_lock); | |
36 | ||
37 | // make sure the name is unique | |
38 | perf_counters_set_t::iterator i; | |
39 | i = m_loggers.find(l); | |
40 | while (i != m_loggers.end()) { | |
41 | ostringstream ss; | |
42 | ss << l->get_name() << "-" << (void*)l; | |
43 | l->set_name(ss.str()); | |
44 | i = m_loggers.find(l); | |
45 | } | |
46 | ||
47 | m_loggers.insert(l); | |
48 | ||
49 | for (unsigned int i = 0; i < l->m_data.size(); ++i) { | |
50 | PerfCounters::perf_counter_data_any_d &data = l->m_data[i]; | |
51 | ||
52 | std::string path = l->get_name(); | |
53 | path += "."; | |
54 | path += data.name; | |
55 | ||
3efd9988 | 56 | by_path[path] = {&data, l}; |
7c673cae FG |
57 | } |
58 | } | |
59 | ||
60 | void PerfCountersCollection::remove(class PerfCounters *l) | |
61 | { | |
62 | Mutex::Locker lck(m_lock); | |
63 | ||
64 | for (unsigned int i = 0; i < l->m_data.size(); ++i) { | |
65 | PerfCounters::perf_counter_data_any_d &data = l->m_data[i]; | |
66 | ||
67 | std::string path = l->get_name(); | |
68 | path += "."; | |
69 | path += data.name; | |
70 | ||
71 | by_path.erase(path); | |
72 | } | |
73 | ||
74 | perf_counters_set_t::iterator i = m_loggers.find(l); | |
75 | assert(i != m_loggers.end()); | |
76 | m_loggers.erase(i); | |
77 | } | |
78 | ||
79 | void PerfCountersCollection::clear() | |
80 | { | |
81 | Mutex::Locker lck(m_lock); | |
82 | perf_counters_set_t::iterator i = m_loggers.begin(); | |
83 | perf_counters_set_t::iterator i_end = m_loggers.end(); | |
84 | for (; i != i_end; ) { | |
85 | m_loggers.erase(i++); | |
86 | } | |
87 | ||
88 | by_path.clear(); | |
89 | } | |
90 | ||
91 | bool PerfCountersCollection::reset(const std::string &name) | |
92 | { | |
93 | bool result = false; | |
94 | Mutex::Locker lck(m_lock); | |
95 | perf_counters_set_t::iterator i = m_loggers.begin(); | |
96 | perf_counters_set_t::iterator i_end = m_loggers.end(); | |
97 | ||
98 | if (!strcmp(name.c_str(), "all")) { | |
99 | while (i != i_end) { | |
100 | (*i)->reset(); | |
101 | ++i; | |
102 | } | |
103 | result = true; | |
104 | } else { | |
105 | while (i != i_end) { | |
106 | if (!name.compare((*i)->get_name())) { | |
107 | (*i)->reset(); | |
108 | result = true; | |
109 | break; | |
110 | } | |
111 | ++i; | |
112 | } | |
113 | } | |
114 | ||
115 | return result; | |
116 | } | |
117 | ||
118 | ||
119 | /** | |
120 | * Serialize current values of performance counters. Optionally | |
121 | * output the schema instead, or filter output to a particular | |
122 | * PerfCounters or particular named counter. | |
123 | * | |
124 | * @param logger name of subsystem logger, e.g. "mds_cache", may be empty | |
125 | * @param counter name of counter within subsystem, e.g. "num_strays", | |
126 | * may be empty. | |
127 | * @param schema if true, output schema instead of current data. | |
128 | * @param histograms if true, dump histogram values, | |
129 | * if false dump all non-histogram counters | |
130 | */ | |
131 | void PerfCountersCollection::dump_formatted_generic( | |
132 | Formatter *f, | |
133 | bool schema, | |
134 | bool histograms, | |
135 | const std::string &logger, | |
136 | const std::string &counter) | |
137 | { | |
138 | Mutex::Locker lck(m_lock); | |
139 | f->open_object_section("perfcounter_collection"); | |
140 | ||
141 | for (perf_counters_set_t::iterator l = m_loggers.begin(); | |
142 | l != m_loggers.end(); ++l) { | |
143 | // Optionally filter on logger name, pass through counter filter | |
144 | if (logger.empty() || (*l)->get_name() == logger) { | |
145 | (*l)->dump_formatted_generic(f, schema, histograms, counter); | |
146 | } | |
147 | } | |
148 | f->close_section(); | |
149 | } | |
150 | ||
151 | void PerfCountersCollection::with_counters(std::function<void( | |
152 | const PerfCountersCollection::CounterMap &)> fn) const | |
153 | { | |
154 | Mutex::Locker lck(m_lock); | |
155 | ||
156 | fn(by_path); | |
157 | } | |
158 | ||
159 | // --------------------------- | |
160 | ||
161 | PerfCounters::~PerfCounters() | |
162 | { | |
163 | } | |
164 | ||
165 | void PerfCounters::inc(int idx, uint64_t amt) | |
166 | { | |
167 | if (!m_cct->_conf->perf) | |
168 | return; | |
169 | ||
170 | assert(idx > m_lower_bound); | |
171 | assert(idx < m_upper_bound); | |
172 | perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); | |
173 | if (!(data.type & PERFCOUNTER_U64)) | |
174 | return; | |
175 | if (data.type & PERFCOUNTER_LONGRUNAVG) { | |
31f18b77 FG |
176 | data.avgcount++; |
177 | data.u64 += amt; | |
178 | data.avgcount2++; | |
7c673cae | 179 | } else { |
31f18b77 | 180 | data.u64 += amt; |
7c673cae FG |
181 | } |
182 | } | |
183 | ||
184 | void PerfCounters::dec(int idx, uint64_t amt) | |
185 | { | |
186 | if (!m_cct->_conf->perf) | |
187 | return; | |
188 | ||
189 | assert(idx > m_lower_bound); | |
190 | assert(idx < m_upper_bound); | |
191 | perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); | |
192 | assert(!(data.type & PERFCOUNTER_LONGRUNAVG)); | |
193 | if (!(data.type & PERFCOUNTER_U64)) | |
194 | return; | |
31f18b77 | 195 | data.u64 -= amt; |
7c673cae FG |
196 | } |
197 | ||
198 | void PerfCounters::set(int idx, uint64_t amt) | |
199 | { | |
200 | if (!m_cct->_conf->perf) | |
201 | return; | |
202 | ||
203 | assert(idx > m_lower_bound); | |
204 | assert(idx < m_upper_bound); | |
205 | perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); | |
206 | if (!(data.type & PERFCOUNTER_U64)) | |
207 | return; | |
208 | ||
209 | ANNOTATE_BENIGN_RACE_SIZED(&data.u64, sizeof(data.u64), | |
210 | "perf counter atomic"); | |
211 | if (data.type & PERFCOUNTER_LONGRUNAVG) { | |
31f18b77 FG |
212 | data.avgcount++; |
213 | data.u64 = amt; | |
214 | data.avgcount2++; | |
7c673cae | 215 | } else { |
31f18b77 | 216 | data.u64 = amt; |
7c673cae FG |
217 | } |
218 | } | |
219 | ||
220 | uint64_t PerfCounters::get(int idx) const | |
221 | { | |
222 | if (!m_cct->_conf->perf) | |
223 | return 0; | |
224 | ||
225 | assert(idx > m_lower_bound); | |
226 | assert(idx < m_upper_bound); | |
227 | const perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); | |
228 | if (!(data.type & PERFCOUNTER_U64)) | |
229 | return 0; | |
31f18b77 | 230 | return data.u64; |
7c673cae FG |
231 | } |
232 | ||
233 | void PerfCounters::tinc(int idx, utime_t amt, uint32_t avgcount) | |
234 | { | |
235 | if (!m_cct->_conf->perf) | |
236 | return; | |
237 | ||
238 | assert(idx > m_lower_bound); | |
239 | assert(idx < m_upper_bound); | |
240 | perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); | |
241 | if (!(data.type & PERFCOUNTER_TIME)) | |
242 | return; | |
243 | if (data.type & PERFCOUNTER_LONGRUNAVG) { | |
31f18b77 FG |
244 | data.avgcount++; |
245 | data.u64 += amt.to_nsec(); | |
246 | data.avgcount2++; | |
7c673cae | 247 | } else { |
31f18b77 | 248 | data.u64 += amt.to_nsec(); |
7c673cae FG |
249 | } |
250 | } | |
251 | ||
252 | void PerfCounters::tinc(int idx, ceph::timespan amt, uint32_t avgcount) | |
253 | { | |
254 | if (!m_cct->_conf->perf) | |
255 | return; | |
256 | ||
257 | assert(idx > m_lower_bound); | |
258 | assert(idx < m_upper_bound); | |
259 | perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); | |
260 | if (!(data.type & PERFCOUNTER_TIME)) | |
261 | return; | |
262 | if (data.type & PERFCOUNTER_LONGRUNAVG) { | |
31f18b77 FG |
263 | data.avgcount++; |
264 | data.u64 += amt.count(); | |
265 | data.avgcount2++; | |
7c673cae | 266 | } else { |
31f18b77 | 267 | data.u64 += amt.count(); |
7c673cae FG |
268 | } |
269 | } | |
270 | ||
271 | void PerfCounters::tset(int idx, utime_t amt) | |
272 | { | |
273 | if (!m_cct->_conf->perf) | |
274 | return; | |
275 | ||
276 | assert(idx > m_lower_bound); | |
277 | assert(idx < m_upper_bound); | |
278 | perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); | |
279 | if (!(data.type & PERFCOUNTER_TIME)) | |
280 | return; | |
31f18b77 | 281 | data.u64 = amt.to_nsec(); |
7c673cae FG |
282 | if (data.type & PERFCOUNTER_LONGRUNAVG) |
283 | ceph_abort(); | |
284 | } | |
285 | ||
286 | utime_t PerfCounters::tget(int idx) const | |
287 | { | |
288 | if (!m_cct->_conf->perf) | |
289 | return utime_t(); | |
290 | ||
291 | assert(idx > m_lower_bound); | |
292 | assert(idx < m_upper_bound); | |
293 | const perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); | |
294 | if (!(data.type & PERFCOUNTER_TIME)) | |
295 | return utime_t(); | |
31f18b77 | 296 | uint64_t v = data.u64; |
7c673cae FG |
297 | return utime_t(v / 1000000000ull, v % 1000000000ull); |
298 | } | |
299 | ||
300 | void PerfCounters::hinc(int idx, int64_t x, int64_t y) | |
301 | { | |
302 | if (!m_cct->_conf->perf) | |
303 | return; | |
304 | ||
305 | assert(idx > m_lower_bound); | |
306 | assert(idx < m_upper_bound); | |
307 | ||
308 | perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); | |
31f18b77 | 309 | assert(data.type == (PERFCOUNTER_HISTOGRAM | PERFCOUNTER_COUNTER | PERFCOUNTER_U64)); |
7c673cae FG |
310 | assert(data.histogram); |
311 | ||
312 | data.histogram->inc(x, y); | |
313 | } | |
314 | ||
315 | pair<uint64_t, uint64_t> PerfCounters::get_tavg_ms(int idx) const | |
316 | { | |
317 | if (!m_cct->_conf->perf) | |
318 | return make_pair(0, 0); | |
319 | ||
320 | assert(idx > m_lower_bound); | |
321 | assert(idx < m_upper_bound); | |
322 | const perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); | |
323 | if (!(data.type & PERFCOUNTER_TIME)) | |
324 | return make_pair(0, 0); | |
325 | if (!(data.type & PERFCOUNTER_LONGRUNAVG)) | |
326 | return make_pair(0, 0); | |
327 | pair<uint64_t,uint64_t> a = data.read_avg(); | |
328 | return make_pair(a.second, a.first / 1000000ull); | |
329 | } | |
330 | ||
331 | void PerfCounters::reset() | |
332 | { | |
333 | perf_counter_data_vec_t::iterator d = m_data.begin(); | |
334 | perf_counter_data_vec_t::iterator d_end = m_data.end(); | |
335 | ||
336 | while (d != d_end) { | |
337 | d->reset(); | |
338 | ++d; | |
339 | } | |
340 | } | |
341 | ||
342 | void PerfCounters::dump_formatted_generic(Formatter *f, bool schema, | |
343 | bool histograms, const std::string &counter) | |
344 | { | |
345 | f->open_object_section(m_name.c_str()); | |
346 | ||
347 | for (perf_counter_data_vec_t::const_iterator d = m_data.begin(); | |
348 | d != m_data.end(); ++d) { | |
349 | if (!counter.empty() && counter != d->name) { | |
350 | // Optionally filter on counter name | |
351 | continue; | |
352 | } | |
353 | ||
354 | // Switch between normal and histogram view | |
355 | bool is_histogram = (d->type & PERFCOUNTER_HISTOGRAM) != 0; | |
356 | if (is_histogram != histograms) { | |
357 | continue; | |
358 | } | |
359 | ||
360 | if (schema) { | |
361 | f->open_object_section(d->name); | |
31f18b77 FG |
362 | // we probably should not have exposed this raw field (with bit |
363 | // values), but existing plugins rely on it so we're stuck with | |
364 | // it. | |
7c673cae FG |
365 | f->dump_int("type", d->type); |
366 | ||
31f18b77 FG |
367 | if (d->type & PERFCOUNTER_COUNTER) { |
368 | f->dump_string("metric_type", "counter"); | |
369 | } else { | |
370 | f->dump_string("metric_type", "gauge"); | |
371 | } | |
372 | ||
373 | if (d->type & PERFCOUNTER_LONGRUNAVG) { | |
374 | if (d->type & PERFCOUNTER_TIME) { | |
375 | f->dump_string("value_type", "real-integer-pair"); | |
376 | } else { | |
377 | f->dump_string("value_type", "integer-integer-pair"); | |
378 | } | |
379 | } else if (d->type & PERFCOUNTER_HISTOGRAM) { | |
380 | if (d->type & PERFCOUNTER_TIME) { | |
381 | f->dump_string("value_type", "real-2d-histogram"); | |
382 | } else { | |
383 | f->dump_string("value_type", "integer-2d-histogram"); | |
384 | } | |
7c673cae | 385 | } else { |
31f18b77 FG |
386 | if (d->type & PERFCOUNTER_TIME) { |
387 | f->dump_string("value_type", "real"); | |
388 | } else { | |
389 | f->dump_string("value_type", "integer"); | |
390 | } | |
7c673cae FG |
391 | } |
392 | ||
31f18b77 | 393 | f->dump_string("description", d->description ? d->description : ""); |
7c673cae FG |
394 | if (d->nick != NULL) { |
395 | f->dump_string("nick", d->nick); | |
396 | } else { | |
397 | f->dump_string("nick", ""); | |
398 | } | |
3efd9988 | 399 | f->dump_int("priority", get_adjusted_priority(d->prio)); |
1adf2230 AA |
400 | |
401 | if (d->unit == NONE) { | |
402 | f->dump_string("units", "none"); | |
403 | } else if (d->unit == BYTES) { | |
404 | f->dump_string("units", "bytes"); | |
405 | } | |
7c673cae FG |
406 | f->close_section(); |
407 | } else { | |
408 | if (d->type & PERFCOUNTER_LONGRUNAVG) { | |
409 | f->open_object_section(d->name); | |
410 | pair<uint64_t,uint64_t> a = d->read_avg(); | |
411 | if (d->type & PERFCOUNTER_U64) { | |
412 | f->dump_unsigned("avgcount", a.second); | |
413 | f->dump_unsigned("sum", a.first); | |
414 | } else if (d->type & PERFCOUNTER_TIME) { | |
415 | f->dump_unsigned("avgcount", a.second); | |
416 | f->dump_format_unquoted("sum", "%" PRId64 ".%09" PRId64, | |
417 | a.first / 1000000000ull, | |
418 | a.first % 1000000000ull); | |
31f18b77 FG |
419 | uint64_t count = a.second; |
420 | uint64_t sum_ns = a.first; | |
421 | if (count) { | |
422 | uint64_t avg_ns = sum_ns / count; | |
423 | f->dump_format_unquoted("avgtime", "%" PRId64 ".%09" PRId64, | |
424 | avg_ns / 1000000000ull, | |
425 | avg_ns % 1000000000ull); | |
426 | } else { | |
427 | f->dump_format_unquoted("avgtime", "%" PRId64 ".%09" PRId64, 0, 0); | |
428 | } | |
7c673cae FG |
429 | } else { |
430 | ceph_abort(); | |
431 | } | |
432 | f->close_section(); | |
433 | } else if (d->type & PERFCOUNTER_HISTOGRAM) { | |
31f18b77 | 434 | assert(d->type == (PERFCOUNTER_HISTOGRAM | PERFCOUNTER_COUNTER | PERFCOUNTER_U64)); |
7c673cae FG |
435 | assert(d->histogram); |
436 | f->open_object_section(d->name); | |
437 | d->histogram->dump_formatted(f); | |
438 | f->close_section(); | |
439 | } else { | |
31f18b77 | 440 | uint64_t v = d->u64; |
7c673cae FG |
441 | if (d->type & PERFCOUNTER_U64) { |
442 | f->dump_unsigned(d->name, v); | |
443 | } else if (d->type & PERFCOUNTER_TIME) { | |
444 | f->dump_format_unquoted(d->name, "%" PRId64 ".%09" PRId64, | |
445 | v / 1000000000ull, | |
446 | v % 1000000000ull); | |
447 | } else { | |
448 | ceph_abort(); | |
449 | } | |
450 | } | |
451 | } | |
452 | } | |
453 | f->close_section(); | |
454 | } | |
455 | ||
456 | const std::string &PerfCounters::get_name() const | |
457 | { | |
458 | return m_name; | |
459 | } | |
460 | ||
461 | PerfCounters::PerfCounters(CephContext *cct, const std::string &name, | |
462 | int lower_bound, int upper_bound) | |
463 | : m_cct(cct), | |
464 | m_lower_bound(lower_bound), | |
465 | m_upper_bound(upper_bound), | |
466 | m_name(name.c_str()), | |
467 | m_lock_name(std::string("PerfCounters::") + name.c_str()), | |
468 | m_lock(m_lock_name.c_str()) | |
469 | { | |
470 | m_data.resize(upper_bound - lower_bound - 1); | |
471 | } | |
472 | ||
473 | PerfCountersBuilder::PerfCountersBuilder(CephContext *cct, const std::string &name, | |
474 | int first, int last) | |
475 | : m_perf_counters(new PerfCounters(cct, name, first, last)) | |
476 | { | |
477 | } | |
478 | ||
479 | PerfCountersBuilder::~PerfCountersBuilder() | |
480 | { | |
481 | if (m_perf_counters) | |
482 | delete m_perf_counters; | |
483 | m_perf_counters = NULL; | |
484 | } | |
485 | ||
486 | void PerfCountersBuilder::add_u64_counter( | |
487 | int idx, const char *name, | |
1adf2230 | 488 | const char *description, const char *nick, int prio, int unit) |
7c673cae FG |
489 | { |
490 | add_impl(idx, name, description, nick, prio, | |
1adf2230 | 491 | PERFCOUNTER_U64 | PERFCOUNTER_COUNTER, unit); |
7c673cae FG |
492 | } |
493 | ||
494 | void PerfCountersBuilder::add_u64( | |
495 | int idx, const char *name, | |
1adf2230 | 496 | const char *description, const char *nick, int prio, int unit) |
7c673cae | 497 | { |
1adf2230 | 498 | add_impl(idx, name, description, nick, prio, PERFCOUNTER_U64, unit); |
7c673cae FG |
499 | } |
500 | ||
501 | void PerfCountersBuilder::add_u64_avg( | |
502 | int idx, const char *name, | |
1adf2230 | 503 | const char *description, const char *nick, int prio, int unit) |
7c673cae FG |
504 | { |
505 | add_impl(idx, name, description, nick, prio, | |
1adf2230 | 506 | PERFCOUNTER_U64 | PERFCOUNTER_LONGRUNAVG, unit); |
7c673cae FG |
507 | } |
508 | ||
509 | void PerfCountersBuilder::add_time( | |
510 | int idx, const char *name, | |
511 | const char *description, const char *nick, int prio) | |
512 | { | |
513 | add_impl(idx, name, description, nick, prio, PERFCOUNTER_TIME); | |
514 | } | |
515 | ||
516 | void PerfCountersBuilder::add_time_avg( | |
517 | int idx, const char *name, | |
518 | const char *description, const char *nick, int prio) | |
519 | { | |
520 | add_impl(idx, name, description, nick, prio, | |
521 | PERFCOUNTER_TIME | PERFCOUNTER_LONGRUNAVG); | |
522 | } | |
523 | ||
31f18b77 | 524 | void PerfCountersBuilder::add_u64_counter_histogram( |
7c673cae FG |
525 | int idx, const char *name, |
526 | PerfHistogramCommon::axis_config_d x_axis_config, | |
527 | PerfHistogramCommon::axis_config_d y_axis_config, | |
1adf2230 | 528 | const char *description, const char *nick, int prio, int unit) |
7c673cae FG |
529 | { |
530 | add_impl(idx, name, description, nick, prio, | |
1adf2230 | 531 | PERFCOUNTER_U64 | PERFCOUNTER_HISTOGRAM | PERFCOUNTER_COUNTER, unit, |
7c673cae FG |
532 | unique_ptr<PerfHistogram<>>{new PerfHistogram<>{x_axis_config, y_axis_config}}); |
533 | } | |
534 | ||
535 | void PerfCountersBuilder::add_impl( | |
536 | int idx, const char *name, | |
1adf2230 | 537 | const char *description, const char *nick, int prio, int ty, int unit, |
7c673cae FG |
538 | unique_ptr<PerfHistogram<>> histogram) |
539 | { | |
540 | assert(idx > m_perf_counters->m_lower_bound); | |
541 | assert(idx < m_perf_counters->m_upper_bound); | |
542 | PerfCounters::perf_counter_data_vec_t &vec(m_perf_counters->m_data); | |
543 | PerfCounters::perf_counter_data_any_d | |
544 | &data(vec[idx - m_perf_counters->m_lower_bound - 1]); | |
545 | assert(data.type == PERFCOUNTER_NONE); | |
546 | data.name = name; | |
547 | data.description = description; | |
548 | // nick must be <= 4 chars | |
549 | if (nick) { | |
550 | assert(strlen(nick) <= 4); | |
551 | } | |
552 | data.nick = nick; | |
3efd9988 | 553 | data.prio = prio ? prio : prio_default; |
7c673cae | 554 | data.type = (enum perfcounter_type_d)ty; |
1adf2230 | 555 | data.unit = (enum unit_t) unit; |
7c673cae FG |
556 | data.histogram = std::move(histogram); |
557 | } | |
558 | ||
559 | PerfCounters *PerfCountersBuilder::create_perf_counters() | |
560 | { | |
561 | PerfCounters::perf_counter_data_vec_t::const_iterator d = m_perf_counters->m_data.begin(); | |
562 | PerfCounters::perf_counter_data_vec_t::const_iterator d_end = m_perf_counters->m_data.end(); | |
31f18b77 | 563 | for (; d != d_end; ++d) { |
7c673cae | 564 | assert(d->type != PERFCOUNTER_NONE); |
31f18b77 FG |
565 | assert(d->type & (PERFCOUNTER_U64 | PERFCOUNTER_TIME)); |
566 | } | |
7c673cae FG |
567 | |
568 | PerfCounters *ret = m_perf_counters; | |
569 | m_perf_counters = NULL; | |
570 | return ret; | |
571 | } | |
572 |