diff --git a/libs/image/kis_update_time_monitor.cpp b/libs/image/kis_update_time_monitor.cpp index 569dc5e779..b76ab09c2d 100644 --- a/libs/image/kis_update_time_monitor.cpp +++ b/libs/image/kis_update_time_monitor.cpp @@ -1,256 +1,258 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_update_time_monitor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_debug.h" #include "kis_global.h" #include "kis_image_config.h" #include Q_GLOBAL_STATIC(KisUpdateTimeMonitor, s_instance) struct StrokeTicket { StrokeTicket() : m_jobTime(0) , m_updateTime(0) {} QRegion dirtyRegion; void start() { m_timer.start(); } void jobCompleted() { m_jobTime = m_timer.restart(); } void updateCompleted() { m_updateTime = m_timer.restart(); } qint64 jobTime() const { return m_jobTime; } qint64 updateTime() const { return m_updateTime; } private: QElapsedTimer m_timer; qint64 m_jobTime; qint64 m_updateTime; }; struct Q_DECL_HIDDEN KisUpdateTimeMonitor::Private { Private() : jobsTime(0), responseTime(0), numTickets(0), numUpdates(0), mousePath(0.0), loggingEnabled(false) { loggingEnabled = KisImageConfig().enablePerfLog(); } QHash preliminaryTickets; QSet finishedTickets; qint64 jobsTime; qint64 responseTime; qint32 numTickets; qint32 numUpdates; QMutex mutex; qreal mousePath; QPointF lastMousePos; QElapsedTimer strokeTime; KisPaintOpPresetSP preset; bool loggingEnabled; }; KisUpdateTimeMonitor::KisUpdateTimeMonitor() : m_d(new Private) { if (m_d->loggingEnabled) { QDir dir; if (dir.exists("log")) { dir.remove("log"); } dir.mkdir("log"); } } KisUpdateTimeMonitor::~KisUpdateTimeMonitor() { delete m_d; } KisUpdateTimeMonitor* KisUpdateTimeMonitor::instance() { return s_instance; } void KisUpdateTimeMonitor::startStrokeMeasure() { if (!m_d->loggingEnabled) return; QMutexLocker locker(&m_d->mutex); m_d->jobsTime = 0; m_d->responseTime = 0; m_d->numTickets = 0; m_d->numUpdates = 0; m_d->mousePath = 0; m_d->lastMousePos = QPointF(); m_d->preset = 0; m_d->strokeTime.start(); } void KisUpdateTimeMonitor::endStrokeMeasure() { if (!m_d->loggingEnabled) return; QMutexLocker locker(&m_d->mutex); if(m_d->numTickets) { printValues(); } } void KisUpdateTimeMonitor::reportPaintOpPreset(KisPaintOpPresetSP preset) { if (!m_d->loggingEnabled) return; m_d->preset = preset; } void KisUpdateTimeMonitor::reportMouseMove(const QPointF &pos) { if (!m_d->loggingEnabled) return; QMutexLocker locker(&m_d->mutex); if (!m_d->lastMousePos.isNull()) { qreal distance = kisDistance(m_d->lastMousePos, pos); m_d->mousePath += distance; } m_d->lastMousePos = pos; } void KisUpdateTimeMonitor::printValues() { qint64 strokeTime = m_d->strokeTime.elapsed(); qreal responseTime = qreal(m_d->responseTime) / m_d->numTickets; qreal nonUpdateTime = qreal(m_d->jobsTime) / m_d->numTickets; - qreal jobsPerUpdate = qreal(m_d->numTickets) / m_d->numUpdates; + qreal jobsPerUpdate = qreal(m_d->numTickets) / m_d->numUpdates; qreal mouseSpeed = qreal(m_d->mousePath) / strokeTime; QString prefix; if (m_d->preset) { KisPaintOpPresetSP preset = m_d->preset->clone(); prefix = QString("%1.").arg(preset->name()); preset->setFilename(QString("log/%1.kpp").arg(preset->name())); preset->save(); } QFile logFile(QString("log/%1stroke.rdata").arg(prefix)); logFile.open(QIODevice::Append); QTextStream stream(&logFile); - stream << mouseSpeed << "\t" - << jobsPerUpdate << "\t" - << nonUpdateTime << "\t" - << responseTime << "\n"; + + stream << i18n("Stroke Time:") << strokeTime << "\t" + << i18n("Mouse Speed:") << QString::number( mouseSpeed, 'f', 3 ) << "\t" + << i18n("Jobs/Update:") << QString::number( jobsPerUpdate, 'f', 3 ) << "\t" + << i18n("Non Update Time:") << QString::number( nonUpdateTime, 'f', 3 ) << "\t" + << i18n("Response Time:") << responseTime << endl; // 'endl' will use the correct OS line ending logFile.close(); } void KisUpdateTimeMonitor::reportJobStarted(void *key) { if (!m_d->loggingEnabled) return; QMutexLocker locker(&m_d->mutex); StrokeTicket *ticket = new StrokeTicket(); ticket->start(); m_d->preliminaryTickets.insert(key, ticket); } void KisUpdateTimeMonitor::reportJobFinished(void *key, const QVector &rects) { if (!m_d->loggingEnabled) return; QMutexLocker locker(&m_d->mutex); StrokeTicket *ticket = m_d->preliminaryTickets.take(key); if( ticket ){ ticket->jobCompleted(); Q_FOREACH (const QRect &rect, rects) { ticket->dirtyRegion += rect; } m_d->finishedTickets.insert(ticket); } } void KisUpdateTimeMonitor::reportUpdateFinished(const QRect &rect) { if (!m_d->loggingEnabled) return; QMutexLocker locker(&m_d->mutex); Q_FOREACH (StrokeTicket *ticket, m_d->finishedTickets) { ticket->dirtyRegion -= rect; if(ticket->dirtyRegion.isEmpty()) { ticket->updateCompleted(); m_d->jobsTime += ticket->jobTime(); m_d->responseTime += ticket->jobTime() + ticket->updateTime(); m_d->numTickets++; m_d->finishedTickets.remove(ticket); delete ticket; } } m_d->numUpdates++; }