diff options
author | Shauren <shauren.trinity@gmail.com> | 2022-04-08 21:33:38 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-06-10 16:21:28 +0200 |
commit | 3e60a922111c0868eb66bc5fac6ee3ef4a4dbb56 (patch) | |
tree | 53e02d50fdfe03a5413bf38a88bc39e1fa423e68 /src/common/Metric | |
parent | c669f5119c2fd66e28ba74db8b686248d27bd536 (diff) |
Core/Metric: Minor optimizations for metrics (reducing number of allocations)
(cherry picked from commit caaedbfa80870b10d58e124dd6bc6a637278da59)
Diffstat (limited to 'src/common/Metric')
-rw-r--r-- | src/common/Metric/Metric.cpp | 12 | ||||
-rw-r--r-- | src/common/Metric/Metric.h | 63 |
2 files changed, 42 insertions, 33 deletions
diff --git a/src/common/Metric/Metric.cpp b/src/common/Metric/Metric.cpp index 56e7b8cdf17..3bb42ff8454 100644 --- a/src/common/Metric/Metric.cpp +++ b/src/common/Metric/Metric.cpp @@ -122,16 +122,16 @@ bool Metric::ShouldLog(std::string const& category, int64 value) const return value >= threshold->second; } -void Metric::LogEvent(std::string const& category, std::string const& title, std::string const& description) +void Metric::LogEvent(std::string category, std::string title, std::string description) { using namespace std::chrono; MetricData* data = new MetricData; - data->Category = category; + data->Category = std::move(category); data->Timestamp = system_clock::now(); data->Type = METRIC_DATA_EVENT; - data->Title = title; - data->Text = description; + data->Title = std::move(title); + data->ValueOrEventText = std::move(description); _queuedData.Enqueue(data); } @@ -160,10 +160,10 @@ void Metric::SendBatch() switch (data->Type) { case METRIC_DATA_VALUE: - batchedData << "value=" << data->Value; + batchedData << "value=" << data->ValueOrEventText; break; case METRIC_DATA_EVENT: - batchedData << "title=\"" << data->Title << "\",text=\"" << data->Text << "\""; + batchedData << "title=\"" << data->Title << "\",text=\"" << data->ValueOrEventText << "\""; break; } diff --git a/src/common/Metric/Metric.h b/src/common/Metric/Metric.h index 6871d5fa021..140e6ec00e0 100644 --- a/src/common/Metric/Metric.h +++ b/src/common/Metric/Metric.h @@ -21,12 +21,13 @@ #include "Define.h" #include "Duration.h" #include "MPSCQueue.h" +#include "Optional.h" +#include <boost/container/small_vector.hpp> #include <functional> #include <iosfwd> #include <memory> #include <string> #include <unordered_map> -#include <vector> #include <utility> namespace Trinity @@ -44,21 +45,25 @@ enum MetricDataType METRIC_DATA_EVENT }; -typedef std::pair<std::string, std::string> MetricTag; +using MetricTag = std::pair<std::string, std::string>; +using MetricTagsVector = boost::container::small_vector<MetricTag, 2>; struct MetricData { std::string Category; SystemTimePoint Timestamp; MetricDataType Type; - std::vector<MetricTag> Tags; // LogValue-specific fields - std::string Value; + MetricTagsVector Tags; // LogEvent-specific fields std::string Title; - std::string Text; + + std::string ValueOrEventText; + + // intrusive queue link + std::atomic<MetricData*> QueueLink; }; class TC_COMMON_API Metric @@ -66,7 +71,7 @@ class TC_COMMON_API Metric private: std::iostream& GetDataStream() { return *_dataStream; } std::unique_ptr<std::iostream> _dataStream; - MPSCQueue<MetricData> _queuedData; + MPSCQueue<MetricData, &MetricData::QueueLink> _queuedData; std::unique_ptr<Trinity::Asio::DeadlineTimer> _batchTimer; std::unique_ptr<Trinity::Asio::DeadlineTimer> _overallStatusTimer; int32 _updateInterval = 0; @@ -108,22 +113,23 @@ public: void Update(); bool ShouldLog(std::string const& category, int64 value) const; - template<class T> - void LogValue(std::string const& category, T value, std::vector<MetricTag> tags) + template<class T, class... Tags> + void LogValue(std::string category, T value, Tags&&... tags) { using namespace std::chrono; MetricData* data = new MetricData; - data->Category = category; + data->Category = std::move(category); data->Timestamp = system_clock::now(); data->Type = METRIC_DATA_VALUE; - data->Value = FormatInfluxDBValue(value); - data->Tags = std::move(tags); + data->ValueOrEventText = FormatInfluxDBValue(value); + if constexpr (sizeof...(tags) > 0) + (data->Tags.emplace_back(std::move(tags)), ...); _queuedData.Enqueue(data); } - void LogEvent(std::string const& category, std::string const& title, std::string const& description); + void LogEvent(std::string category, std::string title, std::string description); void Unload(); bool IsEnabled() const { return _enabled; } @@ -137,14 +143,13 @@ class MetricStopWatch public: MetricStopWatch(LoggerType&& loggerFunc) : _logger(std::forward<LoggerType>(loggerFunc)), - _startTime(sMetric->IsEnabled() ? std::chrono::steady_clock::now() : TimePoint()) + _startTime(std::chrono::steady_clock::now()) { } ~MetricStopWatch() { - if (sMetric->IsEnabled()) - _logger(_startTime); + _logger(_startTime); } private: @@ -153,14 +158,17 @@ private: }; template<typename LoggerType> -MetricStopWatch<LoggerType> MakeMetricStopWatch(LoggerType&& loggerFunc) +Optional<MetricStopWatch<LoggerType>> MakeMetricStopWatch(LoggerType&& loggerFunc) { - return { std::forward<LoggerType>(loggerFunc) }; + if (!sMetric->IsEnabled()) + return {}; + + return MetricStopWatch<LoggerType>(std::forward<LoggerType>(loggerFunc)); } -#define TC_METRIC_TAG(name, value) { name, value } +#define TC_METRIC_TAG(name, value) MetricTag(name, value) -#define TC_METRIC_DO_CONCAT(a, b) a##b +#define TC_METRIC_DO_CONCAT(a, b) a ## b #define TC_METRIC_CONCAT(a, b) TC_METRIC_DO_CONCAT(a, b) #define TC_METRIC_UNIQUE_NAME(name) TC_METRIC_CONCAT(name, __LINE__) @@ -181,7 +189,7 @@ MetricStopWatch<LoggerType> MakeMetricStopWatch(LoggerType&& loggerFunc) #define TC_METRIC_VALUE(category, value, ...) \ do { \ if (sMetric->IsEnabled()) \ - sMetric->LogValue(category, value, { __VA_ARGS__ }); \ + sMetric->LogValue(category, value, ##__VA_ARGS__); \ } while (0) # else #define TC_METRIC_EVENT(category, title, description) \ @@ -197,24 +205,25 @@ MetricStopWatch<LoggerType> MakeMetricStopWatch(LoggerType&& loggerFunc) __pragma(warning(disable:4127)) \ do { \ if (sMetric->IsEnabled()) \ - sMetric->LogValue(category, value, { __VA_ARGS__ }); \ + sMetric->LogValue(category, value, ##__VA_ARGS__); \ } while (0) \ __pragma(warning(pop)) # endif #define TC_METRIC_TIMER(category, ...) \ - MetricStopWatch TC_METRIC_UNIQUE_NAME(__tc_metric_stop_watch) = MakeMetricStopWatch([&](TimePoint start) \ + auto TC_METRIC_UNIQUE_NAME(__tc_metric_stop_watch) = MakeMetricStopWatch([&](TimePoint start) \ { \ - sMetric->LogValue(category, std::chrono::steady_clock::now() - start, { __VA_ARGS__ }); \ + sMetric->LogValue(category, std::chrono::steady_clock::now() - start, ##__VA_ARGS__); \ }); # if defined WITH_DETAILED_METRICS #define TC_METRIC_DETAILED_TIMER(category, ...) \ - MetricStopWatch TC_METRIC_UNIQUE_NAME(__tc_metric_stop_watch) = MakeMetricStopWatch([&](TimePoint start) \ + auto TC_METRIC_UNIQUE_NAME(__tc_metric_stop_watch) = MakeMetricStopWatch([&](TimePoint start) \ { \ int64 duration = int64(std::chrono::duration_cast<Milliseconds>(std::chrono::steady_clock::now() - start).count()); \ - if (sMetric->ShouldLog(category, duration)) \ - sMetric->LogValue(category, duration, { __VA_ARGS__ }); \ + std::string category2 = category; + if (sMetric->ShouldLog(category2, duration)) \ + sMetric->LogValue(std::move(category2), duration, ##__VA_ARGS__); \ }); -#define TC_METRIC_DETAILED_NO_THRESHOLD_TIMER(category, ...) TC_METRIC_TIMER(category, __VA_ARGS__) +#define TC_METRIC_DETAILED_NO_THRESHOLD_TIMER(category, ...) TC_METRIC_TIMER(category, ##__VA_ARGS__) #define TC_METRIC_DETAILED_EVENT(category, title, description) TC_METRIC_EVENT(category, title, description) # else #define TC_METRIC_DETAILED_EVENT(category, title, description) ((void)0) |