From c4694275fb5b0965dc4d322602eecea43399b573 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Tue, 8 Nov 2011 16:54:23 +0100 Subject: [PATCH] QmlProfiler: option to get statistics from local region Change-Id: Id11cce971b081d67052dd8e7c74f51e2e25a8fd8 Reviewed-by: Kai Koehne --- .../qmljsdebugclient/qmlprofilereventlist.cpp | 49 +++++++++++++------ .../qmljsdebugclient/qmlprofilereventlist.h | 5 +- src/plugins/qmlprofiler/qml/MainView.qml | 4 ++ .../qmlprofiler/qmlprofilereventview.cpp | 15 ++++++ .../qmlprofiler/qmlprofilereventview.h | 3 ++ src/plugins/qmlprofiler/qmlprofilertool.cpp | 21 ++++++++ src/plugins/qmlprofiler/tracewindow.cpp | 29 +++++++++++ src/plugins/qmlprofiler/tracewindow.h | 4 ++ 8 files changed, 112 insertions(+), 18 deletions(-) diff --git a/src/libs/qmljsdebugclient/qmlprofilereventlist.cpp b/src/libs/qmljsdebugclient/qmlprofilereventlist.cpp index c96f4f9abec..4d67b6a67bf 100644 --- a/src/libs/qmljsdebugclient/qmlprofilereventlist.cpp +++ b/src/libs/qmljsdebugclient/qmlprofilereventlist.cpp @@ -383,8 +383,12 @@ void QmlProfilerEventList::complete() postProcess(); } -void QmlProfilerEventList::compileStatistics() +void QmlProfilerEventList::compileStatistics(qint64 startTime, qint64 endTime) { + int index; + int fromIndex = findFirstIndex(startTime); + int toIndex = findLastIndex(endTime); + // clear existing statistics foreach (QmlEventData *eventDescription, d->m_eventDescriptions.values()) { eventDescription->calls = 0; @@ -399,19 +403,26 @@ void QmlProfilerEventList::compileStatistics() // compute parent-child relationship and call count QHash lastParent; - foreach (QmlEventStartTimeData eventStartData, d->m_startTimeSortedList) { - QmlEventData *eventDescription = eventStartData.description; + for (index = fromIndex; index <= toIndex; index++) { + QmlEventData *eventDescription = d->m_startTimeSortedList[index].description; + + if (d->m_startTimeSortedList[index].startTime > endTime || + d->m_startTimeSortedList[index].startTime+d->m_startTimeSortedList[index].length < startTime) { + continue; + } + eventDescription->calls++; - eventDescription->cumulatedDuration += eventStartData.length; - if (eventDescription->maxTime < eventStartData.length) - eventDescription->maxTime = eventStartData.length; - if (eventDescription->minTime > eventStartData.length) - eventDescription->minTime = eventStartData.length; + qint64 duration = d->m_startTimeSortedList[index].length; + eventDescription->cumulatedDuration += duration; + if (eventDescription->maxTime < duration) + eventDescription->maxTime = duration; + if (eventDescription->minTime > duration) + eventDescription->minTime = duration; - - if (eventStartData.level > MIN_LEVEL) { - if (lastParent.contains(eventStartData.level-1)) { - QmlEventData *parentEvent = lastParent[eventStartData.level-1]; + int level = d->m_startTimeSortedList[index].level; + if (level > MIN_LEVEL) { + if (lastParent.contains(level-1)) { + QmlEventData *parentEvent = lastParent[level-1]; if (!eventDescription->parentList.contains(parentEvent)) eventDescription->parentList.append(parentEvent); if (!parentEvent->childrenList.contains(eventDescription)) @@ -419,7 +430,7 @@ void QmlProfilerEventList::compileStatistics() } } - lastParent[eventStartData.level] = eventDescription; + lastParent[level] = eventDescription; } // compute percentages @@ -435,8 +446,10 @@ void QmlProfilerEventList::compileStatistics() // compute median time QHash < QmlEventData* , QList > durationLists; - foreach (const QmlEventStartTimeData &startData, d->m_startTimeSortedList) { - durationLists[startData.description].append(startData.length); + for (index = fromIndex; index <= toIndex; index++) { + QmlEventData *desc = d->m_startTimeSortedList[index].description; + qint64 len = d->m_startTimeSortedList[index].length; + durationLists[desc].append(len); } QMutableHashIterator < QmlEventData* , QList > iter(durationLists); while (iter.hasNext()) { @@ -446,7 +459,10 @@ void QmlProfilerEventList::compileStatistics() iter.key()->medianTime = iter.value().at(iter.value().count()/2); } } +} +void QmlProfilerEventList::prepareForDisplay() +{ // generate numeric ids int ndx = 0; foreach (QmlEventData *binding, d->m_eventDescriptions.values()) { @@ -624,8 +640,9 @@ void QmlProfilerEventList::postProcess() sortStartTimes(); sortEndTimes(); computeLevels(); - compileStatistics(); linkEndsToStarts(); + prepareForDisplay(); + compileStatistics(traceStartTime(), traceEndTime()); emit dataReady(); } diff --git a/src/libs/qmljsdebugclient/qmlprofilereventlist.h b/src/libs/qmljsdebugclient/qmlprofilereventlist.h index d409d53ddb6..b54cc09e529 100644 --- a/src/libs/qmljsdebugclient/qmlprofilereventlist.h +++ b/src/libs/qmljsdebugclient/qmlprofilereventlist.h @@ -125,6 +125,7 @@ public: Q_INVOKABLE qint64 traceDuration() const; void showErrorDialog(const QString &st ) const; + void compileStatistics(qint64 startTime, qint64 endTime); signals: void dataReady(); void countChanged(); @@ -147,14 +148,14 @@ public slots: void setTraceEndTime( qint64 time ); void setTraceStartTime( qint64 time ); -private slots: +private: void postProcess(); void sortEndTimes(); void sortStartTimes(); void computeLevels(); void computeNestingLevels(); void computeNestingDepth(); - void compileStatistics(); + void prepareForDisplay(); void linkEndsToStarts(); private: diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml index 1e147ac38d9..a7ff62b13e6 100644 --- a/src/plugins/qmlprofiler/qml/MainView.qml +++ b/src/plugins/qmlprofiler/qml/MainView.qml @@ -66,6 +66,10 @@ Rectangle { signal updateRangeButton property bool selectionRangeMode: false + property bool selectionRangeReady: selectionRange.ready + property variant selectionRangeStart: selectionRange.startTime + property variant selectionRangeEnd: selectionRange.startTime + selectionRange.duration + // ***** connections with external objects Connections { target: zoomControl diff --git a/src/plugins/qmlprofiler/qmlprofilereventview.cpp b/src/plugins/qmlprofiler/qmlprofilereventview.cpp index ad9a2794e34..8d51a0b4f5f 100644 --- a/src/plugins/qmlprofiler/qmlprofilereventview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilereventview.cpp @@ -138,6 +138,12 @@ void QmlProfilerEventsWidget::clear() m_eventParents->clear(); } +void QmlProfilerEventsWidget::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) +{ + clear(); + m_eventTree->getStatisticsInRange(rangeStart, rangeEnd); +} + QModelIndex QmlProfilerEventsWidget::selectedItem() const { return m_eventTree->selectedItem(); @@ -375,6 +381,9 @@ void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFrom if (visitedFunctionsList.contains(binding)) continue; + if (binding->calls == 0) + continue; + QList newRow; if (m_fieldShown[Name]) { newRow << new EventsViewItem(binding->displayname); @@ -531,6 +540,12 @@ QString QmlProfilerEventsMainView::nameForType(int typeNumber) return QString(); } +void QmlProfilerEventsMainView::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) +{ + d->m_eventStatistics->compileStatistics(rangeStart, rangeEnd); + buildModel(); +} + void QmlProfilerEventsMainView::jumpToItem(const QModelIndex &index) { QStandardItem *clickedItem = d->m_model->itemFromIndex(index); diff --git a/src/plugins/qmlprofiler/qmlprofilereventview.h b/src/plugins/qmlprofiler/qmlprofilereventview.h index 221396f40a1..580cc5b44a3 100644 --- a/src/plugins/qmlprofiler/qmlprofilereventview.h +++ b/src/plugins/qmlprofiler/qmlprofilereventview.h @@ -64,6 +64,7 @@ public: void switchToV8View(); void clear(); + void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); QModelIndex selectedItem() const; bool mouseOnTable(const QPoint &position) const; void copyTableToClipboard() const; @@ -128,6 +129,8 @@ public: static QString nameForType(int typeNumber); + void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); + signals: void gotoSourceLocation(const QString &fileName, int lineNumber); void eventSelected(int eventId); diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp index 6655e4239ed..c2d93ca8b4d 100644 --- a/src/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp @@ -182,7 +182,11 @@ void QmlProfilerTool::showContextMenu(const QPoint &position) QAction *copyRowAction = 0; QAction *copyTableAction = 0; QAction *viewAllAction = 0; + QAction *getLocalStatsAction = 0; + QAction *getGlobalStatsAction = 0; + if (eventView && eventView->mouseOnTable(position)) { + menu.addSeparator(); if (eventView->selectedItem().isValid()) copyRowAction = menu.addAction(tr("Copy Row")); copyTableAction = menu.addAction(tr("Copy Table")); @@ -195,6 +199,13 @@ void QmlProfilerTool::showContextMenu(const QPoint &position) } } + if (sender() == d->m_traceWindow || sender() == d->m_eventsView) { + menu.addSeparator(); + if (d->m_traceWindow->hasValidSelection()) + getLocalStatsAction = menu.addAction(tr("Get Stats For Current Range")); + getGlobalStatsAction = menu.addAction(tr("Get Global Statistics")); + } + QAction *selectedAction = menu.exec(position); if (selectedAction) { @@ -208,6 +219,16 @@ void QmlProfilerTool::showContextMenu(const QPoint &position) eventView->copyTableToClipboard(); if (selectedAction == viewAllAction) traceView->viewAll(); + if (selectedAction == getLocalStatsAction) { + d->m_eventsView->getStatisticsInRange( + d->m_traceWindow->selectionStart(), + d->m_traceWindow->selectionEnd()); + } + if (selectedAction == getGlobalStatsAction) { + d->m_eventsView->getStatisticsInRange( + d->m_traceWindow->getEventList()->traceStartTime(), + d->m_traceWindow->getEventList()->traceEndTime()); + } } } diff --git a/src/plugins/qmlprofiler/tracewindow.cpp b/src/plugins/qmlprofiler/tracewindow.cpp index 9696ad74541..18b18a13472 100644 --- a/src/plugins/qmlprofiler/tracewindow.cpp +++ b/src/plugins/qmlprofiler/tracewindow.cpp @@ -296,6 +296,11 @@ QmlProfilerEventList *TraceWindow::getEventList() const return m_eventList; } +ZoomControl *TraceWindow::rangeTimes() const +{ + return m_zoomControl.data(); +} + void TraceWindow::contextMenuEvent(QContextMenuEvent *ev) { emit contextMenuRequested(ev->globalPos()); @@ -434,6 +439,30 @@ void TraceWindow::viewAll() emit globalZoom(); } +bool TraceWindow::hasValidSelection() const +{ + if (m_mainView->rootObject()) { + return m_mainView->rootObject()->property("selectionRangeReady").toBool(); + } + return false; +} + +qint64 TraceWindow::selectionStart() const +{ + if (m_mainView->rootObject()) { + return m_mainView->rootObject()->property("selectionRangeStart").toLongLong(); + } + return 0; +} + +qint64 TraceWindow::selectionEnd() const +{ + if (m_mainView->rootObject()) { + return m_mainView->rootObject()->property("selectionRangeEnd").toLongLong(); + } + return 0; +} + void TraceWindow::setZoomLevel(int zoomLevel) { if (m_currentZoomLevel != zoomLevel && m_mainView->rootObject()) { diff --git a/src/plugins/qmlprofiler/tracewindow.h b/src/plugins/qmlprofiler/tracewindow.h index 3642fde54c5..6ca931fe838 100644 --- a/src/plugins/qmlprofiler/tracewindow.h +++ b/src/plugins/qmlprofiler/tracewindow.h @@ -91,11 +91,15 @@ public: void reset(QmlJsDebugClient::QDeclarativeDebugConnection *conn); QmlJsDebugClient::QmlProfilerEventList *getEventList() const; + ZoomControl *rangeTimes() const; void setRecording(bool recording); bool isRecording() const; void viewAll(); + bool hasValidSelection() const; + qint64 selectionStart() const; + qint64 selectionEnd() const; public slots: void updateCursorPosition();