예제 #1
0
void MemoryUsageModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
{
    if (type.message() != MemoryAllocation) {
        if (type.rangeType() != MaximumRangeType) {
            if (event.rangeStage() == RangeStart)
                m_rangeStack.push(RangeStackFrame(event.typeIndex(), event.timestamp()));
            else if (event.rangeStage() == RangeEnd)
                m_rangeStack.pop();

            m_continuation = ContinueNothing;
        }
        return;
    }

    auto canContinue = [&](EventContinuation continuation) {
        QTC_ASSERT(continuation != ContinueNothing, return false);
        if ((m_continuation & continuation) == 0)
            return false;

        int currentIndex = (continuation == ContinueAllocation ? m_currentJSHeapIndex :
                                                                 m_currentUsageIndex);

        if (m_rangeStack.isEmpty()) {
            qint64 amount = event.number<qint64>(0);
            // outside of ranges show monotonous allocation or deallocation
            return (amount >= 0 && m_data[currentIndex].allocated >= 0)
                    || (amount < 0 && m_data[currentIndex].deallocated > 0);
        } else {
            return m_data[currentIndex].typeId == m_rangeStack.top().originTypeIndex
                    && m_rangeStack.top().startTime < startTime(currentIndex);
        }
    };
예제 #2
0
void QmlProfilerRangeModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
{
    Q_UNUSED(type);
    // store starttime-based instance
    if (event.rangeStage() == RangeStart) {
        int index = insertStart(event.timestamp(), event.typeIndex());
        m_stack.append(index);
        m_data.insert(index, QmlRangeEventStartInstance());
    } else if (event.rangeStage() == RangeEnd) {
        if (!m_stack.isEmpty()) {
            int index = m_stack.pop();
            insertEnd(index, event.timestamp() - startTime(index));
        } else {
            qWarning() << "Received inconsistent trace data from application.";
        }
    }
}
예제 #3
0
void FlameGraphModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
{
    if (!m_acceptedTypes.contains(type.rangeType))
        return;

    if (m_stackBottom.children.isEmpty())
        beginResetModel();

    const QmlEvent *potentialParent = &(m_callStack.top());
    if (event.rangeStage() == RangeEnd) {
        m_stackTop->duration += event.timestamp() - potentialParent->timestamp();
        m_callStack.pop();
        m_stackTop = m_stackTop->parent;
        potentialParent = &(m_callStack.top());
    } else {
        QTC_ASSERT(event.rangeStage() == RangeStart, return);
        m_callStack.push(event);
        m_stackTop = pushChild(m_stackTop, event);
    }
}
void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
{
    if (!d->acceptedTypes.contains(type.rangeType()))
        return;

    switch (event.rangeStage()) {
    case RangeStart:
        // binding loop detection: check whether event is already in stack
        for (int ii = 1; ii < d->callStack.size(); ++ii) {
            if (d->callStack.at(ii).typeIndex() == event.typeIndex()
                    && type.rangeType() != Javascript) {
                d->eventsInBindingLoop.insert(event.typeIndex());
                break;
            }
        }
        d->callStack.push(event);
        break;
    case RangeEnd: {
        // update stats
        QmlEventStats *stats = &d->data[event.typeIndex()];
        qint64 duration = event.timestamp() - d->callStack.top().timestamp();
        stats->duration += duration;
        stats->durationSelf += duration;
        if (duration < stats->minTime)
            stats->minTime = duration;
        if (duration > stats->maxTime)
            stats->maxTime = duration;
        stats->calls++;
        // for median computing
        d->durations[event.typeIndex()].append(duration);
        // qml time computation
        if (event.timestamp() > d->lastEndTime) { // assume parent event if starts before last end
            d->qmlTime += duration;
            d->lastEndTime = event.timestamp();
        }

        d->callStack.pop();

        if (d->callStack.count() > 1)
            d->data[d->callStack.top().typeIndex()].durationSelf -= duration;

        break;
    }
    default:
        break;
    }

    if (!d->childrenModel.isNull())
        d->childrenModel->loadEvent(event);
    if (!d->parentsModel.isNull())
        d->parentsModel->loadEvent(event);
}
예제 #5
0
void FlameGraphModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
{
    Q_UNUSED(type);

    if (m_stackBottom.children.isEmpty())
        beginResetModel();

    const bool isCompiling = (type.rangeType() == Compiling);
    QStack<QmlEvent> &stack =  isCompiling ? m_compileStack : m_callStack;
    FlameGraphData *&stackTop = isCompiling ? m_compileStackTop : m_callStackTop;

    const QmlEvent *potentialParent = &(stack.top());
    if (type.message() == MemoryAllocation) {
        if (type.detailType() == HeapPage)
            return; // We're only interested in actual allocations, not heap pages being mmap'd

        qint64 amount = event.number<qint64>(0);
        if (amount < 0)
            return; // We're not interested in GC runs here

        for (FlameGraphData *data = stackTop; data; data = data->parent) {
            ++data->allocations;
            data->memory += amount;
        }

    } else if (event.rangeStage() == RangeEnd) {
        stackTop->duration += event.timestamp() - potentialParent->timestamp();
        stack.pop();
        stackTop = stackTop->parent;
        potentialParent = &(stack.top());
    } else {
        QTC_ASSERT(event.rangeStage() == RangeStart, return);
        stack.push(event);
        stackTop = pushChild(stackTop, event);
    }
}
void QmlProfilerStatisticsRelativesModel::loadEvent(const QmlEvent &event)
{
    // level computation
    switch (event.rangeStage()) {
    case RangeStart:
        // now lastparent is the new type
        ++m_level;
        m_typesPerLevel[m_level] = event.typeIndex();
        m_startTimesPerLevel[m_level] = event.timestamp();
        break;
    case RangeEnd: {
        int parentTypeIndex = -1;
        if (m_level > Constants::QML_MIN_LEVEL && m_typesPerLevel.contains(m_level-1))
            parentTypeIndex = m_typesPerLevel[m_level-1];

        int relativeTypeIndex = (m_relation == QmlProfilerStatisticsParents) ? parentTypeIndex :
                                                                               event.typeIndex();
        int selfTypeIndex = (m_relation == QmlProfilerStatisticsParents) ? event.typeIndex() :
                                                                           parentTypeIndex;

        QmlStatisticsRelativesMap &relativesMap = m_data[selfTypeIndex];
        QmlStatisticsRelativesMap::Iterator it = relativesMap.find(relativeTypeIndex);
        if (it != relativesMap.end()) {
            it.value().calls++;
            it.value().duration += event.timestamp() - m_startTimesPerLevel[m_level];
        } else {
            QmlStatisticsRelativesData relative = {
                event.timestamp() - m_startTimesPerLevel[m_level],
                1,
                false
            };
            relativesMap.insert(relativeTypeIndex, relative);
        }
        --m_level;
        break;
    }
    default:
        break;
    }
}