perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]);
if (!(data.type & PERFCOUNTER_U64))
return;
- data.u64.add(amt);
- if (data.type & PERFCOUNTER_LONGRUNAVG)
+ if (data.type & PERFCOUNTER_LONGRUNAVG) {
data.avgcount.inc();
+ data.u64.add(amt);
+ data.avgcount2.inc();
+ } else {
+ data.u64.add(amt);
+ }
}
void PerfCounters::dec(int idx, uint64_t amt)
if (!(data.type & PERFCOUNTER_U64))
return;
data.u64.set(amt);
- if (data.type & PERFCOUNTER_LONGRUNAVG)
+ if (data.type & PERFCOUNTER_LONGRUNAVG) {
data.avgcount.inc();
+ data.u64.set(amt);
+ data.avgcount2.inc();
+ } else {
+ data.u64.set(amt);
+ }
}
uint64_t PerfCounters::get(int idx) const
perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]);
if (!(data.type & PERFCOUNTER_TIME))
return;
- data.u64.add(amt.to_nsec());
- if (data.type & PERFCOUNTER_LONGRUNAVG)
+ if (data.type & PERFCOUNTER_LONGRUNAVG) {
data.avgcount.inc();
+ data.u64.add(amt.to_nsec());
+ data.avgcount2.inc();
+ } else {
+ data.u64.add(amt.to_nsec());
+ }
}
void PerfCounters::tset(int idx, utime_t amt)
return make_pair(0, 0);
if (!(data.type & PERFCOUNTER_LONGRUNAVG))
return make_pair(0, 0);
- return make_pair(data.avgcount.read(), data.u64.read()/1000000);
+ pair<uint64_t,uint64_t> a = data.read_avg();
+ return make_pair(a.second, a.first / 1000000ull);
}
void PerfCounters::dump_formatted(Formatter *f, bool schema)
} else {
if (d->type & PERFCOUNTER_LONGRUNAVG) {
f->open_object_section(d->name);
+ pair<uint64_t,uint64_t> a = d->read_avg();
if (d->type & PERFCOUNTER_U64) {
- f->dump_unsigned("avgcount", d->avgcount.read());
- f->dump_unsigned("sum", d->u64.read());
+ f->dump_unsigned("avgcount", a.second);
+ f->dump_unsigned("sum", a.first);
} else if (d->type & PERFCOUNTER_TIME) {
- f->dump_unsigned("avgcount", d->avgcount.read());
- uint64_t v = d->u64.read();
+ f->dump_unsigned("avgcount", a.second);
f->dump_format_unquoted("sum", "%"PRId64".%09"PRId64,
- v / 1000000000ull,
- v % 1000000000ull);
+ a.first / 1000000000ull,
+ a.first % 1000000000ull);
} else {
assert(0);
}
: name(NULL),
type(PERFCOUNTER_NONE),
u64(0),
- avgcount(0)
+ avgcount(0),
+ avgcount2(0)
{}
perf_counter_data_any_d(const perf_counter_data_any_d& other)
: name(other.name),
type(other.type),
- u64(other.u64.read()),
- avgcount(other.avgcount.read())
- {}
+ u64(other.u64.read()) {
+ pair<uint64_t,uint64_t> a = other.read_avg();
+ u64.set(a.first);
+ avgcount.set(a.second);
+ avgcount2.set(a.second);
+ }
void write_schema_json(char *buf, size_t buf_sz) const;
void write_json(char *buf, size_t buf_sz) const;
enum perfcounter_type_d type;
atomic64_t u64;
atomic64_t avgcount;
+ atomic64_t avgcount2;
perf_counter_data_any_d& operator=(const perf_counter_data_any_d& other) {
name = other.name;
type = other.type;
- u64.set(other.u64.read());
- avgcount.set(other.avgcount.read());
+ pair<uint64_t,uint64_t> a = other.read_avg();
+ u64.set(a.first);
+ avgcount.set(a.second);
+ avgcount2.set(a.second);
return *this;
}
+
+ /// read <sum, count> safely
+ pair<uint64_t,uint64_t> read_avg() const {
+ uint64_t sum, count;
+ do {
+ count = avgcount.read();
+ sum = u64.read();
+ } while (avgcount2.read() != count);
+ return make_pair(sum, count);
+ }
};
typedef std::vector<perf_counter_data_any_d> perf_counter_data_vec_t;