Merge pull request #4269 from clemahieu/stats_lasy_time_sampling
Lazy steady clock sampling within nano::stats since the timestamps are only needed when stat sampling is configured. Change stat data structure to an unordered map for O(1) access.
This commit is contained in:
commit
8ebea1176e
2 changed files with 44 additions and 34 deletions
|
@ -391,52 +391,62 @@ void nano::stats::update (uint32_t key_a, uint64_t value)
|
|||
static file_writer log_count (config.log_counters_filename);
|
||||
static file_writer log_sample (config.log_samples_filename);
|
||||
|
||||
auto now (std::chrono::steady_clock::now ());
|
||||
|
||||
nano::unique_lock<nano::mutex> lock{ stat_mutex };
|
||||
if (!stopped)
|
||||
{
|
||||
auto entry (get_entry_impl (key_a, config.interval, config.capacity));
|
||||
auto has_interval_counter = [&] () {
|
||||
return config.log_interval_counters > 0;
|
||||
};
|
||||
auto has_sampling = [&] () {
|
||||
return config.sampling_enabled && entry->sample_interval > 0;
|
||||
};
|
||||
|
||||
// Counters
|
||||
auto old (entry->counter.get_value ());
|
||||
entry->counter.add (value);
|
||||
entry->counter.add (value, has_sampling ()); // Only update timestamp when sampling is enabled as this has a performance impact
|
||||
entry->count_observers.notify (old, entry->counter.get_value ());
|
||||
|
||||
std::chrono::duration<double, std::milli> duration = now - log_last_count_writeout;
|
||||
if (config.log_interval_counters > 0 && duration.count () > config.log_interval_counters)
|
||||
if (has_interval_counter () || has_sampling ())
|
||||
{
|
||||
log_counters_impl (log_count);
|
||||
log_last_count_writeout = now;
|
||||
}
|
||||
|
||||
// Samples
|
||||
if (config.sampling_enabled && entry->sample_interval > 0)
|
||||
{
|
||||
entry->sample_current.add (value, false);
|
||||
|
||||
std::chrono::duration<double, std::milli> duration = now - entry->sample_start_time;
|
||||
if (duration.count () > entry->sample_interval)
|
||||
auto now = std::chrono::steady_clock::now (); // Only sample clock if necessary as this impacts node performance due to frequent usage
|
||||
if (has_interval_counter ())
|
||||
{
|
||||
entry->sample_start_time = now;
|
||||
|
||||
// Make a snapshot of samples for thread safety and to get a stable container
|
||||
entry->sample_current.set_timestamp (std::chrono::system_clock::now ());
|
||||
entry->samples.push_back (entry->sample_current);
|
||||
entry->sample_current.set_value (0);
|
||||
|
||||
if (!entry->sample_observers.empty ())
|
||||
std::chrono::duration<double, std::milli> duration = now - log_last_count_writeout;
|
||||
if (duration.count () > config.log_interval_counters)
|
||||
{
|
||||
auto snapshot (entry->samples);
|
||||
entry->sample_observers.notify (snapshot);
|
||||
log_counters_impl (log_count);
|
||||
log_last_count_writeout = now;
|
||||
}
|
||||
}
|
||||
|
||||
// Log sink
|
||||
duration = now - log_last_sample_writeout;
|
||||
if (config.log_interval_samples > 0 && duration.count () > config.log_interval_samples)
|
||||
// Samples
|
||||
if (has_sampling ())
|
||||
{
|
||||
entry->sample_current.add (value, false);
|
||||
|
||||
std::chrono::duration<double, std::milli> duration = now - entry->sample_start_time;
|
||||
if (duration.count () > entry->sample_interval)
|
||||
{
|
||||
log_samples_impl (log_sample);
|
||||
log_last_sample_writeout = now;
|
||||
entry->sample_start_time = now;
|
||||
|
||||
// Make a snapshot of samples for thread safety and to get a stable container
|
||||
entry->sample_current.set_timestamp (std::chrono::system_clock::now ());
|
||||
entry->samples.push_back (entry->sample_current);
|
||||
entry->sample_current.set_value (0);
|
||||
|
||||
if (!entry->sample_observers.empty ())
|
||||
{
|
||||
auto snapshot (entry->samples);
|
||||
entry->sample_observers.notify (snapshot);
|
||||
}
|
||||
|
||||
// Log sink
|
||||
duration = now - log_last_sample_writeout;
|
||||
if (config.log_interval_samples > 0 && duration.count () > config.log_interval_samples)
|
||||
{
|
||||
log_samples_impl (log_sample);
|
||||
log_last_sample_writeout = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
|
||||
#include <chrono>
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace nano
|
||||
{
|
||||
|
@ -440,7 +440,7 @@ private:
|
|||
nano::stats_config config;
|
||||
|
||||
/** Stat entries are sorted by key to simplify processing of log output */
|
||||
std::map<uint32_t, std::shared_ptr<nano::stat_entry>> entries;
|
||||
std::unordered_map<uint32_t, std::shared_ptr<nano::stat_entry>> entries;
|
||||
std::chrono::steady_clock::time_point log_last_count_writeout{ std::chrono::steady_clock::now () };
|
||||
std::chrono::steady_clock::time_point log_last_sample_writeout{ std::chrono::steady_clock::now () };
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue