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:
Christiaan Janssen
2011-12-05 16:32:05 +01:00
parent a5661ddabc
commit 001425e6ba
5 changed files with 503 additions and 160 deletions

View File

@@ -54,10 +54,115 @@ const char *const TYPE_COMPILING_STR = "Compiling";
const char *const TYPE_CREATING_STR = "Creating"; const char *const TYPE_CREATING_STR = "Creating";
const char *const TYPE_BINDING_STR = "Binding"; const char *const TYPE_BINDING_STR = "Binding";
const char *const TYPE_HANDLINGSIGNAL_STR = "HandlingSignal"; const char *const TYPE_HANDLINGSIGNAL_STR = "HandlingSignal";
const char *const PROFILER_FILE_VERSION = "1.01";
} }
#define MIN_LEVEL 1 #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 // endtimedata
struct QmlEventEndTimeData { struct QmlEventEndTimeData {
qint64 endTime; qint64 endTime;
@@ -151,6 +256,10 @@ public:
QmlProfilerEventList *q; QmlProfilerEventList *q;
// convenience functions
void clearQmlRootEvent();
void clearV8RootEvent();
// Stored data // Stored data
QmlEventHash m_eventDescriptions; QmlEventHash m_eventDescriptions;
QList<QmlEventEndTimeData> m_endTimeSortedList; QList<QmlEventEndTimeData> m_endTimeSortedList;
@@ -160,6 +269,11 @@ public:
QV8EventDescriptions m_v8EventList; QV8EventDescriptions m_v8EventList;
QHash<int, QV8EventData *> m_v8parents; QHash<int, QV8EventData *> m_v8parents;
QmlEventData m_qmlRootEvent;
QV8EventData m_v8RootEvent;
QString m_rootEventName;
QString m_rootEventDesc;
QHash<int, QmlEventTypeCount *> m_typeCounts; QHash<int, QmlEventTypeCount *> m_typeCounts;
qint64 m_traceEndTime; qint64 m_traceEndTime;
@@ -184,6 +298,11 @@ QmlProfilerEventList::QmlProfilerEventList(QObject *parent) :
d->m_traceStartTime = -1; d->m_traceStartTime = -1;
d->m_qmlMeasuredTime = 0; d->m_qmlMeasuredTime = 0;
d->m_v8MeasuredTime = 0; d->m_v8MeasuredTime = 0;
d->m_rootEventName = tr("<program>");
d->m_rootEventDesc = tr("Main Program");
d->clearQmlRootEvent();
d->clearV8RootEvent();
} }
QmlProfilerEventList::~QmlProfilerEventList() QmlProfilerEventList::~QmlProfilerEventList()
@@ -193,17 +312,20 @@ QmlProfilerEventList::~QmlProfilerEventList()
void QmlProfilerEventList::clear() void QmlProfilerEventList::clear()
{ {
foreach (QmlEventData *binding, d->m_eventDescriptions.values()) qDeleteAll(d->m_eventDescriptions.values());
delete binding;
d->m_eventDescriptions.clear(); d->m_eventDescriptions.clear();
qDeleteAll(d->m_v8EventList);
d->m_v8EventList.clear();
d->m_endTimeSortedList.clear(); d->m_endTimeSortedList.clear();
d->m_startTimeSortedList.clear(); d->m_startTimeSortedList.clear();
qDeleteAll(d->m_v8EventList);
d->m_v8EventList.clear();
d->m_v8parents.clear(); d->m_v8parents.clear();
d->clearQmlRootEvent();
d->clearV8RootEvent();
foreach (QmlEventTypeCount *typeCount, d->m_typeCounts.values()) foreach (QmlEventTypeCount *typeCount, d->m_typeCounts.values())
delete typeCount; delete typeCount;
d->m_typeCounts.clear(); 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 QStringList &data, const QString &fileName, int line)
{ {
const QChar colon = QLatin1Char(':'); const QChar colon = QLatin1Char(':');
QString displayName, location, details; QString displayName, eventHashStr, details;
emit processingData(); 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 // generate details string
if (data.isEmpty()) if (data.isEmpty())
details = tr("Source code not available"); 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); 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->displayname = displayName;
newEvent->filename = fileName; newEvent->filename = fileName;
newEvent->location = location; newEvent->eventHashStr = eventHashStr;
newEvent->line = line; newEvent->line = line;
newEvent->eventType = (QmlJsDebugClient::QmlEventType)type; newEvent->eventType = (QmlJsDebugClient::QmlEventType)type;
newEvent->details = details; newEvent->details = details;
d->m_eventDescriptions.insert(location, newEvent); d->m_eventDescriptions.insert(eventHashStr, newEvent);
} }
QmlEventEndTimeData endTimeData; 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) 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); 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 // time is given in milliseconds, but internally we store it in microseconds
totalTime *= 1e6; totalTime *= 1e6;
@@ -319,45 +441,65 @@ void QmlProfilerEventList::addV8Event(int depth, const QString &function, const
// cumulate information // cumulate information
foreach (QV8EventData *v8event, d->m_v8EventList) { foreach (QV8EventData *v8event, d->m_v8EventList) {
if (v8event->displayName == displayName && v8event->functionName == function) if (v8event->displayName == displayName && v8event->functionName == function) {
newData = v8event; eventData = v8event;
break;
}
} }
if (!newData) { if (!eventData) {
newData = new QV8EventData(); eventData = new QV8EventData;
newData->displayName = displayName; eventData->displayName = displayName;
newData->filename = filename; eventData->filename = filename;
newData->functionName = function; eventData->functionName = function;
newData->line = lineNumber; eventData->line = lineNumber;
newData->totalTime = totalTime; eventData->totalTime = totalTime;
newData->selfTime = selfTime; eventData->selfTime = selfTime;
d->m_v8EventList << newData; d->m_v8EventList << eventData;
} else { } else {
newData->totalTime += totalTime; eventData->totalTime += totalTime;
newData->selfTime += selfTime; eventData->selfTime += selfTime;
} }
d->m_v8parents[depth] = newData; d->m_v8parents[depth] = eventData;
if (depth > 0) { QV8EventData *parentEvent = 0;
QV8EventData* parentEvent = d->m_v8parents.value(depth-1); if (depth == 0) {
if (parentEvent) { parentEvent = &d->m_v8RootEvent;
if (!newData->parentList.contains(parentEvent))
newData->parentList << parentEvent;
if (!parentEvent->childrenList.contains(newData))
parentEvent->childrenList << newData;
}
} else {
d->m_v8MeasuredTime += totalTime; 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() void QmlProfilerEventList::QmlProfilerEventListPrivate::collectV8Statistics()
{ {
if (!m_v8EventList.isEmpty()) { if (!m_v8EventList.isEmpty()) {
double totalTimes = 0; double totalTimes = m_v8MeasuredTime;
double selfTimes = 0; double selfTimes = 0;
foreach (QV8EventData *v8event, m_v8EventList) { foreach (QV8EventData *v8event, m_v8EventList) {
totalTimes += v8event->totalTime;
selfTimes += v8event->selfTime; selfTimes += v8event->selfTime;
} }
@@ -367,15 +509,38 @@ void QmlProfilerEventList::QmlProfilerEventListPrivate::collectV8Statistics()
if (selfTimes == 0) if (selfTimes == 0)
selfTimes = 1; 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) { foreach (QV8EventData *v8event, m_v8EventList) {
v8event->totalPercent = v8event->totalTime * 100.0 / totalTimes; v8event->totalPercent = v8event->totalTime * 100.0 / totalTimes;
v8event->selfPercent = v8event->selfTime * 100.0 / selfTimes; v8event->selfPercent = v8event->selfTime * 100.0 / selfTimes;
} }
int index = 0; int index = 0;
foreach (QV8EventData *v8event, m_v8EventList) foreach (QV8EventData *v8event, m_v8EventList) {
v8event->eventId = index++; v8event->eventId = index++;
} }
m_v8RootEvent.eventId = m_v8EventList[rootEventIndex]->eventId;
}
} }
void QmlProfilerEventList::setTraceEndTime( qint64 time ) void QmlProfilerEventList::setTraceEndTime( qint64 time )
@@ -395,11 +560,52 @@ void QmlProfilerEventList::complete()
postProcess(); 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) void QmlProfilerEventList::compileStatistics(qint64 startTime, qint64 endTime)
{ {
int index; int index;
int fromIndex = findFirstIndex(startTime); int fromIndex = findFirstIndex(startTime);
int toIndex = findLastIndex(endTime); int toIndex = findLastIndex(endTime);
double totalTime = 0;
// clear existing statistics // clear existing statistics
foreach (QmlEventData *eventDescription, d->m_eventDescriptions.values()) { 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->minTime = d->m_endTimeSortedList.last().endTime;
eventDescription->maxTime = 0; eventDescription->maxTime = 0;
eventDescription->medianTime = 0; eventDescription->medianTime = 0;
eventDescription->cumulatedDuration = 0; eventDescription->duration = 0;
eventDescription->parentList.clear(); qDeleteAll(eventDescription->parentHash);
eventDescription->childrenList.clear(); qDeleteAll(eventDescription->childrenHash);
eventDescription->parentHash.clear();
eventDescription->childrenHash.clear();
} }
// create root event for statistics
d->clearQmlRootEvent();
// compute parent-child relationship and call count // compute parent-child relationship and call count
QHash<int, QmlEventData*> lastParent; QHash<int, QmlEventData*> lastParent;
for (index = fromIndex; index <= toIndex; index++) { for (index = fromIndex; index <= toIndex; index++) {
@@ -425,35 +636,71 @@ void QmlProfilerEventList::compileStatistics(qint64 startTime, qint64 endTime)
eventDescription->calls++; eventDescription->calls++;
qint64 duration = d->m_startTimeSortedList[index].length; qint64 duration = d->m_startTimeSortedList[index].length;
eventDescription->cumulatedDuration += duration; eventDescription->duration += duration;
if (eventDescription->maxTime < duration) if (eventDescription->maxTime < duration)
eventDescription->maxTime = duration; eventDescription->maxTime = duration;
if (eventDescription->minTime > duration) if (eventDescription->minTime > duration)
eventDescription->minTime = duration; eventDescription->minTime = duration;
int level = d->m_startTimeSortedList[index].level; int level = d->m_startTimeSortedList[index].level;
if (level > MIN_LEVEL) {
if (lastParent.contains(level-1)) { QmlEventData *parentEvent = &d->m_qmlRootEvent;
QmlEventData *parentEvent = lastParent[level-1]; if (level > MIN_LEVEL && lastParent.contains(level-1)) {
if (!eventDescription->parentList.contains(parentEvent)) parentEvent = lastParent[level-1];
eventDescription->parentList.append(parentEvent);
if (!parentEvent->childrenList.contains(eventDescription))
parentEvent->childrenList.append(eventDescription);
} }
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; 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 // compute percentages
double totalTime = 0;
foreach (QmlEventData *binding, d->m_eventDescriptions.values()) { foreach (QmlEventData *binding, d->m_eventDescriptions.values()) {
totalTime += binding->cumulatedDuration; binding->percentOfTime = binding->duration * 100.0 / totalTime;
} binding->timePerCall = binding->calls > 0 ? double(binding->duration) / binding->calls : 0;
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;
} }
// compute median time // compute median time
@@ -841,14 +1088,17 @@ bool QmlProfilerEventList::save(const QString &filename)
stream.writeStartDocument(); stream.writeStartDocument();
stream.writeStartElement("trace"); stream.writeStartElement("trace");
stream.writeAttribute("version", Constants::PROFILER_FILE_VERSION);
stream.writeAttribute("traceStart", QString::number(traceStartTime())); stream.writeAttribute("traceStart", QString::number(traceStartTime()));
stream.writeAttribute("traceEnd", QString::number(traceEndTime())); stream.writeAttribute("traceEnd", QString::number(traceEndTime()));
stream.writeStartElement("eventData"); stream.writeStartElement("eventData");
stream.writeAttribute("totalTime", QString::number(d->m_qmlMeasuredTime));
foreach (const QmlEventData *eventData, d->m_eventDescriptions.values()) { foreach (const QmlEventData *eventData, d->m_eventDescriptions.values()) {
stream.writeStartElement("event"); 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("displayname", eventData->displayname);
stream.writeTextElement("type", qmlEventType(eventData->eventType)); stream.writeTextElement("type", qmlEventType(eventData->eventType));
if (!eventData->filename.isEmpty()) { if (!eventData->filename.isEmpty()) {
@@ -865,12 +1115,13 @@ bool QmlProfilerEventList::save(const QString &filename)
stream.writeStartElement("range"); stream.writeStartElement("range");
stream.writeAttribute("startTime", QString::number(rangedEvent.startTime)); stream.writeAttribute("startTime", QString::number(rangedEvent.startTime));
stream.writeAttribute("duration", QString::number(rangedEvent.length)); 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();
} }
stream.writeEndElement(); // eventList stream.writeEndElement(); // eventList
stream.writeStartElement("v8profile"); // v8 profiler output stream.writeStartElement("v8profile"); // v8 profiler output
stream.writeAttribute("totalTime", QString::number(d->m_v8MeasuredTime));
foreach (QV8EventData *v8event, d->m_v8EventList) { foreach (QV8EventData *v8event, d->m_v8EventList) {
stream.writeStartElement("event"); stream.writeStartElement("event");
stream.writeAttribute("index", QString::number(d->m_v8EventList.indexOf(v8event))); 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("totalTime", QString::number(v8event->totalTime));
stream.writeTextElement("selfTime", QString::number(v8event->selfTime)); stream.writeTextElement("selfTime", QString::number(v8event->selfTime));
if (!v8event->childrenList.isEmpty()) { if (!v8event->childrenHash.isEmpty()) {
stream.writeStartElement("childrenEvents"); stream.writeStartElement("childrenEvents");
QStringList childrenIndexes; QStringList childrenIndexes;
foreach (QV8EventData *v8child, v8event->childrenList) { QStringList childrenTimes;
childrenIndexes << QString::number(d->m_v8EventList.indexOf(v8child)); 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("list", childrenIndexes.join(QString(", ")));
stream.writeAttribute("childrenTimes", childrenTimes.join(QString(", ")));
stream.writeAttribute("parentTimes", parentTimes.join(QString(", ")));
stream.writeEndElement(); stream.writeEndElement();
} }
stream.writeEndElement(); stream.writeEndElement();
@@ -936,12 +1194,20 @@ void QmlProfilerEventList::load()
QmlEventData *currentEvent = 0; QmlEventData *currentEvent = 0;
QHash <int, QV8EventData *> v8eventBuffer; QHash <int, QV8EventData *> v8eventBuffer;
QHash <int, QString> childrenIndexes; QHash <int, QString> childrenIndexes;
QHash <int, QString> childrenTimes;
QHash <int, QString> parentTimes;
QV8EventData *v8event = 0; QV8EventData *v8event = 0;
bool startTimesAreSorted = true; bool startTimesAreSorted = true;
bool validVersion = true;
// time computation
d->m_v8MeasuredTime = 0;
d->m_qmlMeasuredTime = 0;
double cumulatedV8Time = 0;
QXmlStreamReader stream(&file); QXmlStreamReader stream(&file);
while (!stream.atEnd() && !stream.hasError()) { while (validVersion && !stream.atEnd() && !stream.hasError()) {
QXmlStreamReader::TokenType token = stream.readNext(); QXmlStreamReader::TokenType token = stream.readNext();
QString elementName = stream.name().toString(); QString elementName = stream.name().toString();
switch (token) { switch (token) {
@@ -949,6 +1215,10 @@ void QmlProfilerEventList::load()
case QXmlStreamReader::StartElement : { case QXmlStreamReader::StartElement : {
if (elementName == "trace") { if (elementName == "trace") {
QXmlStreamAttributes attributes = stream.attributes(); QXmlStreamAttributes attributes = stream.attributes();
if (attributes.hasAttribute("version"))
validVersion = attributes.value("version").toString() == Constants::PROFILER_FILE_VERSION;
else
validVersion = false;
if (attributes.hasAttribute("traceStart")) if (attributes.hasAttribute("traceStart"))
setTraceStartTime(attributes.value("traceStart").toString().toLongLong()); setTraceStartTime(attributes.value("traceStart").toString().toLongLong());
if (attributes.hasAttribute("traceEnd")) if (attributes.hasAttribute("traceEnd"))
@@ -956,10 +1226,25 @@ void QmlProfilerEventList::load()
} }
if (elementName == "eventData" && !readingV8Events) { if (elementName == "eventData" && !readingV8Events) {
readingQmlEvents = true; readingQmlEvents = true;
QXmlStreamAttributes attributes = stream.attributes();
if (attributes.hasAttribute("totalTime"))
d->m_qmlMeasuredTime = attributes.value("totalTime").toString().toDouble();
break; break;
} }
if (elementName == "v8profile" && !readingQmlEvents) { if (elementName == "v8profile" && !readingQmlEvents) {
readingV8Events = true; 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") { if (elementName == "range") {
@@ -972,7 +1257,7 @@ void QmlProfilerEventList::load()
if (attributes.hasAttribute("eventIndex")) { if (attributes.hasAttribute("eventIndex")) {
int ndx = attributes.value("eventIndex").toString().toInt(); int ndx = attributes.value("eventIndex").toString().toInt();
if (!descriptionBuffer.value(ndx)) if (!descriptionBuffer.value(ndx))
descriptionBuffer[ndx] = new QmlEventData(); descriptionBuffer[ndx] = new QmlEventData;
rangedEvent.description = descriptionBuffer.value(ndx); rangedEvent.description = descriptionBuffer.value(ndx);
} }
rangedEvent.endTimeIndex = d->m_endTimeSortedList.length(); rangedEvent.endTimeIndex = d->m_endTimeSortedList.length();
@@ -996,7 +1281,7 @@ void QmlProfilerEventList::load()
if (attributes.hasAttribute("index")) { if (attributes.hasAttribute("index")) {
int ndx = attributes.value("index").toString().toInt(); int ndx = attributes.value("index").toString().toInt();
if (!descriptionBuffer.value(ndx)) if (!descriptionBuffer.value(ndx))
descriptionBuffer[ndx] = new QmlEventData(); descriptionBuffer[ndx] = new QmlEventData;
currentEvent = descriptionBuffer[ndx]; currentEvent = descriptionBuffer[ndx];
} else { } else {
currentEvent = 0; currentEvent = 0;
@@ -1055,9 +1340,16 @@ void QmlProfilerEventList::load()
if (elementName == "childrenEvents") { if (elementName == "childrenEvents") {
QXmlStreamAttributes attributes = stream.attributes(); QXmlStreamAttributes attributes = stream.attributes();
int eventIndex = v8eventBuffer.key(v8event);
if (attributes.hasAttribute("list")) { if (attributes.hasAttribute("list")) {
// store for later parsing (we haven't read all the events yet) // 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") { if (elementName == "totalTime") {
v8event->totalTime = readData.toDouble(); v8event->totalTime = readData.toDouble();
cumulatedV8Time += v8event->totalTime;
break; break;
} }
@@ -1126,10 +1419,22 @@ void QmlProfilerEventList::load()
stream.clear(); 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 // move the buffered data to the details cache
foreach (QmlEventData *desc, descriptionBuffer.values()) { foreach (QmlEventData *desc, descriptionBuffer.values()) {
QString location = QString("%1:%2:%3").arg(QString::number(desc->eventType), desc->displayname, desc->details); 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; d->m_eventDescriptions[location] = desc;
} }
@@ -1145,12 +1450,20 @@ void QmlProfilerEventList::load()
// find v8events' children and parents // find v8events' children and parents
foreach (int parentIndex, childrenIndexes.keys()) { foreach (int parentIndex, childrenIndexes.keys()) {
QStringList childrenStrings = childrenIndexes.value(parentIndex).split((",")); QStringList childrenStrings = childrenIndexes.value(parentIndex).split(",");
foreach (const QString &childString, childrenStrings) { QStringList childrenTimesStrings = childrenTimes.value(parentIndex).split(", ");
int childIndex = childString.toInt(); QStringList parentTimesStrings = parentTimes.value(parentIndex).split(", ");
for (int ndx = 0; ndx < childrenStrings.count(); ndx++) {
int childIndex = childrenStrings[ndx].toInt();
if (v8eventBuffer.value(childIndex)) { if (v8eventBuffer.value(childIndex)) {
v8eventBuffer[parentIndex]->childrenList << v8eventBuffer[childIndex]; QV8EventSub *newChild = new QV8EventSub(v8eventBuffer[childIndex]);
v8eventBuffer[childIndex]->parentList << v8eventBuffer[parentIndex]; 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);
} }
} }
} }

View File

@@ -41,18 +41,23 @@
namespace QmlJsDebugClient { namespace QmlJsDebugClient {
struct QmlEventSub;
struct QV8EventSub;
struct QMLJSDEBUGCLIENT_EXPORT QmlEventData struct QMLJSDEBUGCLIENT_EXPORT QmlEventData
{ {
QmlEventData():line(-1),cumulatedDuration(0),calls(0),eventId(-1){} QmlEventData();
~QmlEventData();
QString displayname; QString displayname;
QString filename; QString filename;
QString location; QString eventHashStr;
QString details; QString details;
int line; int line;
QmlJsDebugClient::QmlEventType eventType; QmlJsDebugClient::QmlEventType eventType;
QList< QmlEventData *> parentList; QHash <QString, QmlEventSub *> parentHash;
QList< QmlEventData *> childrenList; QHash <QString, QmlEventSub *> childrenHash;
qint64 cumulatedDuration; qint64 duration;
qint64 calls; qint64 calls;
qint64 minTime; qint64 minTime;
qint64 maxTime; qint64 maxTime;
@@ -60,10 +65,23 @@ struct QMLJSDEBUGCLIENT_EXPORT QmlEventData
double percentOfTime; double percentOfTime;
qint64 medianTime; qint64 medianTime;
int eventId; 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 struct QMLJSDEBUGCLIENT_EXPORT QV8EventData
{ {
QV8EventData();
~QV8EventData();
QString displayName; QString displayName;
QString filename; QString filename;
QString functionName; QString functionName;
@@ -72,9 +90,19 @@ struct QMLJSDEBUGCLIENT_EXPORT QV8EventData
double totalPercent; double totalPercent;
double selfTime; double selfTime;
double selfPercent; double selfPercent;
QList< QV8EventData *> parentList; QHash <QString, QV8EventSub *> parentHash;
QList< QV8EventData *> childrenList; QHash <QString, QV8EventSub *> childrenHash;
int eventId; 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; typedef QHash<QString, QmlEventData *> QmlEventHash;

View File

@@ -83,6 +83,9 @@ function drawData(canvas, ctxt, region)
function drawTimeBar(canvas, ctxt, region) function drawTimeBar(canvas, ctxt, region)
{ {
if (!qmlEventList)
return;
var width = canvas.width; var width = canvas.width;
var height = 10; var height = 10;
var startTime = qmlEventList.traceStartTime(); var startTime = qmlEventList.traceStartTime();

View File

@@ -70,7 +70,7 @@ public:
data(LineRole).toInt() < other.data(LineRole).toInt() : data(LineRole).toInt() < other.data(LineRole).toInt() :
data(FilenameRole).toString() < other.data(FilenameRole).toString(); data(FilenameRole).toString() < other.data(FilenameRole).toString();
} else { } 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 buildModelFromList(const QmlEventDescriptions &list, QStandardItem *parentItem, const QmlEventDescriptions &visitedFunctionsList = QmlEventDescriptions() );
void buildV8ModelFromList( const QV8EventDescriptions &list ); void buildV8ModelFromList( const QV8EventDescriptions &list );
int getFieldCount(); int getFieldCount();
QString displayTime(double time) const;
QString nameForType(int typeNumber) const;
QString textForItem(QStandardItem *item, bool recursive) const; QString textForItem(QStandardItem *item, bool recursive) const;
@@ -282,8 +280,6 @@ void QmlProfilerEventsMainView::setViewType(ViewTypes type)
setFieldViewable(MinTime, true); setFieldViewable(MinTime, true);
setFieldViewable(MedianTime, true); setFieldViewable(MedianTime, true);
setFieldViewable(Details, true); setFieldViewable(Details, true);
setFieldViewable(Parents, false);
setFieldViewable(Children, false);
break; break;
} }
case V8ProfileView: { case V8ProfileView: {
@@ -300,8 +296,6 @@ void QmlProfilerEventsMainView::setViewType(ViewTypes type)
setFieldViewable(MinTime, false); setFieldViewable(MinTime, false);
setFieldViewable(MedianTime, false); setFieldViewable(MedianTime, false);
setFieldViewable(Details, true); setFieldViewable(Details, true);
setFieldViewable(Parents, false);
setFieldViewable(Children, false);
break; break;
} }
default: break; default: break;
@@ -358,7 +352,7 @@ int QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::getFieldCount()
{ {
int count = 0; int count = 0;
for (int i=0; i < m_fieldShown.count(); ++i) for (int i=0; i < m_fieldShown.count(); ++i)
if (m_fieldShown[i] && i != Parents && i != Children) if (m_fieldShown[i])
count++; count++;
return count; return count;
} }
@@ -372,12 +366,8 @@ void QmlProfilerEventsMainView::buildModel()
else else
d->buildModelFromList( d->m_eventStatistics->getEventDescriptions(), d->m_model->invisibleRootItem() ); d->buildModelFromList( d->m_eventStatistics->getEventDescriptions(), d->m_model->invisibleRootItem() );
bool hasBranches = d->m_fieldShown[Parents] || d->m_fieldShown[Children]; setRootIsDecorated(false);
setRootIsDecorated(hasBranches);
setSortingEnabled(true); setSortingEnabled(true);
if (!hasBranches)
sortByColumn(d->m_firstNumericColumn,Qt::DescendingOrder); sortByColumn(d->m_firstNumericColumn,Qt::DescendingOrder);
expandAll(); expandAll();
@@ -415,8 +405,8 @@ void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFrom
} }
if (m_fieldShown[TotalDuration]) { if (m_fieldShown[TotalDuration]) {
newRow << new EventsViewItem(displayTime(binding->cumulatedDuration)); newRow << new EventsViewItem(displayTime(binding->duration));
newRow.last()->setData(QVariant(binding->cumulatedDuration)); newRow.last()->setData(QVariant(binding->duration));
} }
if (m_fieldShown[CallCount]) { if (m_fieldShown[CallCount]) {
@@ -457,27 +447,13 @@ void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildModelFrom
item->setEditable(false); item->setEditable(false);
// metadata // 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->filename),FilenameRole);
newRow.at(0)->setData(QVariant(binding->line),LineRole); newRow.at(0)->setData(QVariant(binding->line),LineRole);
newRow.at(0)->setData(QVariant(binding->eventId),EventIdRole); newRow.at(0)->setData(QVariant(binding->eventId),EventIdRole);
// append // append
parentItem->appendRow(newRow); 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,9 +499,10 @@ void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildV8ModelFr
item->setEditable(false); item->setEditable(false);
// metadata // metadata
newRow.at(0)->setData(QVariant(v8event->filename),FilenameRole); newRow.at(0)->setData(QString("%1:%2").arg(v8event->filename, QString::number(v8event->line)), EventHashStrRole);
newRow.at(0)->setData(QVariant(v8event->line),LineRole); newRow.at(0)->setData(QVariant(v8event->filename), FilenameRole);
newRow.at(0)->setData(QVariant(v8event->eventId),EventIdRole); newRow.at(0)->setData(QVariant(v8event->line), LineRole);
newRow.at(0)->setData(QVariant(v8event->eventId), EventIdRole);
// append // append
m_model->invisibleRootItem()->appendRow(newRow); m_model->invisibleRootItem()->appendRow(newRow);
@@ -533,14 +510,14 @@ void QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::buildV8ModelFr
} }
} }
QString QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::displayTime(double time) const QString QmlProfilerEventsMainView::displayTime(double time)
{ {
if (time < 1e6) 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) 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) QString QmlProfilerEventsMainView::nameForType(int typeNumber)
@@ -719,24 +696,36 @@ void QmlProfilerEventsParentsAndChildrenView::displayEvent(int eventId)
if (isV8) { if (isV8) {
QmlJsDebugClient::QV8EventData *v8event = m_eventList->v8EventDescription(eventId); QmlJsDebugClient::QV8EventData *v8event = m_eventList->v8EventDescription(eventId);
if (v8event) { if (v8event) {
if (isChildren) if (isChildren) {
rebuildTree((QObject *)&v8event->childrenList); QList <QmlJsDebugClient::QV8EventSub *> childrenList = v8event->childrenHash.values();
else rebuildTree((QObject *)&childrenList);
rebuildTree((QObject *)&v8event->parentList); }
else {
QList <QmlJsDebugClient::QV8EventSub *> parentList = v8event->parentHash.values();
rebuildTree((QObject *)&parentList);
}
} }
} else { } else {
QmlJsDebugClient::QmlEventData *qmlEvent = m_eventList->eventDescription(eventId); QmlJsDebugClient::QmlEventData *qmlEvent = m_eventList->eventDescription(eventId);
if (qmlEvent) { if (qmlEvent) {
if (isChildren) if (isChildren) {
rebuildTree((QObject *)&qmlEvent->childrenList); QList <QmlJsDebugClient::QmlEventSub *> childrenList = qmlEvent->childrenHash.values();
else rebuildTree((QObject *)&childrenList);
rebuildTree((QObject *)&qmlEvent->parentList); }
else {
QList <QmlJsDebugClient::QmlEventSub *> parentList = qmlEvent->parentHash.values();
rebuildTree((QObject *)&parentList);
}
} }
} }
updateHeader(); updateHeader();
resizeColumnToContents(0); resizeColumnToContents(0);
setSortingEnabled(true); setSortingEnabled(true);
if (isV8)
sortByColumn(1);
else
sortByColumn(2);
} }
void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList) void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList)
@@ -747,8 +736,8 @@ void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList)
QStandardItem *topLevelItem = treeModel()->invisibleRootItem(); QStandardItem *topLevelItem = treeModel()->invisibleRootItem();
bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView; bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView;
QList <QmlEventData *> *qmlList = static_cast< QList <QmlEventData *> *>(eventList); QList <QmlEventSub *> *qmlList = static_cast< QList <QmlEventSub *> *>(eventList);
QList <QV8EventData *> *v8List = static_cast< QList <QV8EventData *> *>(eventList); QList <QV8EventSub*> *v8List = static_cast< QList <QV8EventSub *> *>(eventList);
int listLength; int listLength;
if (!isV8) if (!isV8)
@@ -759,17 +748,23 @@ void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *eventList)
for (int index=0; index < listLength; index++) { for (int index=0; index < listLength; index++) {
QList<QStandardItem *> newRow; QList<QStandardItem *> newRow;
if (!isV8) { if (!isV8) {
QmlEventData *event = qmlList->at(index); QmlEventSub *event = qmlList->at(index);
newRow << new QStandardItem(event->displayname); newRow << new EventsViewItem(event->reference->displayname);
newRow << new QStandardItem(QmlProfilerEventsMainView::nameForType(event->eventType)); newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event->reference->eventType));
newRow << new QStandardItem(event->details); newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event->duration));
newRow.at(0)->setData(QVariant(event->eventId), EventIdRole); 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 { } else {
QV8EventData *event = v8List->at(index); QV8EventSub *event = v8List->at(index);
newRow << new QStandardItem(event->displayName); newRow << new EventsViewItem(event->reference->displayName);
newRow << new QStandardItem(event->functionName); newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event->totalTime));
newRow.at(0)->setData(QVariant(event->eventId), EventIdRole); 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) foreach (QStandardItem *item, newRow)
item->setEditable(false); item->setEditable(false);
@@ -797,9 +792,9 @@ void QmlProfilerEventsParentsAndChildrenView::updateHeader()
if (treeModel()) { if (treeModel()) {
if (isV8) if (isV8)
treeModel()->setColumnCount(2);
else
treeModel()->setColumnCount(3); treeModel()->setColumnCount(3);
else
treeModel()->setColumnCount(5);
int columnIndex = 0; int columnIndex = 0;
if (isChildren) if (isChildren)
@@ -810,6 +805,11 @@ void QmlProfilerEventsParentsAndChildrenView::updateHeader()
if (!isV8) if (!isV8)
treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Type"))); 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) if (isChildren)
treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee Description"))); treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee Description")));
else else

View File

@@ -48,7 +48,7 @@ typedef QHash<QString, QmlJsDebugClient::QmlEventData *> QmlEventHash;
typedef QList<QmlJsDebugClient::QmlEventData *> QmlEventList; typedef QList<QmlJsDebugClient::QmlEventData *> QmlEventList;
enum ItemRole { enum ItemRole {
LocationRole = Qt::UserRole+1, EventHashStrRole = Qt::UserRole+1,
FilenameRole = Qt::UserRole+2, FilenameRole = Qt::UserRole+2,
LineRole = Qt::UserRole+3, LineRole = Qt::UserRole+3,
EventIdRole = Qt::UserRole+4 EventIdRole = Qt::UserRole+4
@@ -108,8 +108,6 @@ public:
MinTime, MinTime,
MedianTime, MedianTime,
Details, Details,
Parents,
Children,
MaxFields MaxFields
}; };
@@ -135,6 +133,7 @@ public:
void copyTableToClipboard() const; void copyTableToClipboard() const;
void copyRowToClipboard() const; void copyRowToClipboard() const;
static QString displayTime(double time);
static QString nameForType(int typeNumber); static QString nameForType(int typeNumber);
void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd);