Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qqmlprofilerclient.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant
4
5
#
include
"qqmlprofilerclient_p_p.h"
6
#
include
"qqmldebugconnection_p.h"
7
8
QT_BEGIN_NAMESPACE
9
10
QQmlProfilerClientPrivate::~QQmlProfilerClientPrivate()
11
{
12
}
13
14
int
QQmlProfilerClientPrivate::resolveType(
const
QQmlProfilerTypedEvent &event)
15
{
16
int
typeIndex = -1;
17
if
(event.serverTypeId != 0) {
18
QHash<qint64,
int
>::ConstIterator it = serverTypeIds.constFind(event.serverTypeId);
19
20
if
(it != serverTypeIds.constEnd()) {
21
typeIndex = it.value();
22
}
else
{
23
typeIndex = eventReceiver->numLoadedEventTypes();
24
eventReceiver->addEventType(event.type);
25
serverTypeIds[event.serverTypeId] = typeIndex;
26
}
27
}
else
{
28
QHash<QQmlProfilerEventType,
int
>::ConstIterator it = eventTypeIds.constFind(event.type);
29
30
if
(it != eventTypeIds.constEnd()) {
31
typeIndex = it.value();
32
}
else
{
33
typeIndex = eventReceiver->numLoadedEventTypes();
34
eventReceiver->addEventType(event.type);
35
eventTypeIds[event.type] = typeIndex;
36
}
37
}
38
return
typeIndex;
39
}
40
41
int
QQmlProfilerClientPrivate::resolveStackTop()
42
{
43
if
(rangesInProgress.isEmpty())
44
return
-1;
45
46
QQmlProfilerTypedEvent &typedEvent = rangesInProgress.top();
47
int
typeIndex = typedEvent.event.typeIndex();
48
if
(typeIndex >= 0)
49
return
typeIndex;
50
51
typeIndex = resolveType(typedEvent);
52
typedEvent.event.setTypeIndex(typeIndex);
53
while
(!pendingMessages.isEmpty()
54
&& pendingMessages.head().timestamp() < typedEvent.event.timestamp()) {
55
forwardEvents(pendingMessages.dequeue());
56
}
57
forwardEvents(typedEvent.event);
58
return
typeIndex;
59
}
60
61
void
QQmlProfilerClientPrivate::forwardEvents(
const
QQmlProfilerEvent &last)
62
{
63
forwardDebugMessages(last.timestamp());
64
eventReceiver->addEvent(last);
65
}
66
67
void
QQmlProfilerClientPrivate::forwardDebugMessages(qint64 untilTimestamp)
68
{
69
while
(!pendingDebugMessages.isEmpty()
70
&& pendingDebugMessages.front().timestamp() <= untilTimestamp) {
71
eventReceiver->addEvent(pendingDebugMessages.dequeue());
72
}
73
}
74
75
void
QQmlProfilerClientPrivate::processCurrentEvent()
76
{
77
// RangeData and RangeLocation always apply to the range on the top of the stack. Furthermore,
78
// all ranges are perfectly nested. This is why we can defer the type resolution until either
79
// the range ends or a child range starts. With only the information in RangeStart we wouldn't
80
// be able to uniquely identify the event type.
81
Message rangeStage = currentEvent.type.rangeType() == MaximumRangeType ?
82
currentEvent.type.message() : currentEvent.event.rangeStage();
83
switch
(rangeStage) {
84
case
RangeStart:
85
resolveStackTop();
86
rangesInProgress.push(currentEvent);
87
break
;
88
case
RangeEnd: {
89
int
typeIndex = resolveStackTop();
90
if
(typeIndex == -1)
91
break
;
92
currentEvent.event.setTypeIndex(typeIndex);
93
while
(!pendingMessages.isEmpty())
94
forwardEvents(pendingMessages.dequeue());
95
forwardEvents(currentEvent.event);
96
rangesInProgress.pop();
97
break
;
98
}
99
case
RangeData:
100
if
(!rangesInProgress.isEmpty())
101
rangesInProgress.top().type.setData(currentEvent.type.data());
102
break
;
103
case
RangeLocation:
104
if
(!rangesInProgress.isEmpty())
105
rangesInProgress.top().type.setLocation(currentEvent.type.location());
106
break
;
107
case
DebugMessage:
108
currentEvent.event.setTypeIndex(resolveType(currentEvent));
109
pendingDebugMessages.enqueue(currentEvent.event);
110
break
;
111
default
: {
112
int
typeIndex = resolveType(currentEvent);
113
currentEvent.event.setTypeIndex(typeIndex);
114
if
(rangesInProgress.isEmpty())
115
forwardEvents(currentEvent.event);
116
else
117
pendingMessages.enqueue(currentEvent.event);
118
break
;
119
}
120
}
121
}
122
123
void
QQmlProfilerClientPrivate::sendRecordingStatus(
int
engineId)
124
{
125
Q_Q(QQmlProfilerClient);
126
QPacket stream(connection->currentDataStreamVersion());
127
stream << recording << engineId;
// engineId -1 is OK. It means "all of them"
128
if
(recording) {
129
stream << requestedFeatures << flushInterval;
130
stream <<
true
;
// yes, we support type IDs
131
}
132
q->sendMessage(stream.data());
133
}
134
135
QQmlProfilerClient
::QQmlProfilerClient(
QQmlDebugConnection
*connection,
136
QQmlProfilerEventReceiver *eventReceiver,
137
quint64 features)
138
: QQmlDebugClient(*(
new
QQmlProfilerClientPrivate(connection, eventReceiver)))
139
{
140
Q_D(QQmlProfilerClient);
141
setRequestedFeatures(features);
142
connect(
this
, &QQmlDebugClient::stateChanged,
this
, &QQmlProfilerClient::onStateChanged);
143
connect(d->engineControl.data(), &QQmlEngineControlClient::engineAboutToBeAdded,
144
this
, &
QQmlProfilerClient
::
sendRecordingStatus
);
145
connect(d->engineControl.data(), &QQmlEngineControlClient::engineAboutToBeRemoved,
146
this
, [d](
int
engineId) {
147
// We may already be done with that engine. Then we don't need to block it.
148
if
(d->trackedEngines.contains(engineId))
149
d->engineControl->blockEngine(engineId);
150
});
151
connect(
this
, &QQmlProfilerClient::traceFinished,
152
d->engineControl.data(), [d](qint64 timestamp,
const
QList<
int
> &engineIds) {
153
Q_UNUSED(timestamp);
154
// The engines might not be blocked because the trace can get finished before engine control
155
// sees them.
156
for
(
int
blocked : d->engineControl->blockedEngines()) {
157
if
(engineIds.contains(blocked))
158
d->engineControl->releaseEngine(blocked);
159
}
160
});
161
}
162
163
QQmlProfilerClient
::~
QQmlProfilerClient
()
164
{
165
//Disable profiling if started by client
166
//Profiling data will be lost!!
167
if
(
isRecording
(
)
)
168
setRecording
(
false
)
;
169
}
170
171
void
QQmlProfilerClient
::
clearEvents
()
172
{
173
Q_D(QQmlProfilerClient);
174
d->rangesInProgress.clear();
175
d->pendingMessages.clear();
176
d->pendingDebugMessages.clear();
177
if
(d->recordedFeatures != 0) {
178
d->recordedFeatures = 0;
179
emit recordedFeaturesChanged(0);
180
}
181
emit cleared();
182
}
183
184
void
QQmlProfilerClient
::
clearAll
()
185
{
186
Q_D(QQmlProfilerClient);
187
d->serverTypeIds.clear();
188
d->eventTypeIds.clear();
189
d->trackedEngines.clear();
190
clearEvents
(
)
;
191
}
192
193
void
QQmlProfilerClientPrivate::finalize()
194
{
195
while
(!rangesInProgress.isEmpty()) {
196
currentEvent = rangesInProgress.top();
197
currentEvent.event.setRangeStage(RangeEnd);
198
currentEvent.event.setTimestamp(maximumTime);
199
processCurrentEvent();
200
}
201
forwardDebugMessages(std::numeric_limits<qint64>::max());
202
}
203
204
205
void
QQmlProfilerClient
::
sendRecordingStatus
(
int
engineId)
206
{
207
Q_D(QQmlProfilerClient);
208
d->sendRecordingStatus(engineId);
209
}
210
211
bool
QQmlProfilerClient
::
isRecording
()
const
212
{
213
Q_D(
const
QQmlProfilerClient);
214
return
d->recording;
215
}
216
217
void
QQmlProfilerClient
::
setRecording
(
bool
v)
218
{
219
Q_D(QQmlProfilerClient);
220
if
(v == d->recording)
221
return
;
222
223
d->recording = v;
224
225
if
(state() == Enabled)
226
sendRecordingStatus
(
)
;
227
228
emit recordingChanged(v);
229
}
230
231
quint64
QQmlProfilerClient
::
recordedFeatures
()
const
232
{
233
Q_D(
const
QQmlProfilerClient);
234
return
d->recordedFeatures;
235
}
236
237
void
QQmlProfilerClient
::receiveDebugMessage(
238
QtMsgType type,
const
QString &text,
const
QQmlDebugContextInfo
&context)
239
{
240
Q_D(QQmlProfilerClient);
241
d->updateFeatures(ProfileDebugMessages);
242
d->currentEvent.event.setTimestamp(context.timestamp > 0 ? context.timestamp : 0);
243
d->currentEvent.event.setTypeIndex(-1);
244
d->currentEvent.event.setString(text);
245
d->currentEvent.type = QQmlProfilerEventType(
246
DebugMessage, MaximumRangeType, type,
247
QQmlProfilerEventLocation(context.file, context.line, 1));
248
d->currentEvent.serverTypeId = 0;
249
d->processCurrentEvent();
250
}
251
252
void
QQmlProfilerClient
::
setRequestedFeatures
(quint64 features)
253
{
254
Q_D(QQmlProfilerClient);
255
256
const
quint64 messagesFlag = 1ull <<
ProfileDebugMessages
;
257
const
bool
hadMessagesBefore = d->requestedFeatures & messagesFlag;
258
const
bool
hasMessagesNow = features & messagesFlag;
259
260
d->requestedFeatures = features;
261
262
if
(!hadMessagesBefore && hasMessagesNow) {
263
connect(d->messageClient.data(), &QQmlDebugMessageClient::message,
264
this
, &QQmlProfilerClient::receiveDebugMessage);
265
}
else
if
(hadMessagesBefore && !hasMessagesNow) {
266
disconnect(d->messageClient.data(), &QQmlDebugMessageClient::message,
267
this
, &QQmlProfilerClient::receiveDebugMessage);
268
}
269
}
270
271
void
QQmlProfilerClient
::
setFlushInterval
(quint32 flushInterval)
272
{
273
Q_D(QQmlProfilerClient);
274
d->flushInterval = flushInterval;
275
}
276
277
QQmlProfilerClient
::
QQmlProfilerClient
(QQmlProfilerClientPrivate &dd) :
278
QQmlDebugClient
(dd)
279
{
280
Q_D(QQmlProfilerClient);
281
connect(d->engineControl.data(), &QQmlEngineControlClient::engineAboutToBeAdded,
282
this
, &
QQmlProfilerClient
::
sendRecordingStatus
);
283
}
284
285
bool
QQmlProfilerClientPrivate::updateFeatures(ProfileFeature feature)
286
{
287
Q_Q(QQmlProfilerClient);
288
quint64 flag = 1ULL << feature;
289
if
(!(requestedFeatures & flag))
290
return
false
;
291
if
(!(recordedFeatures & flag)) {
292
recordedFeatures |= flag;
293
emit q->recordedFeaturesChanged(recordedFeatures);
294
}
295
return
true
;
296
}
297
298
void
QQmlProfilerClient
::
onStateChanged
(State status)
299
{
300
if
(status == Enabled) {
301
sendRecordingStatus
(
-1
)
;
302
}
else
{
303
Q_D(QQmlProfilerClient);
304
d->finalize();
305
}
306
307
}
308
309
void
QQmlProfilerClient
::
messageReceived
(
const
QByteArray &data)
310
{
311
Q_D(QQmlProfilerClient);
312
QPacket stream(d->connection->currentDataStreamVersion(), data);
313
314
stream >> d->currentEvent;
315
316
d->maximumTime = qMax(d->currentEvent.event.timestamp(), d->maximumTime);
317
if
(d->currentEvent.type.message() == Complete) {
318
d->finalize();
319
emit complete(d->maximumTime);
320
}
else
if
(d->currentEvent.type.message() == Event
321
&& d->currentEvent.type.detailType() == StartTrace) {
322
const
QList<
int
> engineIds = d->currentEvent.event.numbers<QList<
int
>, qint32>();
323
d->trackedEngines.append(engineIds);
324
d->forwardDebugMessages(d->currentEvent.event.timestamp());
325
emit traceStarted(d->currentEvent.event.timestamp(), engineIds);
326
}
else
if
(d->currentEvent.type.message() == Event
327
&& d->currentEvent.type.detailType() == EndTrace) {
328
const
QList<
int
> engineIds = d->currentEvent.event.numbers<QList<
int
>, qint32>();
329
for
(
int
engineId : engineIds)
330
d->trackedEngines.removeAll(engineId);
331
d->forwardDebugMessages(d->currentEvent.event.timestamp());
332
emit traceFinished(d->currentEvent.event.timestamp(), engineIds);
333
}
else
if
(d->updateFeatures(d->currentEvent.type.feature())) {
334
d->processCurrentEvent();
335
}
336
}
337
338
QT_END_NAMESPACE
339
340
#
include
"moc_qqmlprofilerclient_p.cpp"
QQmlDebugClient
Definition
qqmldebugclient_p.h:27
QQmlDebugConnection
Definition
qqmldebugconnection_p.h:28
QQmlProfilerClient
Definition
qqmlprofilerclient_p.h:31
QQmlProfilerClient::setFlushInterval
void setFlushInterval(quint32 flushInterval)
Definition
qqmlprofilerclient.cpp:271
QQmlProfilerClient::recordedFeatures
quint64 recordedFeatures() const
Definition
qqmlprofilerclient.cpp:231
QQmlProfilerClient::isRecording
bool isRecording() const
Definition
qqmlprofilerclient.cpp:211
QQmlProfilerClient::setRequestedFeatures
void setRequestedFeatures(quint64 features)
Definition
qqmlprofilerclient.cpp:252
QQmlProfilerClient::clearEvents
void clearEvents()
Definition
qqmlprofilerclient.cpp:171
QQmlProfilerClient::clearAll
void clearAll()
Definition
qqmlprofilerclient.cpp:184
QQmlProfilerClient::messageReceived
virtual void messageReceived(const QByteArray &) override
Definition
qqmlprofilerclient.cpp:309
QQmlProfilerClient::QQmlProfilerClient
QQmlProfilerClient(QQmlProfilerClientPrivate &dd)
Definition
qqmlprofilerclient.cpp:277
QQmlProfilerClient::setRecording
void setRecording(bool)
Definition
qqmlprofilerclient.cpp:217
QQmlProfilerClient::onStateChanged
void onStateChanged(State status)
Definition
qqmlprofilerclient.cpp:298
QQmlProfilerClient::sendRecordingStatus
void sendRecordingStatus(int engineId=-1)
Definition
qqmlprofilerclient.cpp:205
QQmlProfilerClient::~QQmlProfilerClient
~QQmlProfilerClient()
Definition
qqmlprofilerclient.cpp:163
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
ProfileDebugMessages
@ ProfileDebugMessages
Definition
qqmlprofilerclientdefinitions_p.h:123
QQmlDebugContextInfo
Definition
qqmldebugmessageclient_p.h:24
qtdeclarative
src
qmldebug
qqmlprofilerclient.cpp
Generated on
for Qt by
1.18.0