File indexing completed on 2024-05-12 15:56:58
0001 /* 0002 * SPDX-FileCopyrightText: 2017 Bernhard Liebl <poke1024@gmx.de> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef KRITA_KIS_SCALAR_TRACKER_H 0008 #define KRITA_KIS_SCALAR_TRACKER_H 0009 0010 #include "kis_shared.h" 0011 #include <kritaglobal_export.h> 0012 0013 #include <QQueue> 0014 #include <QElapsedTimer> 0015 #include <QDebug> 0016 0017 #include <boost/heap/fibonacci_heap.hpp> 0018 0019 #include <boost/accumulators/accumulators.hpp> 0020 #include <boost/accumulators/statistics/stats.hpp> 0021 #include <boost/accumulators/statistics/rolling_mean.hpp> 0022 #include <boost/accumulators/statistics/rolling_variance.hpp> 0023 0024 template<typename T> 0025 class KisRollingMax { 0026 public: 0027 KisRollingMax(int windowSize) : m_windowSize(windowSize) { 0028 } 0029 0030 void push(T value) { 0031 while (m_samples.size() > m_windowSize) { 0032 m_values.erase(m_samples.dequeue()); 0033 } 0034 0035 m_samples.enqueue(m_values.push(value)); 0036 } 0037 0038 T max() const { 0039 if (m_values.empty()) { 0040 throw std::runtime_error("no values to get max of"); 0041 } else { 0042 return m_values.top(); 0043 } 0044 } 0045 0046 private: 0047 const int m_windowSize; 0048 0049 typedef boost::heap::fibonacci_heap<T> heap_type; 0050 0051 QQueue<typename heap_type::handle_type> m_samples; 0052 heap_type m_values; 0053 }; 0054 0055 template<typename T> 0056 class KisScalarTracker : public KisShared { 0057 public: 0058 /** 0059 * Create a tracker with the given window size. 0060 * @param window The maximum number of elements to take into account for calculation 0061 * of max, mean and variance values. 0062 */ 0063 KisScalarTracker(const QString &name, int windowSize = 500) : 0064 m_name(name), 0065 m_windowSize(windowSize), 0066 m_addCount(0), 0067 m_max(windowSize), 0068 m_acc(boost::accumulators::tag::rolling_window::window_size = windowSize) 0069 { 0070 m_printTimer.start(); 0071 } 0072 0073 virtual ~KisScalarTracker() { 0074 } 0075 0076 /** 0077 * Add a scalar. 0078 * @param value the scalar to be added. 0079 */ 0080 virtual void push(T value) { 0081 m_max.push(value); 0082 m_acc(value); 0083 m_addCount++; 0084 0085 if (m_addCount >= m_windowSize || m_printTimer.elapsed() >= 1000) { 0086 m_printTimer.restart(); 0087 QString s = format(boost::accumulators::rolling_mean(m_acc), 0088 boost::accumulators::rolling_variance(m_acc), 0089 m_max.max()); 0090 print(s); 0091 m_addCount = 0; 0092 } 0093 0094 } 0095 0096 protected: 0097 /** 0098 * Print out a message. 0099 * @param message the message to print 0100 */ 0101 virtual void print(const QString &message) { 0102 qInfo() << qUtf8Printable(message); 0103 } 0104 0105 /** 0106 * Formats a message for printing. 0107 * @param mean the mean scalar in the window 0108 * @param variance the variance of the scalar in the window 0109 * @param max the max scalar in the window 0110 */ 0111 virtual QString format(qint64 mean, qint64 variance, qint64 max) { 0112 return QString("%1: mean %2 ms, var %3, max %4 ms").arg(m_name).arg(mean).arg(variance).arg(max); 0113 } 0114 0115 private: 0116 const QString m_name; 0117 const int m_windowSize; 0118 int m_addCount; 0119 0120 QElapsedTimer m_printTimer; 0121 0122 KisRollingMax<T> m_max; 0123 0124 // see https://svn.boost.org/trac10/ticket/11437 0125 typedef boost::accumulators::stats< 0126 boost::accumulators::tag::lazy_rolling_mean, 0127 boost::accumulators::tag::rolling_variance> stats; 0128 0129 boost::accumulators::accumulator_set<T, stats> m_acc; 0130 }; 0131 0132 /** 0133 * KisLatencyTracker tracks the time it takes events to reach a certain point in the program. 0134 */ 0135 0136 class KRITAGLOBAL_EXPORT KisLatencyTracker : public KisScalarTracker<qint64> { 0137 public: 0138 /** 0139 * Create a tracker with the given window size. 0140 * @param window The maximum number of elements to take into account for calculation 0141 * of max, mean and variance values. 0142 */ 0143 KisLatencyTracker(int windowSize = 500); 0144 0145 /** 0146 * Register that an event with the given timestamp has arrived just now. 0147 * @param timestamp Timestamp of the event that just arrived (the difference to the 0148 * current time is the latency). 0149 */ 0150 virtual void push(qint64 timestamp) override; 0151 0152 protected: 0153 /** 0154 * @return The timestamp of "right now" in a frame that is comparable to those 0155 * timestamps given to push(). 0156 */ 0157 virtual qint64 currentTimestamp() const = 0; 0158 }; 0159 0160 #endif //KRITA_KIS_SCALAR_TRACKER_H