in src/runtime/profiler.cpp [320:520]
void profiler::install(service_spec &)
{
s_task_code_max = dsn::task_code::max();
s_spec_profilers.reset(new task_spec_profiler[s_task_code_max + 1]);
task_ext_for_profiler::register_ext();
message_ext_for_profiler::register_ext();
for (int i = 0; i <= s_task_code_max; i++) {
if (i == TASK_CODE_INVALID)
continue;
std::string name(dsn::task_code(i).to_string());
std::string section_name = std::string("task.") + name;
task_spec *spec = task_spec::get(i);
CHECK_NOTNULL(spec, "");
s_spec_profilers[i].collect_call_count = dsn_config_get_value_bool(
section_name.c_str(),
"collect_call_count",
FLAGS_collect_call_count,
"whether to collect how many time this kind of tasks invoke each of other kinds tasks");
s_spec_profilers[i].call_counts = new std::atomic<int64_t>[ s_task_code_max + 1 ];
std::fill(s_spec_profilers[i].call_counts,
s_spec_profilers[i].call_counts + s_task_code_max + 1,
0);
s_spec_profilers[i].is_profile =
dsn_config_get_value_bool(section_name.c_str(),
"is_profile",
FLAGS_is_profile,
"whether to profile this kind of task");
if (!s_spec_profilers[i].is_profile)
continue;
if (dsn_config_get_value_bool(
section_name.c_str(),
"profiler::inqueue",
true,
"whether to profile the number of this kind of tasks in all queues"))
s_spec_profilers[i].ptr[TASK_IN_QUEUE].init_global_counter(
"zion",
"profiler",
(name + std::string(".inqueue")).c_str(),
COUNTER_TYPE_NUMBER,
"task number in all queues");
if (dsn_config_get_value_bool(section_name.c_str(),
"profiler::queue",
true,
"whether to profile the queuing time of a task"))
s_spec_profilers[i].ptr[TASK_QUEUEING_TIME_NS].init_global_counter(
"zion",
"profiler",
(name + std::string(".queue(ns)")).c_str(),
COUNTER_TYPE_NUMBER_PERCENTILES,
"latency due to waiting in the queue");
if (dsn_config_get_value_bool(section_name.c_str(),
"profiler::exec",
true,
"whether to profile the executing time of a task"))
s_spec_profilers[i].ptr[TASK_EXEC_TIME_NS].init_global_counter(
"zion",
"profiler",
(name + std::string(".exec(ns)")).c_str(),
COUNTER_TYPE_NUMBER_PERCENTILES,
"latency due to executing tasks");
if (dsn_config_get_value_bool(section_name.c_str(),
"profiler::qps",
true,
"whether to profile the qps of a task"))
s_spec_profilers[i].ptr[TASK_THROUGHPUT].init_global_counter(
"zion",
"profiler",
(name + std::string(".qps")).c_str(),
COUNTER_TYPE_RATE,
"task numbers per second");
if (dsn_config_get_value_bool(section_name.c_str(),
"profiler::cancelled",
true,
"whether to profile the cancelled times of a task"))
s_spec_profilers[i].ptr[TASK_CANCELLED].init_global_counter(
"zion",
"profiler",
(name + std::string(".cancelled")).c_str(),
COUNTER_TYPE_NUMBER,
"cancelled times of a specific task type");
if (spec->type == dsn_task_type_t::TASK_TYPE_RPC_REQUEST) {
if (dsn_config_get_value_bool(section_name.c_str(),
"profiler::latency.server",
true,
"whether to profile the server latency of a task")) {
s_spec_profilers[i].ptr[RPC_SERVER_LATENCY_NS].init_global_counter(
"zion",
"profiler",
(name + std::string(".latency.server")).c_str(),
COUNTER_TYPE_NUMBER_PERCENTILES,
"latency from enqueue point to reply point on the server side for RPC "
"tasks");
}
if (dsn_config_get_value_bool(section_name.c_str(),
"profiler::size.request.server",
false,
"whether to profile the size per request")) {
s_spec_profilers[i].ptr[RPC_SERVER_SIZE_PER_REQUEST_IN_BYTES].init_global_counter(
"zion",
"profiler",
(name + std::string(".size.request.server")).c_str(),
COUNTER_TYPE_NUMBER_PERCENTILES,
"");
}
if (dsn_config_get_value_bool(section_name.c_str(),
"profiler::size.response.server",
false,
"whether to profile the size per response")) {
s_spec_profilers[i].ptr[RPC_SERVER_SIZE_PER_RESPONSE_IN_BYTES].init_global_counter(
"zion",
"profiler",
(name + std::string(".size.response.server")).c_str(),
COUNTER_TYPE_NUMBER_PERCENTILES,
"");
}
if (dsn_config_get_value_bool(
section_name.c_str(),
"rpc_request_dropped_before_execution_when_timeout",
false,
"whether to profile the number of rpc dropped for timeout"))
s_spec_profilers[i].ptr[RPC_DROPPED_IF_TIMEOUT].init_global_counter(
"zion",
"profiler",
(name + std::string(".rpc.dropped")).c_str(),
COUNTER_TYPE_VOLATILE_NUMBER,
"rpc dropped if queue time exceed client timeout");
} else if (spec->type == dsn_task_type_t::TASK_TYPE_RPC_RESPONSE) {
if (dsn_config_get_value_bool(section_name.c_str(),
"profiler::latency.client",
true,
"whether to profile the client latency of a task"))
s_spec_profilers[i].ptr[RPC_CLIENT_NON_TIMEOUT_LATENCY_NS].init_global_counter(
"zion",
"profiler",
(name + std::string(".latency.client(ns)")).c_str(),
COUNTER_TYPE_NUMBER_PERCENTILES,
"latency from call point to enqueue point on the client side for RPC "
"tasks");
if (dsn_config_get_value_bool(section_name.c_str(),
"profiler::timeout.qps",
true,
"whether to profile the timeout qps of a task"))
s_spec_profilers[i].ptr[RPC_CLIENT_TIMEOUT_THROUGHPUT].init_global_counter(
"zion",
"profiler",
(name + std::string(".timeout.qps")).c_str(),
COUNTER_TYPE_RATE,
"time-out task numbers per second for RPC tasks");
} else if (spec->type == dsn_task_type_t::TASK_TYPE_AIO) {
if (dsn_config_get_value_bool(section_name.c_str(),
"profiler::latency",
true,
"whether to profile the latency of an AIO task"))
s_spec_profilers[i].ptr[AIO_LATENCY_NS].init_global_counter(
"zion",
"profiler",
(name + std::string(".latency(ns)")).c_str(),
COUNTER_TYPE_NUMBER_PERCENTILES,
"latency from call point to enqueue point for AIO tasks");
}
// we don't use perf_counter_ptr but perf_counter* in ptr[xxx] to avoid unnecessary memory
// access cost
// we need to add reference so that the counters won't go
// release_ref should be done when the profiler exits (which never happens right now so we
// omit that for the time being)
for (size_t j = 0; j < sizeof(s_spec_profilers[i].ptr) / sizeof(perf_counter *); j++) {
if (s_spec_profilers[i].ptr[j].get() != nullptr) {
s_spec_profilers[i].ptr[j]->add_ref();
}
}
spec->on_task_create.put_back(profiler_on_task_create, "profiler");
spec->on_task_enqueue.put_back(profiler_on_task_enqueue, "profiler");
spec->on_task_begin.put_back(profiler_on_task_begin, "profiler");
spec->on_task_end.put_back(profiler_on_task_end, "profiler");
spec->on_task_cancelled.put_back(profiler_on_task_cancelled, "profiler");
spec->on_task_wait_pre.put_back(profiler_on_task_wait_pre, "profiler");
spec->on_task_wait_post.put_back(profiler_on_task_wait_post, "profiler");
spec->on_task_cancel_post.put_back(profiler_on_task_cancel_post, "profiler");
spec->on_aio_call.put_back(profiler_on_aio_call, "profiler");
spec->on_aio_enqueue.put_back(profiler_on_aio_enqueue, "profiler");
spec->on_rpc_call.put_back(profiler_on_rpc_call, "profiler");
spec->on_rpc_request_enqueue.put_back(profiler_on_rpc_request_enqueue, "profiler");
spec->on_rpc_task_dropped.put_back(profile_on_rpc_task_dropped, "profiler");
spec->on_rpc_create_response.put_back(profiler_on_rpc_create_response, "profiler");
spec->on_rpc_reply.put_back(profiler_on_rpc_reply, "profiler");
spec->on_rpc_response_enqueue.put_back(profiler_on_rpc_response_enqueue, "profiler");
}
}