13int QQmlProfilerClientPrivate::resolveType(
const QQmlProfilerTypedEvent &event)
16 if (event.serverTypeId != 0) {
17 QHash<qint64,
int>::ConstIterator it = serverTypeIds.constFind(event.serverTypeId);
19 if (it != serverTypeIds.constEnd()) {
20 typeIndex = it.value();
22 typeIndex = eventReceiver->numLoadedEventTypes();
23 eventReceiver->addEventType(event.type);
24 serverTypeIds[event.serverTypeId] = typeIndex;
27 QHash<QQmlProfilerEventType,
int>::ConstIterator it = eventTypeIds.constFind(event.type);
29 if (it != eventTypeIds.constEnd()) {
30 typeIndex = it.value();
32 typeIndex = eventReceiver->numLoadedEventTypes();
33 eventReceiver->addEventType(event.type);
34 eventTypeIds[event.type] = typeIndex;
40int QQmlProfilerClientPrivate::resolveStackTop()
42 if (rangesInProgress.isEmpty())
45 QQmlProfilerTypedEvent &typedEvent = rangesInProgress.top();
46 int typeIndex = typedEvent.event.typeIndex();
50 typeIndex = resolveType(typedEvent);
51 typedEvent.event.setTypeIndex(typeIndex);
52 while (!pendingMessages.isEmpty()
53 && pendingMessages.head().timestamp() < typedEvent.event.timestamp()) {
54 forwardEvents(pendingMessages.dequeue());
56 forwardEvents(typedEvent.event);
66void QQmlProfilerClientPrivate::forwardDebugMessages(qint64 untilTimestamp)
68 while (!pendingDebugMessages.isEmpty()
69 && pendingDebugMessages.front().timestamp() <= untilTimestamp) {
70 eventReceiver->addEvent(pendingDebugMessages.dequeue());
74void QQmlProfilerClientPrivate::processCurrentEvent()
80 Message rangeStage = currentEvent.type.rangeType() == MaximumRangeType ?
81 currentEvent.type.message() : currentEvent.event.rangeStage();
85 rangesInProgress.push(currentEvent);
88 int typeIndex = resolveStackTop();
91 currentEvent.event.setTypeIndex(typeIndex);
92 while (!pendingMessages.isEmpty())
93 forwardEvents(pendingMessages.dequeue());
94 forwardEvents(currentEvent.event);
95 rangesInProgress.pop();
99 if (!rangesInProgress.isEmpty())
100 rangesInProgress.top().type.setData(currentEvent.type.data());
103 if (!rangesInProgress.isEmpty())
104 rangesInProgress.top().type.setLocation(currentEvent.type.location());
107 currentEvent.event.setTypeIndex(resolveType(currentEvent));
108 pendingDebugMessages.enqueue(currentEvent.event);
111 int typeIndex = resolveType(currentEvent);
112 currentEvent.event.setTypeIndex(typeIndex);
113 if (rangesInProgress.isEmpty())
114 forwardEvents(currentEvent.event);
116 pendingMessages.enqueue(currentEvent.event);
122void QQmlProfilerClientPrivate::sendRecordingStatus(
int engineId)
124 Q_Q(QQmlProfilerClient);
125 QPacket stream(connection->currentDataStreamVersion());
126 stream << recording << engineId;
128 stream << requestedFeatures << flushInterval;
131 q->sendMessage(stream.data());
135 QQmlProfilerEventReceiver *eventReceiver,
137 : QQmlDebugClient(*(
new QQmlProfilerClientPrivate(connection, eventReceiver)))
139 Q_D(QQmlProfilerClient);
140 setRequestedFeatures(features);
141 connect(
this, &QQmlDebugClient::stateChanged,
this, &QQmlProfilerClient::onStateChanged);
142 connect(d->engineControl.data(), &QQmlEngineControlClient::engineAboutToBeAdded,
143 this, &QQmlProfilerClient::sendRecordingStatus);
144 connect(d->engineControl.data(), &QQmlEngineControlClient::engineAboutToBeRemoved,
145 this, [d](
int engineId) {
147 if (d->trackedEngines.contains(engineId))
148 d->engineControl->blockEngine(engineId);
150 connect(
this, &QQmlProfilerClient::traceFinished,
151 d->engineControl.data(), [d](qint64 timestamp,
const QList<
int> &engineIds) {
155 for (
int blocked : d->engineControl->blockedEngines()) {
156 if (engineIds.contains(blocked))
157 d->engineControl->releaseEngine(blocked);
192void QQmlProfilerClientPrivate::finalize()
194 while (!rangesInProgress.isEmpty()) {
195 currentEvent = rangesInProgress.top();
196 currentEvent.event.setRangeStage(RangeEnd);
197 currentEvent.event.setTimestamp(maximumTime);
198 processCurrentEvent();
200 forwardDebugMessages(std::numeric_limits<qint64>::max());
238 Q_D(QQmlProfilerClient);
239 d->requestedFeatures = features;
241 if (d->messageClient.isNull()) {
242 d->messageClient.reset(
new QQmlDebugMessageClient(connection()));
243 connect(d->messageClient.data(), &QQmlDebugMessageClient::message,
this,
244 [
this](QtMsgType type,
const QString &text,
const QQmlDebugContextInfo &context)
246 Q_D(QQmlProfilerClient);
247 d->updateFeatures(ProfileDebugMessages);
248 d->currentEvent.event.setTimestamp(context.timestamp > 0 ? context.timestamp : 0);
249 d->currentEvent.event.setTypeIndex(-1);
250 d->currentEvent.event.setString(text);
251 d->currentEvent.type = QQmlProfilerEventType(
252 DebugMessage, MaximumRangeType, type,
253 QQmlProfilerEventLocation(context.file, context.line, 1));
254 d->currentEvent.serverTypeId = 0;
255 d->processCurrentEvent();
259 d->messageClient.reset();
277bool QQmlProfilerClientPrivate::updateFeatures(ProfileFeature feature)
279 Q_Q(QQmlProfilerClient);
280 quint64 flag = 1ULL << feature;
281 if (!(requestedFeatures & flag))
283 if (!(recordedFeatures & flag)) {
284 recordedFeatures |= flag;
285 emit q->recordedFeaturesChanged(recordedFeatures);
303 Q_D(QQmlProfilerClient);
304 QPacket stream(d->connection->currentDataStreamVersion(), data);
306 stream >> d->currentEvent;
308 d->maximumTime = qMax(d->currentEvent.event.timestamp(), d->maximumTime);
309 if (d->currentEvent.type.message() == Complete) {
311 emit complete(d->maximumTime);
312 }
else if (d->currentEvent.type.message() == Event
313 && d->currentEvent.type.detailType() == StartTrace) {
314 const QList<
int> engineIds = d->currentEvent.event.numbers<QList<
int>, qint32>();
315 d->trackedEngines.append(engineIds);
316 d->forwardDebugMessages(d->currentEvent.event.timestamp());
317 emit traceStarted(d->currentEvent.event.timestamp(), engineIds);
318 }
else if (d->currentEvent.type.message() == Event
319 && d->currentEvent.type.detailType() == EndTrace) {
320 const QList<
int> engineIds = d->currentEvent.event.numbers<QList<
int>, qint32>();
321 for (
int engineId : engineIds)
322 d->trackedEngines.removeAll(engineId);
323 d->forwardDebugMessages(d->currentEvent.event.timestamp());
324 emit traceFinished(d->currentEvent.event.timestamp(), engineIds);
325 }
else if (d->updateFeatures(d->currentEvent.type.feature())) {
326 d->processCurrentEvent();