14int QQmlProfilerClientPrivate::resolveType(
const QQmlProfilerTypedEvent &event)
17 if (event.serverTypeId != 0) {
18 QHash<qint64,
int>::ConstIterator it = serverTypeIds.constFind(event.serverTypeId);
20 if (it != serverTypeIds.constEnd()) {
21 typeIndex = it.value();
23 typeIndex = eventReceiver->numLoadedEventTypes();
24 eventReceiver->addEventType(event.type);
25 serverTypeIds[event.serverTypeId] = typeIndex;
28 QHash<QQmlProfilerEventType,
int>::ConstIterator it = eventTypeIds.constFind(event.type);
30 if (it != eventTypeIds.constEnd()) {
31 typeIndex = it.value();
33 typeIndex = eventReceiver->numLoadedEventTypes();
34 eventReceiver->addEventType(event.type);
35 eventTypeIds[event.type] = typeIndex;
41int QQmlProfilerClientPrivate::resolveStackTop()
43 if (rangesInProgress.isEmpty())
46 QQmlProfilerTypedEvent &typedEvent = rangesInProgress.top();
47 int typeIndex = typedEvent.event.typeIndex();
51 typeIndex = resolveType(typedEvent);
52 typedEvent.event.setTypeIndex(typeIndex);
53 while (!pendingMessages.isEmpty()
54 && pendingMessages.head().timestamp() < typedEvent.event.timestamp()) {
55 forwardEvents(pendingMessages.dequeue());
57 forwardEvents(typedEvent.event);
67void QQmlProfilerClientPrivate::forwardDebugMessages(qint64 untilTimestamp)
69 while (!pendingDebugMessages.isEmpty()
70 && pendingDebugMessages.front().timestamp() <= untilTimestamp) {
71 eventReceiver->addEvent(pendingDebugMessages.dequeue());
75void QQmlProfilerClientPrivate::processCurrentEvent()
81 Message rangeStage = currentEvent.type.rangeType() == MaximumRangeType ?
82 currentEvent.type.message() : currentEvent.event.rangeStage();
86 rangesInProgress.push(currentEvent);
89 int typeIndex = resolveStackTop();
92 currentEvent.event.setTypeIndex(typeIndex);
93 while (!pendingMessages.isEmpty())
94 forwardEvents(pendingMessages.dequeue());
95 forwardEvents(currentEvent.event);
96 rangesInProgress.pop();
100 if (!rangesInProgress.isEmpty())
101 rangesInProgress.top().type.setData(currentEvent.type.data());
104 if (!rangesInProgress.isEmpty())
105 rangesInProgress.top().type.setLocation(currentEvent.type.location());
108 currentEvent.event.setTypeIndex(resolveType(currentEvent));
109 pendingDebugMessages.enqueue(currentEvent.event);
112 int typeIndex = resolveType(currentEvent);
113 currentEvent.event.setTypeIndex(typeIndex);
114 if (rangesInProgress.isEmpty())
115 forwardEvents(currentEvent.event);
117 pendingMessages.enqueue(currentEvent.event);
123void QQmlProfilerClientPrivate::sendRecordingStatus(
int engineId)
125 Q_Q(QQmlProfilerClient);
126 QPacket stream(connection->currentDataStreamVersion());
127 stream << recording << engineId;
129 stream << requestedFeatures << flushInterval;
132 q->sendMessage(stream.data());
136 QQmlProfilerEventReceiver *eventReceiver,
138 : QQmlDebugClient(*(
new QQmlProfilerClientPrivate(connection, eventReceiver)))
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) {
148 if (d->trackedEngines.contains(engineId))
149 d->engineControl->blockEngine(engineId);
151 connect(
this, &QQmlProfilerClient::traceFinished,
152 d->engineControl.data(), [d](qint64 timestamp,
const QList<
int> &engineIds) {
156 for (
int blocked : d->engineControl->blockedEngines()) {
157 if (engineIds.contains(blocked))
158 d->engineControl->releaseEngine(blocked);
193void QQmlProfilerClientPrivate::finalize()
195 while (!rangesInProgress.isEmpty()) {
196 currentEvent = rangesInProgress.top();
197 currentEvent.event.setRangeStage(RangeEnd);
198 currentEvent.event.setTimestamp(maximumTime);
199 processCurrentEvent();
201 forwardDebugMessages(std::numeric_limits<qint64>::max());
239 Q_D(QQmlProfilerClient);
240 d->requestedFeatures = features;
242 if (d->messageClient.isNull()) {
243 d->messageClient.reset(
new QQmlDebugMessageClient(connection()));
244 connect(d->messageClient.data(), &QQmlDebugMessageClient::message,
this,
245 [
this](QtMsgType type,
const QString &text,
const QQmlDebugContextInfo &context)
247 Q_D(QQmlProfilerClient);
248 d->updateFeatures(ProfileDebugMessages);
249 d->currentEvent.event.setTimestamp(context.timestamp > 0 ? context.timestamp : 0);
250 d->currentEvent.event.setTypeIndex(-1);
251 d->currentEvent.event.setString(text);
252 d->currentEvent.type = QQmlProfilerEventType(
253 DebugMessage, MaximumRangeType, type,
254 QQmlProfilerEventLocation(context.file, context.line, 1));
255 d->currentEvent.serverTypeId = 0;
256 d->processCurrentEvent();
260 d->messageClient.reset();
278bool QQmlProfilerClientPrivate::updateFeatures(ProfileFeature feature)
280 Q_Q(QQmlProfilerClient);
281 quint64 flag = 1ULL << feature;
282 if (!(requestedFeatures & flag))
284 if (!(recordedFeatures & flag)) {
285 recordedFeatures |= flag;
286 emit q->recordedFeaturesChanged(recordedFeatures);
304 Q_D(QQmlProfilerClient);
305 QPacket stream(d->connection->currentDataStreamVersion(), data);
307 stream >> d->currentEvent;
309 d->maximumTime = qMax(d->currentEvent.event.timestamp(), d->maximumTime);
310 if (d->currentEvent.type.message() == Complete) {
312 emit complete(d->maximumTime);
313 }
else if (d->currentEvent.type.message() == Event
314 && d->currentEvent.type.detailType() == StartTrace) {
315 const QList<
int> engineIds = d->currentEvent.event.numbers<QList<
int>, qint32>();
316 d->trackedEngines.append(engineIds);
317 d->forwardDebugMessages(d->currentEvent.event.timestamp());
318 emit traceStarted(d->currentEvent.event.timestamp(), engineIds);
319 }
else if (d->currentEvent.type.message() == Event
320 && d->currentEvent.type.detailType() == EndTrace) {
321 const QList<
int> engineIds = d->currentEvent.event.numbers<QList<
int>, qint32>();
322 for (
int engineId : engineIds)
323 d->trackedEngines.removeAll(engineId);
324 d->forwardDebugMessages(d->currentEvent.event.timestamp());
325 emit traceFinished(d->currentEvent.event.timestamp(), engineIds);
326 }
else if (d->updateFeatures(d->currentEvent.type.feature())) {
327 d->processCurrentEvent();