Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

common, osd, tools: Add histograms to performance counters #12829

Merged
merged 1 commit into from Feb 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Expand Up @@ -392,6 +392,7 @@ set(libcommon_files
common/PrebufferedStreambuf.cc
common/BackTrace.cc
common/perf_counters.cc
common/perf_histogram.cc
common/mutex_debug.cc
common/Mutex.cc
common/OutputDataSocket.cc
Expand Down
14 changes: 14 additions & 0 deletions src/common/ceph_context.cc
Expand Up @@ -4,6 +4,7 @@
* Ceph - scalable distributed file system
*
* Copyright (C) 2011 New Dream Network
* Copyright (C) 2017 OVH
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -393,6 +394,17 @@ void CephContext::do_command(std::string command, cmdmap_t& cmdmap,
command == "perf schema") {
_perf_counters_collection->dump_formatted(f, true);
}
else if (command == "perf histogram dump") {
std::string logger;
std::string counter;
cmd_getval(this, cmdmap, "logger", logger);
cmd_getval(this, cmdmap, "counter", counter);
_perf_counters_collection->dump_formatted_histograms(f, false, logger,
counter);
}
else if (command == "perf histogram schema") {
_perf_counters_collection->dump_formatted_histograms(f, true);
}
else if (command == "perf reset") {
std::string var;
string section = command;
Expand Down Expand Up @@ -555,8 +567,10 @@ CephContext::CephContext(uint32_t module_type_, int init_flags_)
_admin_socket->register_command("1", "1", _admin_hook, "");
_admin_socket->register_command("perf dump", "perf dump name=logger,type=CephString,req=false name=counter,type=CephString,req=false", _admin_hook, "dump perfcounters value");
_admin_socket->register_command("perfcounters_schema", "perfcounters_schema", _admin_hook, "");
_admin_socket->register_command("perf histogram dump", "perf histogram dump name=logger,type=CephString,req=false name=counter,type=CephString,req=false", _admin_hook, "dump perf histogram values");
_admin_socket->register_command("2", "2", _admin_hook, "");
_admin_socket->register_command("perf schema", "perf schema", _admin_hook, "dump perfcounters schema");
_admin_socket->register_command("perf histogram schema", "perf histogram schema", _admin_hook, "dump perf histogram schema");
_admin_socket->register_command("perf reset", "perf reset name=var,type=CephString", _admin_hook, "perf reset <name>: perf reset all or one perfcounter name");
_admin_socket->register_command("config show", "config show", _admin_hook, "dump current config settings");
_admin_socket->register_command("config set", "config set name=var,type=CephString name=val,type=CephString,n=N", _admin_hook, "config set <field> <val> [<val> ...]: set a config variable");
Expand Down
52 changes: 47 additions & 5 deletions src/common/perf_counters.cc
Expand Up @@ -4,6 +4,7 @@
* Ceph - scalable distributed file system
*
* Copyright (C) 2011 New Dream Network
* Copyright (C) 2017 OVH
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -135,10 +136,13 @@ bool PerfCountersCollection::reset(const std::string &name)
* @param counter name of counter within subsystem, e.g. "num_strays",
* may be empty.
* @param schema if true, output schema instead of current data.
* @param histograms if true, dump histogram values,
* if false dump all non-histogram counters
*/
void PerfCountersCollection::dump_formatted(
void PerfCountersCollection::dump_formatted_generic(
Formatter *f,
bool schema,
bool histograms,
const std::string &logger,
const std::string &counter)
{
Expand All @@ -149,7 +153,7 @@ void PerfCountersCollection::dump_formatted(
l != m_loggers.end(); ++l) {
// Optionally filter on logger name, pass through counter filter
if (logger.empty() || (*l)->get_name() == logger) {
(*l)->dump_formatted(f, schema, counter);
(*l)->dump_formatted_generic(f, schema, histograms, counter);
}
}
f->close_section();
Expand Down Expand Up @@ -304,6 +308,21 @@ utime_t PerfCounters::tget(int idx) const
return utime_t(v / 1000000000ull, v % 1000000000ull);
}

void PerfCounters::hinc(int idx, int64_t x, int64_t y)
{
if (!m_cct->_conf->perf)
return;

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_HISTOGRAM | PERFCOUNTER_U64));
assert(data.histogram);

data.histogram->inc(x, y);
}

pair<uint64_t, uint64_t> PerfCounters::get_tavg_ms(int idx) const
{
if (!m_cct->_conf->perf)
Expand Down Expand Up @@ -331,8 +350,8 @@ void PerfCounters::reset()
}
}

