Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_update_time_monitor.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2011 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <QGlobalStatic>
10#include <QHash>
11#include <QSet>
12#include <QMutex>
13#include <QMutexLocker>
14#include <QPointF>
15#include <QRect>
16#include <QRegion>
17#include <QFile>
18#include <QDir>
19
20#include <QElapsedTimer>
21
22
23#include <kis_debug.h>
24#include <KisPortingUtils.h>
25#include "kis_image_config.h"
26
27
29
31
32
34{
36 : m_jobTime(0)
37 , m_updateTime(0) {}
38
39 QRegion dirtyRegion;
40
41 void start() {
42 m_timer.start();
43 }
44
45 void jobCompleted() {
46 m_jobTime = m_timer.restart();
47 }
48
50 m_updateTime = m_timer.restart();
51 }
52
53 qint64 jobTime() const {
54 return m_jobTime;
55 }
56
57 qint64 updateTime() const {
58 return m_updateTime;
59 }
60
61private:
62 QElapsedTimer m_timer;
63 qint64 m_jobTime;
65};
66
67struct Q_DECL_HIDDEN KisUpdateTimeMonitor::Private
68{
70 : jobsTime(0),
71 responseTime(0),
72 numTickets(0),
73 numUpdates(0),
74 mousePath(0.0),
75 loggingEnabled(false)
76 {
77 loggingEnabled = KisImageConfig(true).enablePerfLog();
78 }
79
80 QHash<void*, StrokeTicket*> preliminaryTickets;
81 QSet<StrokeTicket*> finishedTickets;
82
83 qint64 jobsTime;
85 qint32 numTickets;
86 qint32 numUpdates;
87 QMutex mutex;
88
89 qreal mousePath;
90 QPointF lastMousePos;
91 QElapsedTimer strokeTime;
93
95};
96
98 : m_d(new Private)
99{
100 if (m_d->loggingEnabled) {
101 QDir dir;
102 if (dir.exists("log")) {
103 dir.remove("log");
104 }
105 dir.mkdir("log");
106 }
107}
108
113
115{
116 return s_instance;
117}
118
120{
121 if (!m_d->loggingEnabled) return;
122
123 QMutexLocker locker(&m_d->mutex);
124
125 m_d->jobsTime = 0;
126 m_d->responseTime = 0;
127 m_d->numTickets = 0;
128 m_d->numUpdates = 0;
129 m_d->mousePath = 0;
130
131 m_d->lastMousePos = QPointF();
132 m_d->preset = 0;
133 m_d->strokeTime.start();
134}
135
137{
138 if (!m_d->loggingEnabled) return;
139
140 QMutexLocker locker(&m_d->mutex);
141
142 if (m_d->numTickets) {
143 printValues();
144 }
145}
146
148{
149 if (!m_d->loggingEnabled) return;
150
151 m_d->preset = preset;
152}
153
155{
156 if (!m_d->loggingEnabled) return;
157
158 QMutexLocker locker(&m_d->mutex);
159
160 if (!m_d->lastMousePos.isNull()) {
161 qreal distance = kisDistance(m_d->lastMousePos, pos);
162 m_d->mousePath += distance;
163 }
164
165 m_d->lastMousePos = pos;
166}
167
169{
170 qint64 strokeTime = m_d->strokeTime.elapsed();
171 qreal responseTime = qreal(m_d->responseTime) / m_d->numTickets;
172 qreal nonUpdateTime = qreal(m_d->jobsTime) / m_d->numTickets;
173 qreal jobsPerUpdate = qreal(m_d->numTickets) / m_d->numUpdates;
174 qreal mouseSpeed = qreal(m_d->mousePath) / strokeTime;
175
176 QString prefix;
177
178 if (m_d->preset) {
179 KoResourceSP preset = m_d->preset->clone();
180 prefix = QString("%1.").arg(preset->name());
181 preset->setFilename(QString("log/%1.kpp").arg(preset->name()));
182 preset->save();
183 }
184
185 QFile logFile(QString("log/%1stroke.rdata").arg(prefix));
186 logFile.open(QIODevice::Append);
187 QTextStream stream(&logFile);
189
190 stream << i18n("Stroke Time:") << strokeTime << "\t"
191 << i18n("Mouse Speed:") << QString::number( mouseSpeed, 'f', 3 ) << "\t"
192 << i18n("Jobs/Update:") << QString::number( jobsPerUpdate, 'f', 3 ) << "\t"
193 << i18n("Non Update Time:") << QString::number( nonUpdateTime, 'f', 3 ) << "\t"
194 << i18n("Response Time:") << responseTime << Qt::endl; // 'endl' will use the correct OS line ending
195 logFile.close();
196}
197
199{
200 if (!m_d->loggingEnabled) return;
201
202 QMutexLocker locker(&m_d->mutex);
203
204 StrokeTicket *ticket = new StrokeTicket();
205 ticket->start();
206
207 m_d->preliminaryTickets.insert(key, ticket);
208}
209
211{
212 if (!m_d->loggingEnabled) return;
213
214 QMutexLocker locker(&m_d->mutex);
215
216 StrokeTicket *ticket = m_d->preliminaryTickets.take(key);
217 if( ticket ){
218 ticket->jobCompleted();
219
220 Q_FOREACH (const QRect &rect, rects) {
221 ticket->dirtyRegion += rect;
222 }
223 m_d->finishedTickets.insert(ticket);
224 }
225}
226
228{
229 if (!m_d->loggingEnabled) return;
230
231 QMutexLocker locker(&m_d->mutex);
232
233 Q_FOREACH (StrokeTicket *ticket, m_d->finishedTickets) {
234 ticket->dirtyRegion -= rect;
235 if(ticket->dirtyRegion.isEmpty()) {
236 ticket->updateCompleted();
237 m_d->jobsTime += ticket->jobTime();
238 m_d->responseTime += ticket->jobTime() + ticket->updateTime();
239 m_d->numTickets++;
240
241 m_d->finishedTickets.remove(ticket);
242 delete ticket;
243 }
244 }
245 m_d->numUpdates++;
246}
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
qreal distance(const QPointF &p1, const QPointF &p2)
bool enablePerfLog(bool requestDefault=false) const
qreal kisDistance(const QPointF &pt1, const QPointF &pt2)
Definition kis_global.h:190
void setUtf8OnStream(QTextStream &stream)
void reportJobFinished(void *key, const QVector< QRect > &rects)
QHash< void *, StrokeTicket * > preliminaryTickets
static KisUpdateTimeMonitor * instance()
void reportUpdateFinished(const QRect &rect)
void reportMouseMove(const QPointF &pos)
void reportPaintOpPreset(KisPaintOpPresetSP preset)
QSet< StrokeTicket * > finishedTickets
qint64 updateTime() const