forked from qt-creator/qt-creator
QmlProfiler: showing children time and count in events pane
Change-Id: Ia285d1c84312e6a314fbf1c59c62b571b4c3e7d4 Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
This commit is contained in:
@@ -54,10 +54,115 @@ const char *const TYPE_COMPILING_STR = "Compiling";
|
||||
const char *const TYPE_CREATING_STR = "Creating";
|
||||
const char *const TYPE_BINDING_STR = "Binding";
|
||||
const char *const TYPE_HANDLINGSIGNAL_STR = "HandlingSignal";
|
||||
const char *const PROFILER_FILE_VERSION = "1.01";
|
||||
}
|
||||
|
||||
#define MIN_LEVEL 1
|
||||
|
||||
QmlEventData::QmlEventData()
|
||||
{
|
||||
line = -1;
|
||||
eventType = MaximumQmlEventType;
|
||||
eventId = -1;
|
||||
duration = 0;
|
||||
calls = 0;
|
||||
minTime = 0;
|
||||
maxTime = 0;
|
||||
timePerCall = 0;
|
||||
percentOfTime = 0;
|
||||
medianTime = 0;
|
||||
}
|
||||
|
||||
QmlEventData::~QmlEventData()
|
||||
{
|
||||
qDeleteAll(parentHash.values());
|
||||
parentHash.clear();
|
||||
qDeleteAll(childrenHash.values());
|
||||
childrenHash.clear();
|
||||
}
|
||||
|
||||
QmlEventData &QmlEventData::operator=(const QmlEventData &ref)
|
||||
{
|
||||
if (this == &ref)
|
||||
return *this;
|
||||
|
||||
displayname = ref.displayname;
|
||||
filename = ref.filename;
|
||||
eventHashStr = ref.eventHashStr;
|
||||
details = ref.details;
|
||||
line = ref.line;
|
||||
eventType = ref.eventType;
|
||||
duration = ref.duration;
|
||||
calls = ref.calls;
|
||||
minTime = ref.minTime;
|
||||
maxTime = ref.maxTime;
|
||||
timePerCall = ref.timePerCall;
|
||||
percentOfTime = ref.percentOfTime;
|
||||
medianTime = ref.medianTime;
|
||||
eventId = ref.eventId;
|
||||
|
||||
qDeleteAll(parentHash.values());
|
||||
parentHash.clear();
|
||||
foreach (const QString &key, ref.parentHash.keys()) {
|
||||
parentHash.insert(key, new QmlEventSub(ref.parentHash.value(key)));
|
||||
}
|
||||
|
||||
qDeleteAll(childrenHash.values());
|
||||
childrenHash.clear();
|
||||
foreach (const QString &key, ref.childrenHash.keys()) {
|
||||
childrenHash.insert(key, new QmlEventSub(ref.childrenHash.value(key)));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
QV8EventData::QV8EventData()
|
||||
{
|
||||
line = -1;
|
||||
eventId = -1;
|
||||
totalTime = 0;
|
||||
selfTime = 0;
|
||||
totalPercent = 0;
|
||||
selfPercent = 0;
|
||||
}
|
||||
|
||||
QV8EventData::~QV8EventData()
|
||||
{
|
||||
qDeleteAll(parentHash.values());
|
||||
parentHash.clear();
|
||||
qDeleteAll(childrenHash.values());
|
||||
childrenHash.clear();
|
||||
}
|
||||
|
||||
QV8EventData &QV8EventData::operator=(const QV8EventData &ref)
|
||||
{
|
||||
if (this == &ref)
|
||||
return *this;
|
||||
|
||||
displayName = ref.displayName;
|
||||
filename = ref.filename;
|
||||
functionName = ref.functionName;
|
||||
line = ref.line;
|
||||
totalTime = ref.totalTime;
|
||||
totalPercent = ref.totalPercent;
|
||||
selfTime = ref.selfTime;
|
||||
selfPercent = ref.selfPercent;
|
||||
eventId = ref.eventId;
|
||||
|
||||
qDeleteAll(parentHash.values());
|
||||
parentHash.clear();
|
||||
foreach (const QString &key, ref.parentHash.keys()) {
|
||||
parentHash.insert(key, new QV8EventSub(ref.parentHash.value(key)));
|
||||
}
|
||||
|
||||
qDeleteAll(childrenHash.values());
|
||||
childrenHash.clear();
|
||||
foreach (const QString &key, ref.childrenHash.keys()) {
|
||||
childrenHash.insert(key, new QV8EventSub(ref.childrenHash.value(key)));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// endtimedata
|
||||
struct QmlEventEndTimeData {
|
||||
qint64 endTime;
|
||||
@@ -151,6 +256,10 @@ public:
|
||||
|
||||
QmlProfilerEventList *q;
|
||||
|
||||
// convenience functions
|
||||
void clearQmlRootEvent();
|
||||
void clearV8RootEvent();
|
||||
|
||||
// Stored data
|
||||
QmlEventHash m_eventDescriptions;
|
||||
QList<QmlEventEndTimeData> m_endTimeSortedList;
|
||||
@@ -160,6 +269,11 @@ public:
|
||||
QV8EventDescriptions m_v8EventList;
|
||||
QHash<int, QV8EventData *> m_v8parents;
|
||||
|
||||
QmlEventData m_qmlRootEvent;
|
||||
QV8EventData m_v8RootEvent;
|
||||
QString m_rootEventName;
|
||||
QString m_rootEventDesc;
|
||||
|
||||
QHash<int, QmlEventTypeCount *> m_typeCounts;
|
||||
|
||||
qint64 m_traceEndTime;
|
||||
@@ -184,6 +298,11 @@ QmlProfilerEventList::QmlProfilerEventList(QObject *parent) :
|
||||
d->m_traceStartTime = -1;
|
||||
d->m_qmlMeasuredTime = 0;
|
||||
d->m_v8MeasuredTime = 0;
|
||||
d->m_rootEventName = tr("<program>");
|
||||
d->m_rootEventDesc = tr("Main Program");
|
||||
d->clearQmlRootEvent();
|
||||
d->clearV8RootEvent();
|
||||
|
||||
}
|
||||
|
||||
QmlProfilerEventList::~QmlProfilerEventList()
|
||||
@@ -193,17 +312,20 @@ QmlProfilerEventList::~QmlProfilerEventList()
|
||||
|
||||
void QmlProfilerEventList::clear()
|
||||
{
|
||||
foreach (QmlEventData *binding, d->m_eventDescriptions.values())
|
||||
delete binding;
|
||||
qDeleteAll(d->m_eventDescriptions.values());
|
||||
d->m_eventDescriptions.clear();
|
||||
|
||||
qDeleteAll(d->m_v8EventList);
|
||||
d->m_v8EventList.clear();
|
||||
|
||||
d->m_endTimeSortedList.clear();
|
||||
d->m_startTimeSortedList.clear();
|
||||
|
||||
qDeleteAll(d->m_v8EventList);
|
||||
d->m_v8EventList.clear();
|
||||
d->m_v8parents.clear();
|
||||
|
||||
d->clearQmlRootEvent();
|
||||
d->clearV8RootEvent();
|
||||
|
||||
foreach (QmlEventTypeCount *typeCount, d->m_typeCounts.values())
|
||||
delete typeCount;
|
||||
d->m_typeCounts.clear();
|
||||
@@ -249,24 +371,10 @@ void QmlProfilerEventList::addRangedEvent(int type, qint64 startTime, qint64 len
|
||||
const QStringList &data, const QString &fileName, int line)
|
||||
{
|
||||
const QChar colon = QLatin1Char(':');
|
||||
QString displayName, location, details;
|
||||
QString displayName, eventHashStr, details;
|
||||
|
||||
emit processingData();
|
||||
|
||||
if (fileName.isEmpty()) {
|
||||
displayName = tr("<bytecode>");
|
||||
location = QString("--:%1:%2").arg(QString::number(type), data.join(" "));
|
||||
} else {
|
||||
const QString filePath = QUrl(fileName).path();
|
||||
displayName = filePath.mid(filePath.lastIndexOf(QChar('/')) + 1) + colon + QString::number(line);
|
||||
location = fileName+colon+QString::number(line);
|
||||
}
|
||||
|
||||
QmlEventData *newEvent;
|
||||
if (d->m_eventDescriptions.contains(location)) {
|
||||
newEvent = d->m_eventDescriptions[location];
|
||||
} else {
|
||||
|
||||
// generate details string
|
||||
if (data.isEmpty())
|
||||
details = tr("Source code not available");
|
||||
@@ -281,14 +389,28 @@ void QmlProfilerEventList::addRangedEvent(int type, qint64 startTime, qint64 len
|
||||
details = details.mid(details.lastIndexOf(QChar('/')) + 1);
|
||||
}
|
||||
|
||||
newEvent = new QmlEventData();
|
||||
// generate hash
|
||||
if (fileName.isEmpty()) {
|
||||
displayName = tr("<bytecode>");
|
||||
eventHashStr = QString("--:%1:%2").arg(QString::number(type), details);
|
||||
} else {
|
||||
const QString filePath = QUrl(fileName).path();
|
||||
displayName = filePath.mid(filePath.lastIndexOf(QChar('/')) + 1) + colon + QString::number(line);
|
||||
eventHashStr = QString("%1:%2:%3:%4").arg(fileName, QString::number(line), QString::number(type), details);
|
||||
}
|
||||
|
||||
QmlEventData *newEvent;
|
||||
if (d->m_eventDescriptions.contains(eventHashStr)) {
|
||||
newEvent = d->m_eventDescriptions[eventHashStr];
|
||||
} else {
|
||||
newEvent = new QmlEventData;
|
||||
newEvent->displayname = displayName;
|
||||
newEvent->filename = fileName;
|
||||
newEvent->location = location;
|
||||
newEvent->eventHashStr = eventHashStr;
|
||||
newEvent->line = line;
|
||||
newEvent->eventType = (QmlJsDebugClient::QmlEventType)type;
|
||||
newEvent->details = details;
|
||||
d->m_eventDescriptions.insert(location, newEvent);
|
||||
d->m_eventDescriptions.insert(eventHashStr, newEvent);
|
||||
}
|
||||
|
||||
QmlEventEndTimeData endTimeData;
|
||||
@@ -311,7 +433,7 @@ void QmlProfilerEventList::addRangedEvent(int type, qint64 startTime, qint64 len
|
||||
void QmlProfilerEventList::addV8Event(int depth, const QString &function, const QString &filename, int lineNumber, double totalTime, double selfTime)
|
||||
{
|
||||
QString displayName = filename.mid(filename.lastIndexOf(QLatin1Char('/')) + 1) + QLatin1Char(':') + QString::number(lineNumber);
|
||||
QV8EventData *newData = 0;
|
||||
QV8EventData *eventData = 0;
|
||||
|
||||
// time is given in milliseconds, but internally we store it in microseconds
|
||||
totalTime *= 1e6;
|
||||
@@ -319,45 +441,65 @@ void QmlProfilerEventList::addV8Event(int depth, const QString &function, const
|
||||
|
||||
// cumulate information
|
||||
foreach (QV8EventData *v8event, d->m_v8EventList) {
|
||||
if (v8event->displayName == displayName && v8event->functionName == function)
|
||||
newData = v8event;
|
||||
if (v8event->displayName == displayName && v8event->functionName == function) {
|
||||
eventData = v8event;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!newData) {
|
||||
newData = new QV8EventData();
|
||||
newData->displayName = displayName;
|
||||
newData->filename = filename;
|
||||
newData->functionName = function;
|
||||
newData->line = lineNumber;
|
||||
newData->totalTime = totalTime;
|
||||
newData->selfTime = selfTime;
|
||||
d->m_v8EventList << newData;
|
||||
if (!eventData) {
|
||||
eventData = new QV8EventData;
|
||||
eventData->displayName = displayName;
|
||||
eventData->filename = filename;
|
||||
eventData->functionName = function;
|
||||
eventData->line = lineNumber;
|
||||
eventData->totalTime = totalTime;
|
||||
eventData->selfTime = selfTime;
|
||||
d->m_v8EventList << eventData;
|
||||
} else {
|
||||
newData->totalTime += totalTime;
|
||||
newData->selfTime += selfTime;
|
||||
eventData->totalTime += totalTime;
|
||||
eventData->selfTime += selfTime;
|
||||
}
|
||||
d->m_v8parents[depth] = newData;
|
||||
d->m_v8parents[depth] = eventData;
|
||||
|
||||
if (depth > 0) {
|
||||
QV8EventData* parentEvent = d->m_v8parents.value(depth-1);
|
||||
if (parentEvent) {
|
||||
if (!newData->parentList.contains(parentEvent))
|
||||
newData->parentList << parentEvent;
|
||||
if (!parentEvent->childrenList.contains(newData))
|
||||
parentEvent->childrenList << newData;
|
||||
}
|
||||
} else {
|
||||
QV8EventData *parentEvent = 0;
|
||||
if (depth == 0) {
|
||||
parentEvent = &d->m_v8RootEvent;
|
||||
d->m_v8MeasuredTime += totalTime;
|
||||
}
|
||||
if (depth > 0 && d->m_v8parents.contains(depth-1)) {
|
||||
parentEvent = d->m_v8parents.value(depth-1);
|
||||
}
|
||||
|
||||
if (parentEvent != 0) {
|
||||
if (!eventData->parentHash.contains(parentEvent->displayName)) {
|
||||
QV8EventSub *newParentSub = new QV8EventSub(parentEvent);
|
||||
newParentSub->totalTime = totalTime;
|
||||
|
||||
eventData->parentHash.insert(parentEvent->displayName, newParentSub );
|
||||
} else {
|
||||
QV8EventSub *newParentSub = eventData->parentHash.value(parentEvent->displayName);
|
||||
newParentSub->totalTime += totalTime;
|
||||
}
|
||||
|
||||
if (!parentEvent->childrenHash.contains(eventData->displayName)) {
|
||||
QV8EventSub *newChildSub = new QV8EventSub(eventData);
|
||||
newChildSub->totalTime = totalTime;
|
||||
|
||||
parentEvent->childrenHash.insert(eventData->displayName, newChildSub);
|
||||
} else {
|
||||
QV8EventSub *newChildSub = parentEvent->childrenHash.value(eventData->displayName);
|
||||
newChildSub->totalTime += totalTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QmlProfilerEventList::QmlProfilerEventListPrivate::collectV8Statistics()
|
||||
{
|
||||
if (!m_v8EventList.isEmpty()) {
|
||||
double totalTimes = 0;
|
||||
double totalTimes = m_v8MeasuredTime;
|
||||
double selfTimes = 0;
|
||||
foreach (QV8EventData *v8event, m_v8EventList) {
|
||||
totalTimes += v8event->totalTime;
|
||||
selfTimes += v8event->selfTime;
|
||||
}
|
||||
|
||||
@@ -367,15 +509,38 @@ void QmlProfilerEventList::QmlProfilerEventListPrivate::collectV8Statistics()
|
||||
if (selfTimes == 0)
|
||||
selfTimes = 1;
|
||||
|
||||
// insert root event in eventlist
|
||||
// the +1 ns is to get it on top of the sorted list
|
||||
m_v8RootEvent.totalTime = m_v8MeasuredTime + 1;
|
||||
m_v8RootEvent.selfTime = 0;
|
||||
|
||||
int rootEventIndex = -1;
|
||||
for (int ndx = 0; ndx < m_v8EventList.count(); ndx++)
|
||||
{
|
||||
if (m_v8EventList.at(ndx)->displayName == m_rootEventName) {
|
||||
m_v8RootEvent = *m_v8EventList.at(ndx);
|
||||
rootEventIndex = ndx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rootEventIndex == -1) {
|
||||
rootEventIndex = m_v8EventList.count();
|
||||
QV8EventData *newRootEvent = new QV8EventData;
|
||||
*newRootEvent = m_v8RootEvent;
|
||||
m_v8EventList << newRootEvent;
|
||||
}
|
||||
|
||||
foreach (QV8EventData *v8event, m_v8EventList) {
|
||||
v8event->totalPercent = v8event->totalTime * 100.0 / totalTimes;
|
||||
v8event->selfPercent = v8event->selfTime * 100.0 / selfTimes;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
foreach (QV8EventData *v8event, m_v8EventList)
|
||||
foreach (QV8EventData *v8event, m_v8EventList) {
|
||||
v8event->eventId = index++;
|
||||
}
|
||||
m_v8RootEvent.eventId = m_v8EventList[rootEventIndex]->eventId;
|
||||
}
|
||||
}
|
||||
|
||||
void QmlProfilerEventList::setTraceEndTime( qint64 time )
|
||||
@@ -395,11 +560,52 @@ void QmlProfilerEventList::complete()
|
||||
postProcess();
|
||||
}
|
||||
|
||||
void QmlProfilerEventList::QmlProfilerEventListPrivate::clearQmlRootEvent()
|
||||
{
|
||||
m_qmlRootEvent.displayname = m_rootEventName;
|
||||
m_qmlRootEvent.filename = QString();
|
||||
m_qmlRootEvent.eventHashStr = m_rootEventName;
|
||||
m_qmlRootEvent.details = m_rootEventDesc;
|
||||
m_qmlRootEvent.line = 01;
|
||||
m_qmlRootEvent.eventType = QmlJsDebugClient::Binding;
|
||||
m_qmlRootEvent.duration = 0;
|
||||
m_qmlRootEvent.calls = 0;
|
||||
m_qmlRootEvent.minTime = 0;
|
||||
m_qmlRootEvent.maxTime = 0;
|
||||
m_qmlRootEvent.timePerCall = 0;
|
||||
m_qmlRootEvent.percentOfTime = 0;
|
||||
m_qmlRootEvent.medianTime = 0;
|
||||
m_qmlRootEvent.eventId = -1;
|
||||
|
||||
qDeleteAll(m_qmlRootEvent.parentHash.values());
|
||||
qDeleteAll(m_qmlRootEvent.childrenHash.values());
|
||||
m_qmlRootEvent.parentHash.clear();
|
||||
m_qmlRootEvent.childrenHash.clear();
|
||||
}
|
||||
|
||||
void QmlProfilerEventList::QmlProfilerEventListPrivate::clearV8RootEvent()
|
||||
{
|
||||
m_v8RootEvent.displayName = m_rootEventName;
|
||||
m_v8RootEvent.functionName = m_rootEventDesc;
|
||||
m_v8RootEvent.line = -1;
|
||||
m_v8RootEvent.totalTime = 0;
|
||||
m_v8RootEvent.totalPercent = 0;
|
||||
m_v8RootEvent.selfTime = 0;
|
||||
m_v8RootEvent.selfPercent = 0;
|
||||
m_v8RootEvent.eventId = -1;
|
||||
|
||||
qDeleteAll(m_v8RootEvent.parentHash.values());
|
||||
qDeleteAll(m_v8RootEvent.childrenHash.values());
|
||||
m_v8RootEvent.parentHash.clear();
|
||||
m_v8RootEvent.childrenHash.clear();
|
||||
}
|
||||
|
||||
void QmlProfilerEventList::compileStatistics(qint64 startTime, qint64 endTime)
|
||||
{
|
||||
int index;
|
||||
int fromIndex = findFirstIndex(startTime);
|
||||
int toIndex = findLastIndex(endTime);
|
||||
double totalTime = 0;
|
||||
|
||||
// clear existing statistics
|
||||
foreach (QmlEventData *eventDescription, d->m_eventDescriptions.values()) {
|
||||
@@ -408,11 +614,16 @@ void QmlProfilerEventList::compileStatistics(qint64 startTime, qint64 endTime)
|
||||
eventDescription->minTime = d->m_endTimeSortedList.last().endTime;
|
||||
eventDescription->maxTime = 0;
|
||||
eventDescription->medianTime = 0;
|
||||
eventDescription->cumulatedDuration = 0;
|
||||
eventDescription->parentList.clear();
|
||||
eventDescription->childrenList.clear();
|
||||
eventDescription->duration = 0;
|
||||
qDeleteAll(eventDescription->parentHash);
|
||||
qDeleteAll(eventDescription->childrenHash);
|
||||
eventDescription->parentHash.clear();
|
||||
eventDescription->childrenHash.clear();
|
||||
}
|
||||
|
||||
// create root event for statistics
|
||||
d->clearQmlRootEvent();
|
||||
|
||||
// compute parent-child relationship and call count
|
||||
QHash<int, QmlEventData*> lastParent;
|
||||
for (index = fromIndex; index <= toIndex; index++) {
|
||||
@@ -425,35 +636,71 @@ void QmlProfilerEventList::compileStatistics(qint64 startTime, qint64 endTime)
|
||||
|
||||
eventDescription->calls++;
|
||||
qint64 duration = d->m_startTimeSortedList[index].length;
|
||||
eventDescription->cumulatedDuration += duration;
|
||||
eventDescription->duration += duration;
|
||||
if (eventDescription->maxTime < duration)
|
||||
eventDescription->maxTime = duration;
|
||||
if (eventDescription->minTime > duration)
|
||||
eventDescription->minTime = duration;
|
||||
|
||||
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))
|
||||
parentEvent->childrenList.append(eventDescription);
|
||||
|
||||
QmlEventData *parentEvent = &d->m_qmlRootEvent;
|
||||
if (level > MIN_LEVEL && lastParent.contains(level-1)) {
|
||||
parentEvent = lastParent[level-1];
|
||||
}
|
||||
|
||||
if (!eventDescription->parentHash.contains(parentEvent->eventHashStr)) {
|
||||
QmlEventSub *newParentEvent = new QmlEventSub(parentEvent);
|
||||
newParentEvent->calls = 1;
|
||||
newParentEvent->duration = duration;
|
||||
|
||||
eventDescription->parentHash.insert(parentEvent->eventHashStr, newParentEvent);
|
||||
} else {
|
||||
QmlEventSub *newParentEvent = eventDescription->parentHash.value(parentEvent->eventHashStr);
|
||||
newParentEvent->duration += duration;
|
||||
newParentEvent->calls++;
|
||||
}
|
||||
|
||||
if (!parentEvent->childrenHash.contains(eventDescription->eventHashStr)) {
|
||||
QmlEventSub *newChildEvent = new QmlEventSub(eventDescription);
|
||||
newChildEvent->calls = 1;
|
||||
newChildEvent->duration = duration;
|
||||
|
||||
parentEvent->childrenHash.insert(eventDescription->eventHashStr, newChildEvent);
|
||||
} else {
|
||||
QmlEventSub *newChildEvent = parentEvent->childrenHash.value(eventDescription->eventHashStr);
|
||||
newChildEvent->duration += duration;
|
||||
newChildEvent->calls++;
|
||||
}
|
||||
|
||||
lastParent[level] = eventDescription;
|
||||
|
||||
if (level == MIN_LEVEL) {
|
||||
totalTime += duration;
|
||||
}
|
||||
}
|
||||
|
||||
// fake rootEvent statistics
|
||||
// the +1 nanosecond is to force it to be on top of the sorted list
|
||||
d->m_qmlRootEvent.duration = totalTime+1;
|
||||
d->m_qmlRootEvent.minTime = totalTime+1;
|
||||
d->m_qmlRootEvent.maxTime = totalTime+1;
|
||||
d->m_qmlRootEvent.medianTime = totalTime+1;
|
||||
if (totalTime > 0)
|
||||
d->m_qmlRootEvent.calls = 1;
|
||||
|
||||
// insert into list
|
||||
QmlEventData *listedRootEvent = d->m_eventDescriptions.value(d->m_rootEventName);
|
||||
if (!listedRootEvent) {
|
||||
listedRootEvent = new QmlEventData;
|
||||
d->m_eventDescriptions.insert(d->m_rootEventName, listedRootEvent);
|
||||
}
|
||||
*listedRootEvent = d->m_qmlRootEvent;
|
||||
|
||||
// compute percentages
|
||||
double totalTime = 0;
|
||||
foreach (QmlEventData *binding, d->m_eventDescriptions.values()) {
|
||||
totalTime += binding->cumulatedDuration;
|
||||
}
|
||||
|
||||
foreach (QmlEventData *binding, d->m_eventDescriptions.values()) {
|
||||
binding->percentOfTime = binding->cumulatedDuration * 100.0 / totalTime;
|
||||
binding->timePerCall = binding->calls > 0 ? double(binding->cumulatedDuration) / binding->calls : 0;
|
||||
binding->percentOfTime = binding->duration * 100.0 / totalTime;
|
||||
binding->timePerCall = binding->calls > 0 ? double(binding->duration) / binding->calls : 0;
|
||||
}
|
||||
|
||||
// compute median time
|
||||
@@ -841,14 +1088,17 @@ bool QmlProfilerEventList::save(const QString &filename)
|
||||
stream.writeStartDocument();
|
||||
|
||||
stream.writeStartElement("trace");
|
||||
stream.writeAttribute("version", Constants::PROFILER_FILE_VERSION);
|
||||
|
||||
stream.writeAttribute("traceStart", QString::number(traceStartTime()));
|
||||
stream.writeAttribute("traceEnd", QString::number(traceEndTime()));
|
||||
|
||||
stream.writeStartElement("eventData");
|
||||
stream.writeAttribute("totalTime", QString::number(d->m_qmlMeasuredTime));
|
||||
|
||||
foreach (const QmlEventData *eventData, d->m_eventDescriptions.values()) {
|
||||
stream.writeStartElement("event");
|
||||
stream.writeAttribute("index", QString::number(d->m_eventDescriptions.keys().indexOf(eventData->location)));
|
||||
stream.writeAttribute("index", QString::number(d->m_eventDescriptions.keys().indexOf(eventData->eventHashStr)));
|
||||
stream.writeTextElement("displayname", eventData->displayname);
|
||||
stream.writeTextElement("type", qmlEventType(eventData->eventType));
|
||||
if (!eventData->filename.isEmpty()) {
|
||||
@@ -865,12 +1115,13 @@ bool QmlProfilerEventList::save(const QString &filename)
|
||||
stream.writeStartElement("range");
|
||||
stream.writeAttribute("startTime", QString::number(rangedEvent.startTime));
|
||||
stream.writeAttribute("duration", QString::number(rangedEvent.length));
|
||||
stream.writeAttribute("eventIndex", QString::number(d->m_eventDescriptions.keys().indexOf(rangedEvent.description->location)));
|
||||
stream.writeAttribute("eventIndex", QString::number(d->m_eventDescriptions.keys().indexOf(rangedEvent.description->eventHashStr)));
|
||||
stream.writeEndElement();
|
||||
}
|
||||
stream.writeEndElement(); // eventList
|
||||
|
||||
stream.writeStartElement("v8profile"); // v8 profiler output
|
||||
stream.writeAttribute("totalTime", QString::number(d->m_v8MeasuredTime));
|
||||
foreach (QV8EventData *v8event, d->m_v8EventList) {
|
||||
stream.writeStartElement("event");
|
||||
stream.writeAttribute("index", QString::number(d->m_v8EventList.indexOf(v8event)));
|
||||
@@ -882,13 +1133,20 @@ bool QmlProfilerEventList::save(const QString &filename)
|
||||
}
|
||||
stream.writeTextElement("totalTime", QString::number(v8event->totalTime));
|
||||
stream.writeTextElement("selfTime", QString::number(v8event->selfTime));
|
||||
if (!v8event->childrenList.isEmpty()) {
|
||||
if (!v8event->childrenHash.isEmpty()) {
|
||||
stream.writeStartElement("childrenEvents");
|
||||
QStringList childrenIndexes;
|
||||
foreach (QV8EventData *v8child, v8event->childrenList) {
|
||||
childrenIndexes << QString::number(d->m_v8EventList.indexOf(v8child));
|
||||
QStringList childrenTimes;
|
||||
QStringList parentTimes;
|
||||
foreach (QV8EventSub *v8child, v8event->childrenHash.values()) {
|
||||
childrenIndexes << QString::number(v8child->reference->eventId);
|
||||
childrenTimes << QString::number(v8child->totalTime);
|
||||
parentTimes << QString::number(d->m_v8EventList[v8child->reference->eventId]->parentHash[v8event->displayName]->totalTime);
|
||||
}
|
||||
|
||||
stream.writeAttribute("list", childrenIndexes.join(QString(", ")));
|
||||
stream.writeAttribute("childrenTimes", childrenTimes.join(QString(", ")));
|
||||
stream.writeAttribute("parentTimes", parentTimes.join(QString(", ")));
|
||||
stream.writeEndElement();
|
||||
}
|
||||
stream.writeEndElement();
|
||||
@@ -936,12 +1194,20 @@ void QmlProfilerEventList::load()
|
||||
QmlEventData *currentEvent = 0;
|
||||
QHash <int, QV8EventData *> v8eventBuffer;
|
||||
QHash <int, QString> childrenIndexes;
|
||||
QHash <int, QString> childrenTimes;
|
||||
QHash <int, QString> parentTimes;
|
||||
QV8EventData *v8event = 0;
|
||||
bool startTimesAreSorted = true;
|
||||
bool validVersion = true;
|
||||
|
||||
// time computation
|
||||
d->m_v8MeasuredTime = 0;
|
||||
d->m_qmlMeasuredTime = 0;
|
||||
double cumulatedV8Time = 0;
|
||||
|
||||
QXmlStreamReader stream(&file);
|
||||
|
||||
while (!stream.atEnd() && !stream.hasError()) {
|
||||
while (validVersion && !stream.atEnd() && !stream.hasError()) {
|
||||
QXmlStreamReader::TokenType token = stream.readNext();
|
||||
QString elementName = stream.name().toString();
|
||||
switch (token) {
|
||||
@@ -949,6 +1215,10 @@ void QmlProfilerEventList::load()
|
||||
case QXmlStreamReader::StartElement : {
|
||||
if (elementName == "trace") {
|
||||
QXmlStreamAttributes attributes = stream.attributes();
|
||||
if (attributes.hasAttribute("version"))
|
||||
validVersion = attributes.value("version").toString() == Constants::PROFILER_FILE_VERSION;
|
||||
else
|
||||
validVersion = false;
|
||||
if (attributes.hasAttribute("traceStart"))
|
||||
setTraceStartTime(attributes.value("traceStart").toString().toLongLong());
|
||||
if (attributes.hasAttribute("traceEnd"))
|
||||
@@ -956,10 +1226,25 @@ void QmlProfilerEventList::load()
|
||||
}
|
||||
if (elementName == "eventData" && !readingV8Events) {
|
||||
readingQmlEvents = true;
|
||||
QXmlStreamAttributes attributes = stream.attributes();
|
||||
if (attributes.hasAttribute("totalTime"))
|
||||
d->m_qmlMeasuredTime = attributes.value("totalTime").toString().toDouble();
|
||||
break;
|
||||
}
|
||||
if (elementName == "v8profile" && !readingQmlEvents) {
|
||||
readingV8Events = true;
|
||||
QXmlStreamAttributes attributes = stream.attributes();
|
||||
if (attributes.hasAttribute("totalTime"))
|
||||
d->m_v8MeasuredTime = attributes.value("totalTime").toString().toDouble();
|
||||
break;
|
||||
}
|
||||
|
||||
if (elementName == "trace") {
|
||||
QXmlStreamAttributes attributes = stream.attributes();
|
||||
if (attributes.hasAttribute("traceStart"))
|
||||
setTraceStartTime(attributes.value("traceStart").toString().toLongLong());
|
||||
if (attributes.hasAttribute("traceEnd"))
|
||||
setTraceEndTime(attributes.value("traceEnd").toString().toLongLong());
|
||||
}
|
||||
|
||||
if (elementName == "range") {
|
||||
@@ -972,7 +1257,7 @@ void QmlProfilerEventList::load()
|
||||
if (attributes.hasAttribute("eventIndex")) {
|
||||
int ndx = attributes.value("eventIndex").toString().toInt();
|
||||
if (!descriptionBuffer.value(ndx))
|
||||
descriptionBuffer[ndx] = new QmlEventData();
|
||||
descriptionBuffer[ndx] = new QmlEventData;
|
||||
rangedEvent.description = descriptionBuffer.value(ndx);
|
||||
}
|
||||
rangedEvent.endTimeIndex = d->m_endTimeSortedList.length();
|
||||
@@ -996,7 +1281,7 @@ void QmlProfilerEventList::load()
|
||||
if (attributes.hasAttribute("index")) {
|
||||
int ndx = attributes.value("index").toString().toInt();
|
||||
if (!descriptionBuffer.value(ndx))
|
||||
descriptionBuffer[ndx] = new QmlEventData();
|
||||
descriptionBuffer[ndx] = new QmlEventData;
|
||||
currentEvent = descriptionBuffer[ndx];
|
||||
} else {
|
||||
currentEvent = 0;
|
||||
@@ -1055,9 +1340,16 @@ void QmlProfilerEventList::load()
|
||||
|
||||
if (elementName == "childrenEvents") {
|
||||
QXmlStreamAttributes attributes = stream.attributes();
|
||||
int eventIndex = v8eventBuffer.key(v8event);
|
||||
if (attributes.hasAttribute("list")) {
|
||||
// store for later parsing (we haven't read all the events yet)
|
||||
childrenIndexes[v8eventBuffer.key(v8event)] = attributes.value("list").toString();
|
||||
childrenIndexes[eventIndex] = attributes.value("list").toString();
|
||||
}
|
||||
if (attributes.hasAttribute("childrenTimes")) {
|
||||
childrenTimes[eventIndex] = attributes.value("childrenTimes").toString();
|
||||
}
|
||||
if (attributes.hasAttribute("parentTimes")) {
|
||||
parentTimes[eventIndex] = attributes.value("parentTimes").toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1088,6 +1380,7 @@ void QmlProfilerEventList::load()
|
||||
|
||||
if (elementName == "totalTime") {
|
||||
v8event->totalTime = readData.toDouble();
|
||||
cumulatedV8Time += v8event->totalTime;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1126,10 +1419,22 @@ void QmlProfilerEventList::load()
|
||||
|
||||
stream.clear();
|
||||
|
||||
if (!validVersion) {
|
||||
clear();
|
||||
emit countChanged();
|
||||
emit dataReady();
|
||||
emit error(tr("Invalid version of QmlProfiler trace file."));
|
||||
return;
|
||||
}
|
||||
|
||||
// backwards compatibility
|
||||
if (d->m_v8MeasuredTime == 0)
|
||||
d->m_v8MeasuredTime = cumulatedV8Time;
|
||||
|
||||
// move the buffered data to the details cache
|
||||
foreach (QmlEventData *desc, descriptionBuffer.values()) {
|
||||
QString location = QString("%1:%2:%3").arg(QString::number(desc->eventType), desc->displayname, desc->details);
|
||||
desc->location = location;
|
||||
desc->eventHashStr = location;
|
||||
d->m_eventDescriptions[location] = desc;
|
||||
}
|
||||
|
||||
@@ -1145,12 +1450,20 @@ void QmlProfilerEventList::load()
|
||||
|
||||
// find v8events' children and parents
|
||||
foreach (int parentIndex, childrenIndexes.keys()) {
|
||||
QStringList childrenStrings = childrenIndexes.value(parentIndex).split((","));
|
||||
foreach (const QString &childString, childrenStrings) {
|
||||
int childIndex = childString.toInt();
|
||||
QStringList childrenStrings = childrenIndexes.value(parentIndex).split(",");
|
||||
QStringList childrenTimesStrings = childrenTimes.value(parentIndex).split(", ");
|
||||
QStringList parentTimesStrings = parentTimes.value(parentIndex).split(", ");
|
||||
for (int ndx = 0; ndx < childrenStrings.count(); ndx++) {
|
||||
int childIndex = childrenStrings[ndx].toInt();
|
||||
if (v8eventBuffer.value(childIndex)) {
|
||||
v8eventBuffer[parentIndex]->childrenList << v8eventBuffer[childIndex];
|
||||
v8eventBuffer[childIndex]->parentList << v8eventBuffer[parentIndex];
|
||||
QV8EventSub *newChild = new QV8EventSub(v8eventBuffer[childIndex]);
|
||||
QV8EventSub *newParent = new QV8EventSub(v8eventBuffer[parentIndex]);
|
||||
if (childrenTimesStrings.count() > ndx)
|
||||
newChild->totalTime = childrenTimesStrings[ndx].toDouble();
|
||||
if (parentTimesStrings.count() > ndx)
|
||||
newParent->totalTime = parentTimesStrings[ndx].toDouble();
|
||||
v8eventBuffer[parentIndex]->childrenHash.insert(newChild->reference->displayName, newChild);
|
||||
v8eventBuffer[childIndex]->parentHash.insert(newParent->reference->displayName, newParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,18 +41,23 @@
|
||||
|
||||
namespace QmlJsDebugClient {
|
||||
|
||||
struct QmlEventSub;
|
||||
struct QV8EventSub;
|
||||
|
||||
struct QMLJSDEBUGCLIENT_EXPORT QmlEventData
|
||||
{
|
||||
QmlEventData():line(-1),cumulatedDuration(0),calls(0),eventId(-1){}
|
||||
QmlEventData();
|
||||
~QmlEventData();
|
||||
|
||||
QString displayname;
|
||||
QString filename;
|
||||
QString location;
|
||||
QString eventHashStr;
|
||||
QString details;
|
||||
int line;
|
||||
QmlJsDebugClient::QmlEventType eventType;
|
||||
QList< QmlEventData *> parentList;
|
||||
QList< QmlEventData *> childrenList;
|
||||
qint64 cumulatedDuration;
|
||||
QHash <QString, QmlEventSub *> parentHash;
|
||||
QHash <QString, QmlEventSub *> childrenHash;
|
||||
qint64 duration;
|
||||
qint64 calls;
|
||||
qint64 minTime;
|
||||
qint64 maxTime;
|
||||
@@ -60,10 +65,23 @@ struct QMLJSDEBUGCLIENT_EXPORT QmlEventData
|
||||
double percentOfTime;
|
||||
qint64 medianTime;
|
||||
int eventId;
|
||||
|
||||
QmlEventData &operator=(const QmlEventData &ref);
|
||||
};
|
||||
|
||||
struct QMLJSDEBUGCLIENT_EXPORT QmlEventSub {
|
||||
QmlEventSub(QmlEventData *from) : reference(from), duration(0), calls(0) {}
|
||||
QmlEventSub(QmlEventSub *from) : reference(from->reference), duration(from->duration), calls(from->calls) {}
|
||||
QmlEventData *reference;
|
||||
qint64 duration;
|
||||
qint64 calls;
|
||||
};
|
||||
|
||||
struct QMLJSDEBUGCLIENT_EXPORT QV8EventData
|
||||
{
|
||||
QV8EventData();
|
||||
~QV8EventData();
|
||||
|
||||
QString displayName;
|
||||
QString filename;
|
||||
QString functionName;
|
||||
@@ -72,9 +90,19 @@ struct QMLJSDEBUGCLIENT_EXPORT QV8EventData
|
||||
double totalPercent;
|
||||
double selfTime;
|
||||
double selfPercent;
|
||||
QList< QV8EventData *> parentList;
|
||||
QList< QV8EventData *> childrenList;
|
||||
QHash <QString, QV8EventSub *> parentHash;
|
||||
QHash <QString, QV8EventSub *> childrenHash;
|
||||
int eventId;
|
||||
|
||||
QV8EventData &operator=(const QV8EventData &ref);
|
||||
};
|
||||
|
||||
struct QMLJSDEBUGCLIENT_EXPORT QV8EventSub {
|
||||
QV8EventSub(QV8EventData *from) : reference(from), totalTime(0) {}
|
||||
QV8EventSub(QV8EventSub *from) : reference(from->reference), totalTime(from->totalTime) {}
|
||||
|
||||
QV8EventData *reference;
|
||||
qint64 totalTime;
|
||||
};
|
||||
|
||||
typedef QHash<QString, QmlEventData *> QmlEventHash;
|
||||
|
||||
@@ -83,6 +83,9 @@ function drawData(canvas, ctxt, region)
|
||||
|
||||
function drawTimeBar(canvas, ctxt, region)
|
||||
{
|
||||
if (!qmlEventList)
|
||||
return;
|
||||
|
||||
var width = canvas.width;
|
||||
var height = 10;
|
||||
var startTime = qmlEventList.traceStartTime();
|
||||
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
data(LineRole).toInt() < other.data(LineRole).toInt() :
|
||||
data(FilenameRole).toString() < other.data(FilenameRole).toString();
|
||||
} else {
|
||||
return data().toString() < other.data().toString();
|
||||
return data().toString().toLower() < other.data().toString().toLower();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,8 +196,6 @@ public:
|
||||
void buildModelFromList(const QmlEventDescriptions &list, QStandardItem *parentItem, const QmlEventDescriptions &visitedFunctionsList = QmlEventDescriptions() );
|
||||
void buildV8ModelFromList( const QV8EventDescriptions &list );
|
||||
int getFieldCount();
|
||||
QString displayTime(double time) const;
|
||||
QString nameForType(int typeNumber) const;
|
||||
|
||||
QString textForItem(QStandardItem *item, bool recursive) const;
|
||||
|
||||
@@ -282,8 +280,6 @@ void QmlProfilerEventsMainView::setViewType(ViewTypes type)
|
||||
setFieldViewable(MinTime, true);
|
||||
setFieldViewable(MedianTime, true);
|
||||
setFieldViewable(Details, true);
|
||||
setFieldViewable(Parents, false);
|
||||
setFieldViewable(Children, false);
|
||||
break;
|
||||
}
|
||||
case V8ProfileView: {
|
||||
@@ -300,8 +296,6 @@ void QmlProfilerEventsMainView::setViewType(ViewTypes type)
|
||||
setFieldViewable(MinTime, false);
|
||||
setFieldViewable(MedianTime, false);
|
||||
setFieldViewable(Details, true);
|
||||
setFieldViewable(Parents, false);
|
||||
setFieldViewable(Children, false);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
@@ -358,7 +352,7 @@ int QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::getFieldCount()
|
||||
{
|
||||
int count = 0;
|
||||
for (int i=0; i < m_fieldShown.count(); ++i)
|
||||
if (m_fieldShown[i] && i != Parents && i != Children)
|
||||
if (m_fieldShown[i])
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
@@ -372,12 +366,8 @@ void QmlProfilerEventsMainView::buildModel()
|
||||
else
|
||||
d->buildModelFromList( d->m_eventStatistics->getEventDescriptions(), d->m_model->invisibleRootItem() );
|
||||
|
||||
bool hasBranches = d->m_fieldShown[Parents] || d->m_fieldShown[Children];
|
||||
setRootIsDecorated(hasBranches);
|
||||
|
||||
setRootIsDecorated(false);
|
||||
setSortingEnabled(true);
|
||||
|
||||
if (!hasBranches)
|
||||
sortByColumn(d->m_firstNumericColumn,Qt::DescendingOrder);
|
||||
|
||||
expandAll();
|
||||
@@ -415,8 +405,8 @@ void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFrom
|
||||
}
|
||||
|
||||
if (m_fieldShown[TotalDuration]) {
|
||||
newRow << new EventsViewItem(displayTime(binding->cumulatedDuration));
|
||||
newRow.last()->setData(QVariant(binding->cumulatedDuration));
|
||||
newRow << new EventsViewItem(displayTime(binding->duration));
|
||||
newRow.last()->setData(QVariant(binding->duration));
|
||||
}
|
||||
|
||||
if (m_fieldShown[CallCount]) {
|
||||
@@ -457,27 +447,13 @@ void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFrom
|
||||
item->setEditable(false);
|
||||
|
||||
// metadata
|
||||
newRow.at(0)->setData(QVariant(binding->location),LocationRole);
|
||||
newRow.at(0)->setData(QVariant(binding->eventHashStr),EventHashStrRole);
|
||||
newRow.at(0)->setData(QVariant(binding->filename),FilenameRole);
|
||||
newRow.at(0)->setData(QVariant(binding->line),LineRole);
|
||||
newRow.at(0)->setData(QVariant(binding->eventId),EventIdRole);
|
||||
|
||||
// append
|
||||
parentItem->appendRow(newRow);
|
||||
|
||||
if (m_fieldShown[Parents] && !binding->parentList.isEmpty()) {
|
||||
QmlEventDescriptions newParentList(visitedFunctionsList);
|
||||
newParentList.append(binding);
|
||||
|
||||
buildModelFromList(binding->parentList, newRow.at(0), newParentList);
|
||||
}
|
||||
|
||||
if (m_fieldShown[Children] && !binding->childrenList.isEmpty()) {
|
||||
QmlEventDescriptions newChildrenList(visitedFunctionsList);
|
||||
newChildrenList.append(binding);
|
||||
|
||||
buildModelFromList(binding->childrenList, newRow.at(0), newChildrenList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -523,6 +499,7 @@ void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildV8ModelFr
|
||||
item->setEditable(false);
|
||||
|
||||
// metadata
|
||||
newRow.at(0)->setData(QString("%1:%2").arg(v8event->filename, QString::number(v8event->line)), EventHashStrRole);
|
||||
newRow.at(0)->setData(QVariant(v8event->filename), FilenameRole);
|
||||
newRow.at(0)->setData(QVariant(v8event->line), LineRole);
|
||||
newRow.at(0)->setData(QVariant(v8event->eventId), EventIdRole);
|
||||
@@ -533,14 +510,14 @@ void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildV8ModelFr
|
||||
}
|
||||
}
|
||||
|
||||
QString QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::displayTime(double time) const
|
||||
QString QmlProfilerEventsMainView::displayTime(double time)
|
||||
{
|
||||
if (time < 1e6)
|
||||
return QString::number(time/1e3,'f',3) + QString::fromWCharArray(L" \u03BCs");
|
||||
return QString::number(time/1e3,'f',3) + trUtf8(" \u03BCs");
|
||||
if (time < 1e9)
|
||||
return QString::number(time/1e6,'f',3) + QLatin1String(" ms");
|
||||
return QString::number(time/1e6,'f',3) + tr(" ms");
|
||||
|
||||
return QString::number(time/1e9,'f',3) + QLatin1String(" s");
|
||||
return QString::number(time/1e9,'f',3) + tr(" s");
|
||||
}
|
||||
|
||||
QString QmlProfilerEventsMainView::nameForType(int typeNumber)
|
||||
@@ -719,24 +696,36 @@ void QmlProfilerEventsParentsAndChildrenView::displayEvent(int eventId)
|
||||
if (isV8) {
|
||||
QmlJsDebugClient::QV8EventData *v8event = m_eventList->v8EventDescription(eventId);
|
||||
if (v8event) {
|
||||
if (isChildren)
|
||||
rebuildTree((QObject *)&v8event->childrenList);
|
||||
else
|
||||
rebuildTree((QObject *)&v8event->parentList);
|
||||
if (isChildren) {
|
||||
QList <QmlJsDebugClient::QV8EventSub *> childrenList = v8event->childrenHash.values();
|
||||
rebuildTree((QObject *)&childrenList);
|
||||
}
|
||||
else {
|
||||
QList <QmlJsDebugClient::QV8EventSub *> parentList = v8event->parentHash.values();
|
||||
rebuildTree((QObject *)&parentList);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QmlJsDebugClient::QmlEventData *qmlEvent = m_eventList->eventDescription(eventId);
|
||||
if (qmlEvent) {
|
||||
if (isChildren)
|
||||
rebuildTree((QObject *)&qmlEvent->childrenList);
|
||||
else
|
||||
rebuildTree((QObject *)&qmlEvent->parentList);
|
||||
if (isChildren) {
|
||||
QList <QmlJsDebugClient::QmlEventSub *> childrenList = qmlEvent->childrenHash.values();
|
||||
rebuildTree((QObject *)&childrenList);
|
||||
}
|
||||
else {
|
||||
QList <QmlJsDebugClient::QmlEventSub *> parentList = qmlEvent->parentHash.values();
|
||||
rebuildTree((QObject *)&parentList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateHeader();
|
||||
resizeColumnToContents(0);
|
||||
setSortingEnabled(true);
|
||||
if (isV8)
|
||||
sortByColumn(1);
|
||||
else
|
||||
sortByColumn(2);
|
||||
}
|
||||
|
||||
void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList)
|
||||
@@ -747,8 +736,8 @@ void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList)
|
||||
QStandardItem *topLevelItem = treeModel()->invisibleRootItem();
|
||||
bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView;
|
||||
|
||||
QList <QmlEventData *> *qmlList = static_cast< QList <QmlEventData *> *>(eventList);
|
||||
QList <QV8EventData *> *v8List = static_cast< QList <QV8EventData *> *>(eventList);
|
||||
QList <QmlEventSub *> *qmlList = static_cast< QList <QmlEventSub *> *>(eventList);
|
||||
QList <QV8EventSub*> *v8List = static_cast< QList <QV8EventSub *> *>(eventList);
|
||||
|
||||
int listLength;
|
||||
if (!isV8)
|
||||
@@ -759,17 +748,23 @@ void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList)
|
||||
for (int index=0; index < listLength; index++) {
|
||||
QList<QStandardItem *> newRow;
|
||||
if (!isV8) {
|
||||
QmlEventData *event = qmlList->at(index);
|
||||
QmlEventSub *event = qmlList->at(index);
|
||||
|
||||
newRow << new QStandardItem(event->displayname);
|
||||
newRow << new QStandardItem(QmlProfilerEventsMainView::nameForType(event->eventType));
|
||||
newRow << new QStandardItem(event->details);
|
||||
newRow.at(0)->setData(QVariant(event->eventId), EventIdRole);
|
||||
newRow << new EventsViewItem(event->reference->displayname);
|
||||
newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event->reference->eventType));
|
||||
newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event->duration));
|
||||
newRow << new EventsViewItem(QString::number(event->calls));
|
||||
newRow << new EventsViewItem(event->reference->details);
|
||||
newRow.at(0)->setData(QVariant(event->reference->eventId), EventIdRole);
|
||||
newRow.at(2)->setData(QVariant(event->duration));
|
||||
newRow.at(3)->setData(QVariant(event->calls));
|
||||
} else {
|
||||
QV8EventData *event = v8List->at(index);
|
||||
newRow << new QStandardItem(event->displayName);
|
||||
newRow << new QStandardItem(event->functionName);
|
||||
newRow.at(0)->setData(QVariant(event->eventId), EventIdRole);
|
||||
QV8EventSub *event = v8List->at(index);
|
||||
newRow << new EventsViewItem(event->reference->displayName);
|
||||
newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event->totalTime));
|
||||
newRow << new EventsViewItem(event->reference->functionName);
|
||||
newRow.at(0)->setData(QVariant(event->reference->eventId), EventIdRole);
|
||||
newRow.at(1)->setData(QVariant(event->totalTime));
|
||||
}
|
||||
foreach (QStandardItem *item, newRow)
|
||||
item->setEditable(false);
|
||||
@@ -797,9 +792,9 @@ void QmlProfilerEventsParentsAndChildrenView::updateHeader()
|
||||
|
||||
if (treeModel()) {
|
||||
if (isV8)
|
||||
treeModel()->setColumnCount(2);
|
||||
else
|
||||
treeModel()->setColumnCount(3);
|
||||
else
|
||||
treeModel()->setColumnCount(5);
|
||||
|
||||
int columnIndex = 0;
|
||||
if (isChildren)
|
||||
@@ -810,6 +805,11 @@ void QmlProfilerEventsParentsAndChildrenView::updateHeader()
|
||||
if (!isV8)
|
||||
treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Type")));
|
||||
|
||||
treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Total Time")));
|
||||
|
||||
if (!isV8)
|
||||
treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Calls")));
|
||||
|
||||
if (isChildren)
|
||||
treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee Description")));
|
||||
else
|
||||
|
||||
@@ -48,7 +48,7 @@ typedef QHash<QString, QmlJsDebugClient::QmlEventData *> QmlEventHash;
|
||||
typedef QList<QmlJsDebugClient::QmlEventData *> QmlEventList;
|
||||
|
||||
enum ItemRole {
|
||||
LocationRole = Qt::UserRole+1,
|
||||
EventHashStrRole = Qt::UserRole+1,
|
||||
FilenameRole = Qt::UserRole+2,
|
||||
LineRole = Qt::UserRole+3,
|
||||
EventIdRole = Qt::UserRole+4
|
||||
@@ -108,8 +108,6 @@ public:
|
||||
MinTime,
|
||||
MedianTime,
|
||||
Details,
|
||||
Parents,
|
||||
Children,
|
||||
|
||||
MaxFields
|
||||
};
|
||||
@@ -135,6 +133,7 @@ public:
|
||||
void copyTableToClipboard() const;
|
||||
void copyRowToClipboard() const;
|
||||
|
||||
static QString displayTime(double time);
|
||||
static QString nameForType(int typeNumber);
|
||||
|
||||
void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd);
|
||||
|
||||
Reference in New Issue
Block a user