void PerfCounters::dump_formatted(Formatter *f, bool schema,
const std::string &counter)
void PerfCounters::dump_formatted_generic(Formatter *f, bool schema,
bool histograms, const std::string &counter)
{
f->open_object_section(m_name.c_str());

Expand All @@ -343,6 +362,12 @@ void PerfCounters::dump_formatted(Formatter *f, bool schema,
continue;
}

// Switch between normal and histogram view
bool is_histogram = (d->type & PERFCOUNTER_HISTOGRAM) != 0;
if (is_histogram != histograms) {
continue;
}

if (schema) {
f->open_object_section(d->name);
f->dump_int("type", d->type);
Expand Down Expand Up @@ -375,6 +400,12 @@ void PerfCounters::dump_formatted(Formatter *f, bool schema,
ceph_abort();
}
f->close_section();
} else if (d->type & PERFCOUNTER_HISTOGRAM) {
assert(d->type == (PERFCOUNTER_HISTOGRAM | PERFCOUNTER_U64));
assert(d->histogram);
f->open_object_section(d->name);
d->histogram->dump_formatted(f);
f->close_section();
} else {
uint64_t v = d->u64.read();
if (d->type & PERFCOUNTER_U64) {
Expand Down Expand Up @@ -452,8 +483,18 @@ void PerfCountersBuilder::add_time_avg(int idx, const char *name,
add_impl(idx, name, description, nick, PERFCOUNTER_TIME | PERFCOUNTER_LONGRUNAVG);
}

void PerfCountersBuilder::add_histogram(int idx, const char *name,
PerfHistogramCommon::axis_config_d x_axis_config,
PerfHistogramCommon::axis_config_d y_axis_config,
const char *description, const char *nick)
{
add_impl(idx, name, description, nick, PERFCOUNTER_U64 | PERFCOUNTER_HISTOGRAM,
unique_ptr<PerfHistogram<>>{new PerfHistogram<>{x_axis_config, y_axis_config}});
}

void PerfCountersBuilder::add_impl(int idx, const char *name,
const char *description, const char *nick, int ty)
const char *description, const char *nick, int ty,
unique_ptr<PerfHistogram<>> histogram)
{
assert(idx > m_perf_counters->m_lower_bound);
assert(idx < m_perf_counters->m_upper_bound);
Expand All @@ -465,6 +506,7 @@ void PerfCountersBuilder::add_impl(int idx, const char *name,
data.description = description;
data.nick = nick;
data.type = (enum perfcounter_type_d)ty;
data.histogram = std::move(histogram);
}

PerfCounters *PerfCountersBuilder::create_perf_counters()
Expand Down
69 changes: 48 additions & 21 deletions src/common/perf_counters.h
Expand Up @@ -4,6 +4,7 @@
* Ceph - scalable distributed file system
*
* Copyright (C) 2011 New Dream Network
* Copyright (C) 2017 OVH
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand All @@ -17,6 +18,7 @@
#define CEPH_COMMON_PERF_COUNTERS_H

#include "common/config_obs.h"
#include "common/perf_histogram.h"
#include "common/Mutex.h"
#include "include/utime.h"

Expand All @@ -27,6 +29,7 @@
#include <stdint.h>
#include <string>
#include <vector>
#include <memory>

class CephContext;
class PerfCountersBuilder;
Expand All @@ -38,8 +41,10 @@ enum perfcounter_type_d : uint8_t
PERFCOUNTER_U64 = 0x2,
PERFCOUNTER_LONGRUNAVG = 0x4,
PERFCOUNTER_COUNTER = 0x8,
PERFCOUNTER_HISTOGRAM = 0x10,
};


/*
* A PerfCounters object is usually associated with a single subsystem.
* It contains counters which we modify to track performance and throughput
Expand All @@ -49,11 +54,12 @@ enum perfcounter_type_d : uint8_t
* 1) integer values & counters
* 2) floating-point values & counters
* 3) floating-point averages
* 4) 2D histograms of quantized value pairs
*
* The difference between values and counters is in how they are initialized
* The difference between values, counters and histograms is in how they are initialized
* and accessed. For a counter, use the inc(counter, amount) function (note
* that amount defaults to 1 if you don't set it). For a value, use the
* set(index, value) function.
* set(index, value) function. For histogram use the hinc(value1, value2) function.
* (For time, use the tinc and tset variants.)
*
* If for some reason you would like to reset your counters, you can do so using
Expand Down Expand Up @@ -88,6 +94,9 @@ class PerfCounters
u64.set(a.first);
avgcount.set(a.second);
avgcount2.set(a.second);
if (other.histogram) {
histogram.reset(new PerfHistogram<>(*other.histogram));
}
}

const char *name;
Expand All @@ -97,6 +106,7 @@ class PerfCounters
atomic64_t u64;
atomic64_t avgcount;
atomic64_t avgcount2;
std::unique_ptr<PerfHistogram<>> histogram;

void reset()
{
Expand All @@ -105,18 +115,9 @@ class PerfCounters
avgcount.set(0);
avgcount2.set(0);
}
}

perf_counter_data_any_d& operator=(const perf_counter_data_any_d& other) {
name = other.name;
description = other.description;
nick = other.nick;
type = other.type;
pair<uint64_t,uint64_t> a = other.read_avg();
u64.set(a.first);
avgcount.set(a.second);
avgcount2.set(a.second);
return *this;
if (histogram) {
histogram->reset();
}
}

/// read <sum, count> safely
Expand Down Expand Up @@ -160,9 +161,17 @@ class PerfCounters
void tinc(int idx, ceph::timespan v);
utime_t tget(int idx) const;

void hinc(int idx, int64_t x, int64_t y);

void reset();
void dump_formatted(ceph::Formatter *f, bool schema,
const std::string &counter = "");
const std::string &counter = "") {
dump_formatted_generic(f, schema, false, counter);
}
void dump_formatted_histograms(ceph::Formatter *f, bool schema,
const std::string &counter = "") {
dump_formatted_generic(f, schema, true, counter);
}
pair<uint64_t, uint64_t> get_tavg_ms(int idx) const;

const std::string& get_name() const;
Expand All @@ -175,6 +184,8 @@ class PerfCounters
int lower_bound, int upper_bound);
PerfCounters(const PerfCounters &rhs);
PerfCounters& operator=(const PerfCounters &rhs);
void dump_formatted_generic(ceph::Formatter *f, bool schema, bool histograms,
const std::string &counter = "");

typedef std::vector<perf_counter_data_any_d> perf_counter_data_vec_t;

Expand Down Expand Up @@ -214,18 +225,29 @@ class PerfCountersCollection
void remove(class PerfCounters *l);
void clear();
bool reset(const std::string &name);
void dump_formatted(
ceph::Formatter *f,
bool schema,
const std::string &logger = "",
const std::string &counter = "");

void dump_formatted(ceph::Formatter *f, bool schema,
const std::string &logger = "",
const std::string &counter = "") {
dump_formatted_generic(f, schema, false, logger, counter);
}

void dump_formatted_histograms(ceph::Formatter *f, bool schema,
const std::string &logger = "",
const std::string &counter = "") {
dump_formatted_generic(f, schema, true, logger, counter);
}

typedef std::map<std::string,
PerfCounters::perf_counter_data_any_d *> CounterMap;

void with_counters(std::function<void(const CounterMap &)>) const;

private:
void dump_formatted_generic(ceph::Formatter *f, bool schema, bool histograms,
const std::string &logger = "",
const std::string &counter = "");

CephContext *m_cct;

/** Protects m_loggers */
Expand Down Expand Up @@ -262,12 +284,17 @@ class PerfCountersBuilder
const char *description=NULL, const char *nick = NULL);
void add_time_avg(int key, const char *name,
const char *description=NULL, const char *nick = NULL);
void add_histogram(int key, const char* name,
PerfHistogramCommon::axis_config_d x_axis_config,
PerfHistogramCommon::axis_config_d y_axis_config,
const char *description=NULL, const char* nick = NULL);
PerfCounters* create_perf_counters();
private:
PerfCountersBuilder(const PerfCountersBuilder &rhs);
PerfCountersBuilder& operator=(const PerfCountersBuilder &rhs);
void add_impl(int idx, const char *name,
const char *description, const char *nick, int ty);
const char *description, const char *nick, int ty,
unique_ptr<PerfHistogram<>> histogram = nullptr);

PerfCounters *m_perf_counters;
};
Expand Down