" Terminate the program if started from qmlprofiler,\n"
" and qmlprofiler itself.";
+static const char *features[] = {
+ "javascript",
+ "memory",
+ "pixmapcache",
+ "scenegraph",
+ "animations",
+ "painting",
+ "compiling",
+ "creating",
+ "binding",
+ "handlingsignal",
+ "inputevents"
+};
+
static const char TraceFileExtension[] = ".qtd";
QmlProfilerApplication::QmlProfilerApplication(int &argc, char **argv) :
QLatin1String("on|off"), QLatin1String("on"));
parser.addOption(record);
+ QStringList featureList;
+ for (int i = 0; i < QQmlProfilerService::MaximumProfileFeature; ++i)
+ featureList << QLatin1String(features[i]);
+
+ QCommandLineOption include(QLatin1String("include"),
+ tr("Comma-separated list of features to record. By default all "
+ "features supported by the QML engine are recorded. If --include "
+ "is specified, only the given features will be recorded. "
+ "The following features are unserstood by qmlprofiler: %1").arg(
+ featureList.join(", ")),
+ QLatin1String("feature,..."));
+ parser.addOption(include);
+
+ QCommandLineOption exclude(QLatin1String("exclude"),
+ tr("Comma-separated list of features to exclude when recording. By "
+ "default all features supported by the QML engine are recorded. "
+ "See --include for the features understood by qmlprofiler."),
+ QLatin1String("feature,..."));
+ parser.addOption(exclude);
+
QCommandLineOption interactive(QLatin1String("interactive"),
tr("Manually control the recording from the command line. The "
"profiler will not terminate itself when the application "
m_recording = (parser.value(record) == QLatin1String("on"));
m_interactive = parser.isSet(interactive);
+ quint64 features = std::numeric_limits<quint64>::max();
+ if (parser.isSet(include)) {
+ if (parser.isSet(exclude)) {
+ logError(tr("qmlprofiler can only process either --include or --exclude, not both."));
+ parser.showHelp(4);
+ }
+ features = parseFeatures(featureList, parser.value(include), false);
+ }
+
+ if (parser.isSet(exclude))
+ features = parseFeatures(featureList, parser.value(exclude), true);
+
+ if (features == 0)
+ parser.showHelp(4);
+
+ m_qmlProfilerClient.setFeatures(features);
+
if (parser.isSet(verbose))
m_verbose = true;
return m_interactive;
}
+quint64 QmlProfilerApplication::parseFeatures(const QStringList &featureList, const QString &values,
+ bool exclude)
+{
+ quint64 features = exclude ? std::numeric_limits<quint64>::max() : 0;
+ QStringList givenFeatures = values.split(QLatin1Char(','));
+ foreach (const QString &f, givenFeatures) {
+ int index = featureList.indexOf(f);
+ if (index < 0) {
+ logError(tr("Unknown feature '%1'").arg(f));
+ return 0;
+ }
+ quint64 flag = static_cast<quint64>(1) << index;
+ features = (exclude ? (features ^ flag) : (features | flag));
+ }
+ if (features == 0) {
+ logError(exclude ? tr("No features remaining to record after processing --exclude.") :
+ tr("No features specified for --include."));
+ }
+ return features;
+}
+
void QmlProfilerApplication::flush()
{
if (m_recording) {
{
public:
QmlProfilerClientPrivate()
- : inProgressRanges(0)
+ : inProgressRanges(0) , features(std::numeric_limits<quint64>::max())
{
::memset(rangeCount, 0,
QQmlProfilerService::MaximumRangeType * sizeof(int));
QStack<QmlEventLocation> rangeLocations[QQmlProfilerService::MaximumRangeType];
QStack<QQmlProfilerService::BindingType> bindingTypes;
int rangeCount[QQmlProfilerService::MaximumRangeType];
+
+ quint64 features;
};
QmlProfilerClient::QmlProfilerClient(
delete d;
}
+void QmlProfilerClient::setFeatures(quint64 features)
+{
+ d->features = features;
+}
+
void QmlProfilerClient::clearData()
{
::memset(d->rangeCount, 0,
{
QByteArray ba;
QDataStream stream(&ba, QIODevice::WriteOnly);
- stream << record;
+ stream << record << -1 << d->features;
sendMessage(ba);
}
+inline QQmlProfilerService::ProfileFeature featureFromRangeType(
+ QQmlProfilerService::RangeType range)
+{
+ switch (range) {
+ case QQmlProfilerService::Painting:
+ return QQmlProfilerService::ProfilePainting;
+ case QQmlProfilerService::Compiling:
+ return QQmlProfilerService::ProfileCompiling;
+ case QQmlProfilerService::Creating:
+ return QQmlProfilerService::ProfileCreating;
+ case QQmlProfilerService::Binding:
+ return QQmlProfilerService::ProfileBinding;
+ case QQmlProfilerService::HandlingSignal:
+ return QQmlProfilerService::ProfileHandlingSignal;
+ case QQmlProfilerService::Javascript:
+ return QQmlProfilerService::ProfileJavaScript;
+ default:
+ return QQmlProfilerService::MaximumProfileFeature;
+ }
+}
+
void QmlProfilerClient::messageReceived(const QByteArray &data)
{
QByteArray rwData = data;
QDataStream stream(&rwData, QIODevice::ReadOnly);
+ // Force all the 1 << <FLAG> expressions to be done in 64 bit, to silence some warnings
+ const quint64 one = static_cast<quint64>(1);
+
qint64 time;
int messageType;
if (event == QQmlProfilerService::EndTrace) {
emit this->traceFinished(time);
} else if (event == QQmlProfilerService::AnimationFrame) {
+ if (!(d->features & one << QQmlProfilerService::ProfileAnimations))
+ return;
int frameRate, animationCount;
int threadId = 0;
stream >> frameRate >> animationCount;
} else if (messageType == QQmlProfilerService::Complete) {
emit complete();
} else if (messageType == QQmlProfilerService::SceneGraphFrame) {
+ if (!(d->features & one << QQmlProfilerService::ProfileSceneGraph))
+ return;
int sgEventType;
int count = 0;
qint64 params[5];
emit sceneGraphFrame((QQmlProfilerService::SceneGraphFrameType)sgEventType, time,
params[0], params[1], params[2], params[3], params[4]);
} else if (messageType == QQmlProfilerService::PixmapCacheEvent) {
+ if (!(d->features & one << QQmlProfilerService::ProfilePixmapCache))
+ return;
int pixEvTy, width = 0, height = 0, refcount = 0;
QString pixUrl;
stream >> pixEvTy >> pixUrl;
emit pixmapCache((QQmlProfilerService::PixmapEventType)pixEvTy, time,
QmlEventLocation(pixUrl,0,0), width, height, refcount);
} else if (messageType == QQmlProfilerService::MemoryAllocation) {
+ if (!(d->features & one << QQmlProfilerService::ProfileMemory))
+ return;
int type;
qint64 delta;
stream >> type >> delta;
if (range >= QQmlProfilerService::MaximumRangeType)
return;
+ if (!(d->features & one << featureFromRangeType(
+ static_cast<QQmlProfilerService::RangeType>(range))))
+ return;
+
if (messageType == QQmlProfilerService::RangeStart) {
d->rangeStartTimes[range].push(time);
d->inProgressRanges |= (static_cast<qint64>(1) << range);