QmlProfilerTool: add tool to QDeclarative
[profile/ivi/qtdeclarative.git] / tools / qmlprofiler / profileclient.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "profileclient.h"
43
44 #include <QtCore/QStack>
45 #include <QtCore/QStringList>
46
47 ProfileClient::ProfileClient(const QString &clientName,
48                              QDeclarativeDebugConnection *client)
49     : QDeclarativeDebugClient(clientName, client),
50       m_recording(false),
51       m_enabled(false)
52 {
53 }
54
55 ProfileClient::~ProfileClient()
56 {
57     //Disable profiling if started by client
58     //Profiling data will be lost!!
59     if (isRecording())
60         setRecording(false);
61 }
62
63 void ProfileClient::clearData()
64 {
65     emit cleared();
66 }
67
68 bool ProfileClient::isEnabled() const
69 {
70     return m_enabled;
71 }
72
73 void ProfileClient::sendRecordingStatus()
74 {
75 }
76
77 bool ProfileClient::isRecording() const
78 {
79     return m_recording;
80 }
81
82 void ProfileClient::setRecording(bool v)
83 {
84     if (v == m_recording)
85         return;
86
87     m_recording = v;
88
89     if (state() == Enabled) {
90         sendRecordingStatus();
91     }
92
93     emit recordingChanged(v);
94 }
95
96 void ProfileClient::stateChanged(State status)
97 {
98     if ((m_enabled && status != Enabled) ||
99             (!m_enabled && status == Enabled))
100         emit enabledChanged();
101
102     m_enabled = status == Enabled;
103
104 }
105
106 class DeclarativeProfileClientPrivate
107 {
108 public:
109     DeclarativeProfileClientPrivate()
110         : inProgressRanges(0)
111         , maximumTime(0)
112     {
113         ::memset(rangeCount, 0,
114                  QDeclarativeProfilerService::MaximumRangeType * sizeof(int));
115     }
116
117     qint64 inProgressRanges;
118     QStack<qint64> rangeStartTimes[QDeclarativeProfilerService::MaximumRangeType];
119     QStack<QStringList> rangeDatas[QDeclarativeProfilerService::MaximumRangeType];
120     QStack<EventLocation> rangeLocations[QDeclarativeProfilerService::MaximumRangeType];
121     int rangeCount[QDeclarativeProfilerService::MaximumRangeType];
122     qint64 maximumTime;
123 };
124
125 DeclarativeProfileClient::DeclarativeProfileClient(
126         QDeclarativeDebugConnection *client)
127     : ProfileClient(QLatin1String("CanvasFrameRate"), client),
128       d(new DeclarativeProfileClientPrivate)
129 {
130 }
131
132 DeclarativeProfileClient::~DeclarativeProfileClient()
133 {
134     delete d;
135 }
136
137 void DeclarativeProfileClient::clearData()
138 {
139     ::memset(d->rangeCount, 0,
140              QDeclarativeProfilerService::MaximumRangeType * sizeof(int));
141     ProfileClient::clearData();
142 }
143
144 void DeclarativeProfileClient::sendRecordingStatus()
145 {
146     QByteArray ba;
147     QDataStream stream(&ba, QIODevice::WriteOnly);
148     stream << isRecording();
149     sendMessage(ba);
150 }
151
152 void DeclarativeProfileClient::messageReceived(const QByteArray &data)
153 {
154     QByteArray rwData = data;
155     QDataStream stream(&rwData, QIODevice::ReadOnly);
156
157     qint64 time;
158     int messageType;
159
160     stream >> time >> messageType;
161
162     if (messageType >= QDeclarativeProfilerService::MaximumMessage)
163         return;
164
165     if (messageType == QDeclarativeProfilerService::Event) {
166         int event;
167         stream >> event;
168
169         if (event == QDeclarativeProfilerService::EndTrace) {
170             emit this->traceFinished(time);
171             d->maximumTime = time;
172             d->maximumTime = qMax(time, d->maximumTime);
173         } else if (event == QDeclarativeProfilerService::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 == QDeclarativeProfilerService::StartTrace) {
179             emit this->traceStarted(time);
180             d->maximumTime = time;
181         } else if (event < QDeclarativeProfilerService::MaximumEventType) {
182             d->maximumTime = qMax(time, d->maximumTime);
183         }
184     } else if (messageType == QDeclarativeProfilerService::Complete) {
185         emit complete();
186
187     } else {
188         int range;
189         stream >> range;
190
191         if (range >= QDeclarativeProfilerService::MaximumRangeType)
192             return;
193
194         if (messageType == QDeclarativeProfilerService::RangeStart) {
195             d->rangeStartTimes[range].push(time);
196             d->inProgressRanges |= (static_cast<qint64>(1) << range);
197             ++d->rangeCount[range];
198         } else if (messageType == QDeclarativeProfilerService::RangeData) {
199             QString data;
200             stream >> data;
201
202             int count = d->rangeCount[range];
203             if (count > 0) {
204                 while (d->rangeDatas[range].count() < count)
205                     d->rangeDatas[range].push(QStringList());
206                 d->rangeDatas[range][count-1] << data;
207             }
208
209         } else if (messageType == QDeclarativeProfilerService::RangeLocation) {
210             QString fileName;
211             int line;
212             int column = -1;
213             stream >> fileName >> line;
214
215             if (!stream.atEnd())
216                 stream >> column;
217
218             if (d->rangeCount[range] > 0) {
219                 d->rangeLocations[range].push(EventLocation(fileName, line,
220                                                             column));
221             }
222         } else {
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);
227
228                 d->maximumTime = qMax(time, d->maximumTime);
229                 QStringList data = d->rangeDatas[range].count() ?
230                             d->rangeDatas[range].pop() : QStringList();
231                 EventLocation location = d->rangeLocations[range].count() ?
232                             d->rangeLocations[range].pop() : EventLocation();
233
234                 qint64 startTime = d->rangeStartTimes[range].pop();
235                 emit this->range((QDeclarativeProfilerService::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();
241                     if (count != 0)
242                         qWarning() << "incorrectly nested data";
243                 }
244             }
245         }
246     }
247 }
248
249 V8ProfileClient::V8ProfileClient(QDeclarativeDebugConnection *client)
250     : ProfileClient(QLatin1String("V8Profiler"), client)
251 {
252 }
253
254 V8ProfileClient::~V8ProfileClient()
255 {
256 }
257
258 void V8ProfileClient::sendRecordingStatus()
259 {
260     QByteArray ba;
261     QDataStream stream(&ba, QIODevice::WriteOnly);
262     QByteArray cmd("V8PROFILER");
263     QByteArray option("");
264     QByteArray title("");
265
266     if (m_recording) {
267         option = "start";
268     } else {
269         option = "stop";
270     }
271     stream << cmd << option << title;
272     sendMessage(ba);
273 }
274
275 void V8ProfileClient::messageReceived(const QByteArray &data)
276 {
277     QByteArray rwData = data;
278     QDataStream stream(&rwData, QIODevice::ReadOnly);
279
280     int messageType;
281
282     stream >> messageType;
283
284     if (messageType == V8Complete) {
285         emit complete();
286     } else if (messageType == V8Entry) {
287         QString filename;
288         QString function;
289         int lineNumber;
290         double totalTime;
291         double selfTime;
292         int depth;
293
294         stream  >> filename >> function >> lineNumber >> totalTime >>
295                    selfTime >> depth;
296         emit this->range(depth, function, filename, lineNumber, totalTime,
297                          selfTime);
298     }
299 }
300