diff options
Diffstat (limited to 'tools/qmlprofiler/qmlprofilerclient.cpp')
-rw-r--r-- | tools/qmlprofiler/qmlprofilerclient.cpp | 400 |
1 files changed, 126 insertions, 274 deletions
diff --git a/tools/qmlprofiler/qmlprofilerclient.cpp b/tools/qmlprofiler/qmlprofilerclient.cpp index b4768e6934..217942244f 100644 --- a/tools/qmlprofiler/qmlprofilerclient.cpp +++ b/tools/qmlprofiler/qmlprofilerclient.cpp @@ -1,348 +1,200 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qmlprofilerclient.h" +#include "qmlprofilerdata.h" + +#include <private/qqmlprofilerclient_p_p.h> #include <QtCore/QStack> #include <QtCore/QStringList> -#include <QtCore/QDataStream> #include <limits> -ProfilerClient::ProfilerClient(const QString &clientName, - QQmlDebugConnection *client) - : QQmlDebugClient(clientName, client), - m_enabled(false) -{ -} - -ProfilerClient::~ProfilerClient() -{ -} - -void ProfilerClient::clearData() -{ - emit cleared(); -} - -bool ProfilerClient::isEnabled() const -{ - return m_enabled; -} - -void ProfilerClient::stateChanged(State status) -{ - if ((m_enabled && status != Enabled) || - (!m_enabled && status == Enabled)) - emit enabledChanged(); - - m_enabled = status == Enabled; - -} - -class QmlProfilerClientPrivate +class QmlProfilerClientPrivate : public QQmlProfilerClientPrivate { + Q_DECLARE_PUBLIC(QmlProfilerClient) public: - QmlProfilerClientPrivate() - : inProgressRanges(0) , features(std::numeric_limits<quint64>::max()) - { - ::memset(rangeCount, 0, QQmlProfilerDefinitions::MaximumRangeType * sizeof(int)); - } + QmlProfilerClientPrivate(QQmlDebugConnection *connection, QmlProfilerData *data); + + QmlProfilerData *data; qint64 inProgressRanges; QStack<qint64> rangeStartTimes[QQmlProfilerDefinitions::MaximumRangeType]; QStack<QStringList> rangeDatas[QQmlProfilerDefinitions::MaximumRangeType]; - QStack<QmlEventLocation> rangeLocations[QQmlProfilerDefinitions::MaximumRangeType]; - QStack<QQmlProfilerDefinitions::BindingType> bindingTypes; + QStack<QQmlEventLocation> rangeLocations[QQmlProfilerDefinitions::MaximumRangeType]; int rangeCount[QQmlProfilerDefinitions::MaximumRangeType]; - quint64 features; + bool enabled; }; -QmlProfilerClient::QmlProfilerClient( - QQmlDebugConnection *client) - : ProfilerClient(QStringLiteral("CanvasFrameRate"), client), - d(new QmlProfilerClientPrivate) +QmlProfilerClientPrivate::QmlProfilerClientPrivate(QQmlDebugConnection *connection, + QmlProfilerData *data) : + QQmlProfilerClientPrivate(connection), data(data), inProgressRanges(0), enabled(false) { + ::memset(rangeCount, 0, QQmlProfilerDefinitions::MaximumRangeType * sizeof(int)); } -QmlProfilerClient::~QmlProfilerClient() +QmlProfilerClient::QmlProfilerClient(QQmlDebugConnection *connection, QmlProfilerData *data) : + QQmlProfilerClient(*(new QmlProfilerClientPrivate(connection, data))) { - delete d; } -void QmlProfilerClient::setFeatures(quint64 features) +void QmlProfilerClient::clearPendingData() { - d->features = features; + Q_D(QmlProfilerClient); + for (int i = 0; i < QQmlProfilerDefinitions::MaximumRangeType; ++i) { + d->rangeCount[i] = 0; + d->rangeDatas[i].clear(); + d->rangeLocations[i].clear(); + } } -void QmlProfilerClient::clearData() +void QmlProfilerClient::stateChanged(State state) { - ::memset(d->rangeCount, 0, QQmlProfilerDefinitions::MaximumRangeType * sizeof(int)); - d->bindingTypes.clear(); - ProfilerClient::clearData(); + Q_D(QmlProfilerClient); + if ((d->enabled && state != Enabled) || (!d->enabled && state == Enabled)) { + d->enabled = (state == Enabled); + emit enabledChanged(d->enabled); + } } -void QmlProfilerClient::sendRecordingStatus(bool record) +void QmlProfilerClient::traceStarted(qint64 time, int engineId) { - QByteArray ba; - QDataStream stream(&ba, QIODevice::WriteOnly); - stream.setVersion(QDataStream::Qt_4_7); - stream << record << -1 << d->features; - sendMessage(ba); + Q_UNUSED(engineId); + Q_D(QmlProfilerClient); + d->data->setTraceStartTime(time); + emit recordingStarted(); } -inline QQmlProfilerDefinitions::ProfileFeature featureFromRangeType( - QQmlProfilerDefinitions::RangeType range) +void QmlProfilerClient::traceFinished(qint64 time, int engineId) { - switch (range) { - case QQmlProfilerDefinitions::Painting: - return QQmlProfilerDefinitions::ProfilePainting; - case QQmlProfilerDefinitions::Compiling: - return QQmlProfilerDefinitions::ProfileCompiling; - case QQmlProfilerDefinitions::Creating: - return QQmlProfilerDefinitions::ProfileCreating; - case QQmlProfilerDefinitions::Binding: - return QQmlProfilerDefinitions::ProfileBinding; - case QQmlProfilerDefinitions::HandlingSignal: - return QQmlProfilerDefinitions::ProfileHandlingSignal; - case QQmlProfilerDefinitions::Javascript: - return QQmlProfilerDefinitions::ProfileJavaScript; - default: - return QQmlProfilerDefinitions::MaximumProfileFeature; - } + Q_UNUSED(engineId); + Q_D(QmlProfilerClient); + d->data->setTraceEndTime(time); } -void QmlProfilerClient::messageReceived(const QByteArray &data) +void QmlProfilerClient::rangeStart(QQmlProfilerDefinitions::RangeType type, qint64 startTime) { - QByteArray rwData = data; - QDataStream stream(&rwData, QIODevice::ReadOnly); - stream.setVersion(QDataStream::Qt_4_7); + Q_D(QmlProfilerClient); + d->rangeStartTimes[type].push(startTime); + d->inProgressRanges |= (static_cast<qint64>(1) << type); + ++d->rangeCount[type]; +} - // Force all the 1 << <FLAG> expressions to be done in 64 bit, to silence some warnings - const quint64 one = static_cast<quint64>(1); +void QmlProfilerClient::rangeData(QQmlProfilerDefinitions::RangeType type, qint64 time, + const QString &data) +{ + Q_UNUSED(time); + Q_D(QmlProfilerClient); + int count = d->rangeCount[type]; + if (count > 0) { + while (d->rangeDatas[type].count() < count) + d->rangeDatas[type].push(QStringList()); + d->rangeDatas[type][count - 1] << data; + } +} - qint64 time; - int messageType; +void QmlProfilerClient::rangeLocation(QQmlProfilerDefinitions::RangeType type, qint64 time, + const QQmlEventLocation &location) +{ + Q_UNUSED(time); + Q_D(QmlProfilerClient); + if (d->rangeCount[type] > 0) + d->rangeLocations[type].push(location); +} - stream >> time >> messageType; +void QmlProfilerClient::rangeEnd(QQmlProfilerDefinitions::RangeType type, qint64 endTime) +{ + Q_D(QmlProfilerClient); - if (messageType >= QQmlProfilerDefinitions::MaximumMessage) + if (d->rangeCount[type] == 0) { + emit error(tr("Spurious range end detected.")); return; + } - if (messageType == QQmlProfilerDefinitions::Event) { - int event; - stream >> event; - - if (event == QQmlProfilerDefinitions::EndTrace) { - emit this->traceFinished(time); - } else if (event == QQmlProfilerDefinitions::AnimationFrame) { - if (!(d->features & one << QQmlProfilerDefinitions::ProfileAnimations)) - return; - int frameRate, animationCount; - int threadId = 0; - stream >> frameRate >> animationCount; - if (!stream.atEnd()) - stream >> threadId; - emit this->frame(time, frameRate, animationCount, threadId); - } else if (event == QQmlProfilerDefinitions::StartTrace) { - emit this->traceStarted(time); - } else if (event == QQmlProfilerDefinitions::Key || - event == QQmlProfilerDefinitions::Mouse) { - if (!(d->features & one << QQmlProfilerDefinitions::ProfileInputEvents)) - return; - emit this->inputEvent((QQmlProfilerDefinitions::EventType)event, time); - } - } else if (messageType == QQmlProfilerDefinitions::Complete) { - emit complete(); - } else if (messageType == QQmlProfilerDefinitions::SceneGraphFrame) { - if (!(d->features & one << QQmlProfilerDefinitions::ProfileSceneGraph)) - return; - int sgEventType; - int count = 0; - qint64 params[5]; - - stream >> sgEventType; - while (!stream.atEnd()) { - stream >> params[count++]; - } - while (count<5) - params[count++] = 0; - emit sceneGraphFrame((QQmlProfilerDefinitions::SceneGraphFrameType)sgEventType, time, - params[0], params[1], params[2], params[3], params[4]); - } else if (messageType == QQmlProfilerDefinitions::PixmapCacheEvent) { - if (!(d->features & one << QQmlProfilerDefinitions::ProfilePixmapCache)) - return; - int pixEvTy, width = 0, height = 0, refcount = 0; - QString pixUrl; - stream >> pixEvTy >> pixUrl; - if (pixEvTy == (int)QQmlProfilerDefinitions::PixmapReferenceCountChanged || - pixEvTy == (int)QQmlProfilerDefinitions::PixmapCacheCountChanged) { - stream >> refcount; - } else if (pixEvTy == (int)QQmlProfilerDefinitions::PixmapSizeKnown) { - stream >> width >> height; - refcount = 1; - } - emit pixmapCache((QQmlProfilerDefinitions::PixmapEventType)pixEvTy, time, - QmlEventLocation(pixUrl,0,0), width, height, refcount); - } else if (messageType == QQmlProfilerDefinitions::MemoryAllocation) { - if (!(d->features & one << QQmlProfilerDefinitions::ProfileMemory)) - return; - int type; - qint64 delta; - stream >> type >> delta; - emit memoryAllocation((QQmlProfilerDefinitions::MemoryType)type, time, delta); - } else { - int range; - stream >> range; - - if (range >= QQmlProfilerDefinitions::MaximumRangeType) - return; - - if (!(d->features & one << featureFromRangeType( - static_cast<QQmlProfilerDefinitions::RangeType>(range)))) - return; - - if (messageType == QQmlProfilerDefinitions::RangeStart) { - d->rangeStartTimes[range].push(time); - d->inProgressRanges |= (static_cast<qint64>(1) << range); - ++d->rangeCount[range]; - - // read binding type - if (range == (int)QQmlProfilerDefinitions::Binding) { - int bindingType = (int)QQmlProfilerDefinitions::QmlBinding; - if (!stream.atEnd()) - stream >> bindingType; - d->bindingTypes.push((QQmlProfilerDefinitions::BindingType)bindingType); - } - } else if (messageType == QQmlProfilerDefinitions::RangeData) { - QString data; - stream >> data; - - int count = d->rangeCount[range]; - if (count > 0) { - while (d->rangeDatas[range].count() < count) - d->rangeDatas[range].push(QStringList()); - d->rangeDatas[range][count-1] << data; - } - - } else if (messageType == QQmlProfilerDefinitions::RangeLocation) { - QString fileName; - int line; - int column = -1; - stream >> fileName >> line; - - if (!stream.atEnd()) - stream >> column; - - if (d->rangeCount[range] > 0) { - d->rangeLocations[range].push(QmlEventLocation(fileName, line, - column)); - } - } else { - if (d->rangeCount[range] > 0) { - --d->rangeCount[range]; - if (d->inProgressRanges & (static_cast<qint64>(1) << range)) - d->inProgressRanges &= ~(static_cast<qint64>(1) << range); - - QStringList data = d->rangeDatas[range].count() ? - d->rangeDatas[range].pop() : QStringList(); - QmlEventLocation location = d->rangeLocations[range].count() ? - d->rangeLocations[range].pop() : QmlEventLocation(); - - qint64 startTime = d->rangeStartTimes[range].pop(); - QQmlProfilerDefinitions::BindingType bindingType = - QQmlProfilerDefinitions::QmlBinding; - if (range == (int)QQmlProfilerDefinitions::Binding) - bindingType = d->bindingTypes.pop(); - emit this->range((QQmlProfilerDefinitions::RangeType)range, - bindingType, startTime, time - startTime, data, location); - if (d->rangeCount[range] == 0) { - int count = d->rangeDatas[range].count() + - d->rangeStartTimes[range].count() + - d->rangeLocations[range].count(); - if (count != 0) - qWarning() << "incorrectly nested data"; - } - } - } + --d->rangeCount[type]; + if (d->inProgressRanges & (static_cast<qint64>(1) << type)) + d->inProgressRanges &= ~(static_cast<qint64>(1) << type); + QStringList data = d->rangeDatas[type].count() ? d->rangeDatas[type].pop() : QStringList(); + QQmlEventLocation location = d->rangeLocations[type].count() ? d->rangeLocations[type].pop() : + QQmlEventLocation(); + qint64 startTime = d->rangeStartTimes[type].pop(); + + if (d->rangeCount[type] == 0 && d->rangeDatas[type].count() + d->rangeStartTimes[type].count() + + d->rangeLocations[type].count() != 0) { + emit error(tr("Incorrectly nested range data")); + return; } + + d->data->addQmlEvent(type, QQmlProfilerDefinitions::QmlBinding, startTime, endTime - startTime, + data, location); } -V8ProfilerClient::V8ProfilerClient(QQmlDebugConnection *client) - : ProfilerClient(QStringLiteral("V8Profiler"), client) +void QmlProfilerClient::animationFrame(qint64 time, int frameRate, int animationCount, int threadId) { + Q_D(QmlProfilerClient); + d->data->addFrameEvent(time, frameRate, animationCount, threadId); } -V8ProfilerClient::~V8ProfilerClient() +void QmlProfilerClient::sceneGraphEvent(QQmlProfilerDefinitions::SceneGraphFrameType type, + qint64 time, qint64 numericData1, qint64 numericData2, + qint64 numericData3, qint64 numericData4, + qint64 numericData5) { + Q_D(QmlProfilerClient); + d->data->addSceneGraphFrameEvent(type, time, numericData1, numericData2, numericData3, + numericData4, numericData5); } -void V8ProfilerClient::sendRecordingStatus(bool record) +void QmlProfilerClient::pixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type, qint64 time, + const QString &url, int numericData1, int numericData2) { - QByteArray ba; - QDataStream stream(&ba, QIODevice::WriteOnly); - QByteArray cmd("V8PROFILER"); - QByteArray option(record ? "start" : "stop"); - QByteArray title(""); - - stream << cmd << option << title; - sendMessage(ba); + Q_D(QmlProfilerClient); + d->data->addPixmapCacheEvent(type, time, url, numericData1, numericData2); } -void V8ProfilerClient::messageReceived(const QByteArray &data) +void QmlProfilerClient::memoryAllocation(QQmlProfilerDefinitions::MemoryType type, qint64 time, + qint64 amount) { - QByteArray rwData = data; - QDataStream stream(&rwData, QIODevice::ReadOnly); - - int messageType; - - stream >> messageType; - - if (messageType == V8Complete) { - emit complete(); - } else if (messageType == V8Entry) { - QString filename; - QString function; - int lineNumber; - double totalTime; - double selfTime; - int depth; + Q_D(QmlProfilerClient); + d->data->addMemoryEvent(type, time, amount); +} - stream >> filename >> function >> lineNumber >> totalTime >> - selfTime >> depth; - emit this->range(depth, function, filename, lineNumber, totalTime, - selfTime); - } +void QmlProfilerClient::inputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time, + int a, int b) +{ + Q_D(QmlProfilerClient); + d->data->addInputEvent(type, time, a, b); } +void QmlProfilerClient::complete() +{ + Q_D(QmlProfilerClient); + d->data->complete(); +} |