From: Sage Weil Date: Sun, 11 May 2014 18:18:36 +0000 (-0700) Subject: common/perf_counters: use atomics instead of a mutex X-Git-Tag: v0.82~44^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=45281d9b64f19392d9d1505c2efe4e7975bebaa0;p=ceph.git common/perf_counters: use atomics instead of a mutex The mutex is way too expensive. Signed-off-by: Sage Weil --- diff --git a/src/common/perf_counters.cc b/src/common/perf_counters.cc index 4fe1354fa637..06edb4199103 100644 --- a/src/common/perf_counters.cc +++ b/src/common/perf_counters.cc @@ -101,15 +101,14 @@ void PerfCounters::inc(int idx, uint64_t amt) if (!m_cct->_conf->perf) return; - Mutex::Locker lck(m_lock); assert(idx > m_lower_bound); assert(idx < m_upper_bound); perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); if (!(data.type & PERFCOUNTER_U64)) return; - data.u64 += amt; + data.u64.add(amt); if (data.type & PERFCOUNTER_LONGRUNAVG) - data.avgcount++; + data.avgcount.inc(); } void PerfCounters::dec(int idx, uint64_t amt) @@ -117,15 +116,13 @@ void PerfCounters::dec(int idx, uint64_t amt) if (!m_cct->_conf->perf) return; - Mutex::Locker lck(m_lock); assert(idx > m_lower_bound); assert(idx < m_upper_bound); perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); assert(!(data.type & PERFCOUNTER_LONGRUNAVG)); if (!(data.type & PERFCOUNTER_U64)) return; - assert(data.u64 >= amt); - data.u64 -= amt; + data.u64.sub(amt); } void PerfCounters::set(int idx, uint64_t amt) @@ -133,15 +130,14 @@ void PerfCounters::set(int idx, uint64_t amt) if (!m_cct->_conf->perf) return; - Mutex::Locker lck(m_lock); assert(idx > m_lower_bound); assert(idx < m_upper_bound); perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); if (!(data.type & PERFCOUNTER_U64)) return; - data.u64 = amt; + data.u64.set(amt); if (data.type & PERFCOUNTER_LONGRUNAVG) - data.avgcount++; + data.avgcount.inc(); } uint64_t PerfCounters::get(int idx) const @@ -149,13 +145,12 @@ uint64_t PerfCounters::get(int idx) const if (!m_cct->_conf->perf) return 0; - Mutex::Locker lck(m_lock); assert(idx > m_lower_bound); assert(idx < m_upper_bound); const perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); if (!(data.type & PERFCOUNTER_U64)) return 0; - return data.u64; + return data.u64.read(); } void PerfCounters::tinc(int idx, utime_t amt) @@ -163,15 +158,14 @@ void PerfCounters::tinc(int idx, utime_t amt) if (!m_cct->_conf->perf) return; - Mutex::Locker lck(m_lock); assert(idx > m_lower_bound); assert(idx < m_upper_bound); perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); if (!(data.type & PERFCOUNTER_TIME)) return; - data.u64 += amt.to_nsec(); + data.u64.add(amt.to_nsec()); if (data.type & PERFCOUNTER_LONGRUNAVG) - data.avgcount++; + data.avgcount.inc(); } void PerfCounters::tset(int idx, utime_t amt) @@ -179,13 +173,12 @@ void PerfCounters::tset(int idx, utime_t amt) if (!m_cct->_conf->perf) return; - Mutex::Locker lck(m_lock); assert(idx > m_lower_bound); assert(idx < m_upper_bound); perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); if (!(data.type & PERFCOUNTER_TIME)) return; - data.u64 = amt.to_nsec(); + data.u64.set(amt.to_nsec()); if (data.type & PERFCOUNTER_LONGRUNAVG) assert(0); } @@ -195,13 +188,13 @@ utime_t PerfCounters::tget(int idx) const if (!m_cct->_conf->perf) return utime_t(); - Mutex::Locker lck(m_lock); assert(idx > m_lower_bound); assert(idx < m_upper_bound); const perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); if (!(data.type & PERFCOUNTER_TIME)) return utime_t(); - return utime_t(data.u64 / 1000000000ull, data.u64 % 1000000000ull); + uint64_t v = data.u64.read(); + return utime_t(v / 1000000000ull, v % 1000000000ull); } pair PerfCounters::get_tavg_ms(int idx) const @@ -209,7 +202,6 @@ pair PerfCounters::get_tavg_ms(int idx) const if (!m_cct->_conf->perf) return make_pair(0, 0); - Mutex::Locker lck(m_lock); assert(idx > m_lower_bound); assert(idx < m_upper_bound); const perf_counter_data_any_d& data(m_data[idx - m_lower_bound - 1]); @@ -217,13 +209,11 @@ pair PerfCounters::get_tavg_ms(int idx) const return make_pair(0, 0); if (!(data.type & PERFCOUNTER_LONGRUNAVG)) return make_pair(0, 0); - return make_pair(data.avgcount, data.u64/1000000); + return make_pair(data.avgcount.read(), data.u64.read()/1000000); } void PerfCounters::dump_formatted(Formatter *f, bool schema) { - Mutex::Locker lck(m_lock); - f->open_object_section(m_name.c_str()); perf_counter_data_vec_t::const_iterator d = m_data.begin(); perf_counter_data_vec_t::const_iterator d_end = m_data.end(); @@ -240,24 +230,26 @@ void PerfCounters::dump_formatted(Formatter *f, bool schema) if (d->type & PERFCOUNTER_LONGRUNAVG) { f->open_object_section(d->name); if (d->type & PERFCOUNTER_U64) { - f->dump_unsigned("avgcount", d->avgcount); - f->dump_unsigned("sum", d->u64); + f->dump_unsigned("avgcount", d->avgcount.read()); + f->dump_unsigned("sum", d->u64.read()); } else if (d->type & PERFCOUNTER_TIME) { - f->dump_unsigned("avgcount", d->avgcount); + f->dump_unsigned("avgcount", d->avgcount.read()); + uint64_t v = d->u64.read(); f->dump_format_unquoted("sum", "%"PRId64".%09"PRId64, - d->u64 / 1000000000ull, - d->u64 % 1000000000ull); + v / 1000000000ull, + v % 1000000000ull); } else { assert(0); } f->close_section(); } else { + uint64_t v = d->u64.read(); if (d->type & PERFCOUNTER_U64) { - f->dump_unsigned(d->name, d->u64); + f->dump_unsigned(d->name, v); } else if (d->type & PERFCOUNTER_TIME) { f->dump_format_unquoted(d->name, "%"PRId64".%09"PRId64, - d->u64 / 1000000000ull, - d->u64 % 1000000000ull); + v / 1000000000ull, + v % 1000000000ull); } else { assert(0); } @@ -287,14 +279,6 @@ PerfCounters::PerfCounters(CephContext *cct, const std::string &name, m_data.resize(upper_bound - lower_bound - 1); } -PerfCounters::perf_counter_data_any_d::perf_counter_data_any_d() - : name(NULL), - type(PERFCOUNTER_NONE), - u64(0), - avgcount(0) -{ -} - PerfCountersBuilder::PerfCountersBuilder(CephContext *cct, const std::string &name, int first, int last) : m_perf_counters(new PerfCounters(cct, name, first, last)) diff --git a/src/common/perf_counters.h b/src/common/perf_counters.h index f4651c69f1ca..f4f650771bcc 100644 --- a/src/common/perf_counters.h +++ b/src/common/perf_counters.h @@ -111,14 +111,34 @@ private: /** Represents a PerfCounters data element. */ struct perf_counter_data_any_d { - perf_counter_data_any_d(); + perf_counter_data_any_d() + : name(NULL), + type(PERFCOUNTER_NONE), + u64(0), + avgcount(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()) + {} + void write_schema_json(char *buf, size_t buf_sz) const; void write_json(char *buf, size_t buf_sz) const; const char *name; enum perfcounter_type_d type; - uint64_t u64; - uint64_t avgcount; + atomic64_t u64; + atomic64_t avgcount; + + 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()); + return *this; + } }; typedef std::vector perf_counter_data_vec_t;