diff --git a/include/maxscale/response_stat.hh b/include/maxscale/response_stat.hh index 90be34ed0..d4c437c60 100644 --- a/include/maxscale/response_stat.hh +++ b/include/maxscale/response_stat.hh @@ -16,42 +16,33 @@ #include #include -/** This could arguably be a utility, but is written specifically for rwsplit - * so it stays here at least for now. - */ namespace maxscale { /** - * Query response statistics. Uses median of N samples to filter noise, then - * uses those medians to calculate the average response time. - * The class makes an average of the durations between calls to query_started() - * and query_ended(). Once the stats are good, sync_time_reached(int max) returns true, - * based on the average containing at least max samples (or medians), or the time - * sync_duration (constructor arg) has passed since the last reset(). + * Query response time average for a backend. Uses median of N samples to filter noise, + * then uses those medians to calculate the average response time. */ class ResponseStat { public: /* - * @param num_filter_samples - collect num samples, use median - * @param num_synch_medians - this many medians before the average should be synced, or - * @param sync_duration - this much time between syncs. + * @param num_filter_samples - collect num samples, use median (digital filter) + * @param sync_duration - this much time between synchronize to server stats. */ - ResponseStat(int num_filter_samples = 5, - int num_synch_medians = 500, - maxbase::Duration sync_duration = std::chrono::seconds(5)); + ResponseStat(int num_filter_samples = 9, + maxbase::Duration sync_duration = std::chrono::milliseconds(250)); void query_started(); - void query_ended();// ok to call without a query_started - bool make_valid(); // make valid even if there are too few filter_samples + void query_ended(); // ok to call without a query_started + bool make_valid(); // make valid even if there are only filter_samples bool is_valid() const; int num_samples() const; maxbase::Duration average() const; - bool sync_time_reached(); // is it time to apply the average? + bool sync_time_reached(); // is it time to apply the average to the server? void reset(); + private: const int m_num_filter_samples; - const int m_num_synch_medians; const maxbase::Duration m_sync_duration; int m_sample_count; std::vector m_samples; // N sampels from which median is used diff --git a/server/core/response_stat.cc b/server/core/response_stat.cc index a198da64d..f090cab66 100644 --- a/server/core/response_stat.cc +++ b/server/core/response_stat.cc @@ -17,10 +17,8 @@ namespace maxscale { ResponseStat::ResponseStat(int num_filter_samples, - int num_synch_medians, maxbase::Duration sync_duration) : m_num_filter_samples {num_filter_samples} - , m_num_synch_medians{num_synch_medians} , m_sync_duration{sync_duration} , m_sample_count{0} , m_samples(num_filter_samples) @@ -39,7 +37,7 @@ void ResponseStat::query_ended() { if (m_last_start == maxbase::TimePoint()) { - // m_last_start is defaulted. Ignore, avoids extra logic in call sites. + // m_last_start is defaulted. Ignore, avoids extra logic at call sites. return; } m_samples[m_sample_count] = maxbase::Clock::now() - m_last_start; @@ -58,9 +56,11 @@ bool ResponseStat::make_valid() { if (!m_average.num_samples() && m_sample_count) { + std::sort(m_samples.begin(), m_samples.begin() + m_sample_count); maxbase::Duration new_sample = m_samples[m_sample_count / 2]; m_average.add(std::chrono::duration(new_sample).count()); m_sample_count = 0; + m_last_start = maxbase::TimePoint(); } return is_valid(); @@ -84,8 +84,7 @@ maxbase::Duration ResponseStat::average() const bool ResponseStat::sync_time_reached() { auto now = maxbase::Clock::now(); - bool reached = m_next_sync < now - || m_average.num_samples() >= m_num_synch_medians; + bool reached = m_next_sync < now; if (reached) {