1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qdeclarativeprofilerservice_p.h"
44 #include <QtCore/qdatastream.h>
45 #include <QtCore/qurl.h>
46 #include <QtCore/qtimer.h>
47 #include <QtCore/qthread.h>
48 #include <QtCore/qcoreapplication.h>
50 // this contains QUnifiedTimer
51 #include <private/qabstractanimation_p.h>
55 Q_GLOBAL_STATIC(QDeclarativeProfilerService, profilerInstance)
57 QDeclarativeBindingProfiler::QDeclarativeBindingProfiler(const QString &url, int line, int column)
59 QDeclarativeProfilerService::startRange(QDeclarativeProfilerService::Binding);
60 QDeclarativeProfilerService::rangeLocation(QDeclarativeProfilerService::Binding, url, line, column);
63 QDeclarativeBindingProfiler::~QDeclarativeBindingProfiler()
65 QDeclarativeProfilerService::endRange(QDeclarativeProfilerService::Binding);
68 void QDeclarativeBindingProfiler::addDetail(const QString &details)
70 QDeclarativeProfilerService::rangeData(QDeclarativeProfilerService::Binding, details);
73 // convert to a QByteArray that can be sent to the debug client
74 // use of QDataStream can skew results
75 // (see tst_qdeclarativedebugtrace::trace() benchmark)
76 QByteArray QDeclarativeProfilerData::toByteArray() const
79 //### using QDataStream is relatively expensive
80 QDataStream ds(&data, QIODevice::WriteOnly);
81 ds << time << messageType << detailType;
82 if (messageType == (int)QDeclarativeProfilerService::RangeData)
84 if (messageType == (int)QDeclarativeProfilerService::RangeLocation)
85 ds << detailData << line << column;
86 if (messageType == (int)QDeclarativeProfilerService::Event &&
87 detailType == (int)QDeclarativeProfilerService::AnimationFrame)
88 ds << framerate << animationcount;
92 QDeclarativeProfilerService::QDeclarativeProfilerService()
93 : QDeclarativeDebugService(QLatin1String("CanvasFrameRate"), 1),
94 m_enabled(false), m_messageReceived(false)
98 if (registerService() == Enabled) {
99 // wait for first message indicating whether to trace or not
100 while (!m_messageReceived)
103 QUnifiedTimer::instance()->registerProfilerCallback( &animationFrame );
107 QDeclarativeProfilerService::~QDeclarativeProfilerService()
111 void QDeclarativeProfilerService::initialize()
113 // just make sure that the service is properly registered
117 bool QDeclarativeProfilerService::startProfiling()
119 return profilerInstance()->startProfilingImpl();
122 bool QDeclarativeProfilerService::stopProfiling()
124 return profilerInstance()->stopProfilingImpl();
127 void QDeclarativeProfilerService::sendStartedProfilingMessage()
129 profilerInstance()->sendStartedProfilingMessageImpl();
132 void QDeclarativeProfilerService::addEvent(EventType t)
134 profilerInstance()->addEventImpl(t);
137 void QDeclarativeProfilerService::startRange(RangeType t)
139 profilerInstance()->startRangeImpl(t);
142 void QDeclarativeProfilerService::rangeData(RangeType t, const QString &data)
144 profilerInstance()->rangeDataImpl(t, data);
147 void QDeclarativeProfilerService::rangeData(RangeType t, const QUrl &data)
149 profilerInstance()->rangeDataImpl(t, data);
152 void QDeclarativeProfilerService::rangeLocation(RangeType t, const QString &fileName, int line, int column)
154 profilerInstance()->rangeLocationImpl(t, fileName, line, column);
157 void QDeclarativeProfilerService::rangeLocation(RangeType t, const QUrl &fileName, int line, int column)
159 profilerInstance()->rangeLocationImpl(t, fileName, line, column);
162 void QDeclarativeProfilerService::endRange(RangeType t)
164 profilerInstance()->endRangeImpl(t);
167 void QDeclarativeProfilerService::animationFrame(qint64 delta)
169 profilerInstance()->animationFrameImpl(delta);
172 void QDeclarativeProfilerService::sendProfilingData()
174 profilerInstance()->sendMessages();
177 bool QDeclarativeProfilerService::startProfilingImpl()
179 bool success = false;
180 if (!profilingEnabled()) {
181 setProfilingEnabled(true);
182 sendStartedProfilingMessageImpl();
188 bool QDeclarativeProfilerService::stopProfilingImpl()
190 bool success = false;
191 if (profilingEnabled()) {
192 addEventImpl(EndTrace);
193 setProfilingEnabled(false);
199 void QDeclarativeProfilerService::sendStartedProfilingMessageImpl()
201 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
204 QDeclarativeProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)StartTrace, QString(), -1, -1, 0, 0};
205 QDeclarativeDebugService::sendMessage(ed.toByteArray());
208 void QDeclarativeProfilerService::addEventImpl(EventType event)
210 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
213 QDeclarativeProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)event, QString(), -1, -1, 0, 0};
217 void QDeclarativeProfilerService::startRangeImpl(RangeType range)
219 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
222 QDeclarativeProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeStart, (int)range, QString(), -1, -1, 0, 0};
226 void QDeclarativeProfilerService::rangeDataImpl(RangeType range, const QString &rData)
228 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
231 QDeclarativeProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData, -1, -1, 0, 0};
235 void QDeclarativeProfilerService::rangeDataImpl(RangeType range, const QUrl &rData)
237 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
240 QDeclarativeProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1, -1, 0, 0};
244 void QDeclarativeProfilerService::rangeLocationImpl(RangeType range, const QString &fileName, int line, int column)
246 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
249 QDeclarativeProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName, line, column, 0, 0};
253 void QDeclarativeProfilerService::rangeLocationImpl(RangeType range, const QUrl &fileName, int line, int column)
255 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
258 QDeclarativeProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line, column, 0, 0};
262 void QDeclarativeProfilerService::endRangeImpl(RangeType range)
264 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
267 QDeclarativeProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeEnd, (int)range, QString(), -1, -1, 0, 0};
271 void QDeclarativeProfilerService::animationFrameImpl(qint64 delta)
273 Q_ASSERT(QDeclarativeDebugService::isDebuggingEnabled());
277 int animCount = QUnifiedTimer::instance()->runningAnimationCount();
279 if (animCount > 0 && delta > 0) {
280 // trim fps to integer
281 int fps = 1000 / delta;
282 QDeclarativeProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)AnimationFrame, QString(), -1, -1, fps, animCount};
288 Either send the message directly, or queue up
289 a list of messages to send later (via sendMessages)
291 void QDeclarativeProfilerService::processMessage(const QDeclarativeProfilerData &message)
293 QMutexLocker locker(&m_mutex);
294 m_data.append(message);
297 bool QDeclarativeProfilerService::profilingEnabled()
302 void QDeclarativeProfilerService::setProfilingEnabled(bool enable)
308 Send the messages queued up by processMessage
310 void QDeclarativeProfilerService::sendMessages()
312 QMutexLocker locker(&m_mutex);
313 QList<QByteArray> messages;
314 for (int i = 0; i < m_data.count(); ++i)
315 messages << m_data.at(i).toByteArray();
318 //indicate completion
320 QDataStream ds(&data, QIODevice::WriteOnly);
321 ds << (qint64)-1 << (int)Complete;
324 QDeclarativeDebugService::sendMessages(messages);
327 void QDeclarativeProfilerService::stateAboutToBeChanged(QDeclarativeDebugService::State newState)
329 if (state() == newState)
332 if (state() == Enabled
339 void QDeclarativeProfilerService::messageReceived(const QByteArray &message)
341 QByteArray rwData = message;
342 QDataStream stream(&rwData, QIODevice::ReadOnly);
347 m_messageReceived = true;
350 startProfilingImpl();
352 if (stopProfilingImpl())