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 QtQml 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 "qmlprofilerclient.h"
44 #include <QtCore/QStack>
45 #include <QtCore/QStringList>
47 ProfilerClient::ProfilerClient(const QString &clientName,
48 QQmlDebugConnection *client)
49 : QQmlDebugClient(clientName, client),
55 ProfilerClient::~ProfilerClient()
57 //Disable profiling if started by client
58 //Profiling data will be lost!!
63 void ProfilerClient::clearData()
68 bool ProfilerClient::isEnabled() const
73 void ProfilerClient::sendRecordingStatus()
77 bool ProfilerClient::isRecording() const
82 void ProfilerClient::setRecording(bool v)
89 if (state() == Enabled) {
90 sendRecordingStatus();
93 emit recordingChanged(v);
96 void ProfilerClient::stateChanged(State status)
98 if ((m_enabled && status != Enabled) ||
99 (!m_enabled && status == Enabled))
100 emit enabledChanged();
102 m_enabled = status == Enabled;
106 class QmlProfilerClientPrivate
109 QmlProfilerClientPrivate()
110 : inProgressRanges(0)
113 ::memset(rangeCount, 0,
114 QQmlProfilerService::MaximumRangeType * sizeof(int));
117 qint64 inProgressRanges;
118 QStack<qint64> rangeStartTimes[QQmlProfilerService::MaximumRangeType];
119 QStack<QStringList> rangeDatas[QQmlProfilerService::MaximumRangeType];
120 QStack<QmlEventLocation> rangeLocations[QQmlProfilerService::MaximumRangeType];
121 int rangeCount[QQmlProfilerService::MaximumRangeType];
125 QmlProfilerClient::QmlProfilerClient(
126 QQmlDebugConnection *client)
127 : ProfilerClient(QStringLiteral("CanvasFrameRate"), client),
128 d(new QmlProfilerClientPrivate)
132 QmlProfilerClient::~QmlProfilerClient()
137 void QmlProfilerClient::clearData()
139 ::memset(d->rangeCount, 0,
140 QQmlProfilerService::MaximumRangeType * sizeof(int));
141 ProfilerClient::clearData();
144 void QmlProfilerClient::sendRecordingStatus()
147 QDataStream stream(&ba, QIODevice::WriteOnly);
148 stream << isRecording();
152 void QmlProfilerClient::messageReceived(const QByteArray &data)
154 QByteArray rwData = data;
155 QDataStream stream(&rwData, QIODevice::ReadOnly);
160 stream >> time >> messageType;
162 if (messageType >= QQmlProfilerService::MaximumMessage)
165 if (messageType == QQmlProfilerService::Event) {
169 if (event == QQmlProfilerService::EndTrace) {
170 emit this->traceFinished(time);
171 d->maximumTime = time;
172 d->maximumTime = qMax(time, d->maximumTime);
173 } else if (event == QQmlProfilerService::AnimationFrame) {
174 int frameRate, animationCount;
175 stream >> frameRate >> animationCount;
176 emit this->frame(time, frameRate, animationCount);
177 d->maximumTime = qMax(time, d->maximumTime);
178 } else if (event == QQmlProfilerService::StartTrace) {
179 emit this->traceStarted(time);
180 d->maximumTime = time;
181 } else if (event < QQmlProfilerService::MaximumEventType) {
182 d->maximumTime = qMax(time, d->maximumTime);
184 } else if (messageType == QQmlProfilerService::Complete) {
191 if (range >= QQmlProfilerService::MaximumRangeType)
194 if (messageType == QQmlProfilerService::RangeStart) {
195 d->rangeStartTimes[range].push(time);
196 d->inProgressRanges |= (static_cast<qint64>(1) << range);
197 ++d->rangeCount[range];
198 } else if (messageType == QQmlProfilerService::RangeData) {
202 int count = d->rangeCount[range];
204 while (d->rangeDatas[range].count() < count)
205 d->rangeDatas[range].push(QStringList());
206 d->rangeDatas[range][count-1] << data;
209 } else if (messageType == QQmlProfilerService::RangeLocation) {
213 stream >> fileName >> line;
218 if (d->rangeCount[range] > 0) {
219 d->rangeLocations[range].push(QmlEventLocation(fileName, line,
223 if (d->rangeCount[range] > 0) {
224 --d->rangeCount[range];
225 if (d->inProgressRanges & (static_cast<qint64>(1) << range))
226 d->inProgressRanges &= ~(static_cast<qint64>(1) << range);
228 d->maximumTime = qMax(time, d->maximumTime);
229 QStringList data = d->rangeDatas[range].count() ?
230 d->rangeDatas[range].pop() : QStringList();
231 QmlEventLocation location = d->rangeLocations[range].count() ?
232 d->rangeLocations[range].pop() : QmlEventLocation();
234 qint64 startTime = d->rangeStartTimes[range].pop();
235 emit this->range((QQmlProfilerService::RangeType)range,
236 startTime, time - startTime, data, location);
237 if (d->rangeCount[range] == 0) {
238 int count = d->rangeDatas[range].count() +
239 d->rangeStartTimes[range].count() +
240 d->rangeLocations[range].count();
242 qWarning() << "incorrectly nested data";
249 V8ProfilerClient::V8ProfilerClient(QQmlDebugConnection *client)
250 : ProfilerClient(QStringLiteral("V8Profiler"), client)
254 V8ProfilerClient::~V8ProfilerClient()
258 void V8ProfilerClient::sendRecordingStatus()
261 QDataStream stream(&ba, QIODevice::WriteOnly);
262 QByteArray cmd("V8PROFILER");
263 QByteArray option("");
264 QByteArray title("");
271 stream << cmd << option << title;
275 void V8ProfilerClient::messageReceived(const QByteArray &data)
277 QByteArray rwData = data;
278 QDataStream stream(&rwData, QIODevice::ReadOnly);
282 stream >> messageType;
284 if (messageType == V8Complete) {
286 } else if (messageType == V8Entry) {
294 stream >> filename >> function >> lineNumber >> totalTime >>
296 emit this->range(depth, function, filename, lineNumber, totalTime,