Skip to content

Commit

Permalink
MER: Add libsystrace support.
Browse files Browse the repository at this point in the history
[MER]: This patch is not upstreamed as libsystrace is not widely in use, the
impact of additional function calls into QtBase was undesired, and the general
approach is not really generic to other types of tracing at this time.

libsystrace is a very small initialized-on-load wrapper for Android systrace
functionality, used so that data is written in order, regardless of how many
different libraries are writing data to it at a given time.

systrace is very useful for tracking system behavior, and for performance
analysis and improvement.

See also:
https://developer.android.com/tools/debugging/systrace.html

Some example uses of QSystraceEvent are also included in this patch. More are
undoubtedly possible. Additional tracing (e.g. counting the number of ongoing
HTTP requests and various other bits and pieces) are also easily accomplished.

Change-Id: I70012f6ddaa084f5b08685ee40795d7fafcd9c96

Conflicts:
	configure
	src/corelib/global/global.pri
	src/dbus/qdbusintegrator.cpp
  • Loading branch information
rburchell authored and martinjones committed Oct 3, 2016
1 parent aedf4d2 commit 1ca6e3c
Show file tree
Hide file tree
Showing 18 changed files with 323 additions and 2 deletions.
7 changes: 7 additions & 0 deletions config.tests/unix/libsystrace/libsystrace.pro
@@ -0,0 +1,7 @@
SOURCES = systrace.c

CONFIG += link_pkgconfig
PKGCONFIG_PRIVATE += systrace

CONFIG -= qt

49 changes: 49 additions & 0 deletions config.tests/unix/libsystrace/systrace.c
@@ -0,0 +1,49 @@
/****************************************************************************
**
** Copyright (C) 2014 Jolla Ltd, author: <robin.burchell@jollamobile.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the config.tests of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/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 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt 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.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <systrace.h>

int main(int argc, char **argv)
{
SYSTRACE_BEGIN("config.tests", "systrace_main", "testing");
return 0;
}

22 changes: 22 additions & 0 deletions configure
Expand Up @@ -633,6 +633,7 @@ CFG_MTDEV=auto
CFG_JOURNALD=no
CFG_SYSLOG=no
CFG_SQLITE=qt
CFG_LIBSYSTRACE=auto
CFG_GIF=auto
CFG_PNG=yes
CFG_LIBPNG=auto
Expand Down Expand Up @@ -1733,6 +1734,13 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
;;
libsystrace)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_LIBSYSTRACE="$VAL"
else
UNKNOWN_OPT=yes
fi
;;
libpng)
[ "$VAL" = "yes" ] && VAL=qt
if [ "$VAL" = "qt" ] || [ "$VAL" = "no" ] || [ "$VAL" = "system" ]; then
Expand Down Expand Up @@ -4715,6 +4723,19 @@ if [ "$CFG_SYSLOG" != "no" ]; then
fi
fi

if [ "$CFG_LIBSYSTRACE" != "no" ]; then
if compileTest unix/libsystrace "libsystrace"; then
CFG_LIBSYSTRACE=yes
QMAKE_CONFIG="$QMAKE_CONFIG libsystrace"
QMakeVar add DEFINES QT_USE_LIBSYSTRACE
else
if [ "$CFG_LIBSYSTRACE" != "auto" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then
echo "libsystrace support cannot be enabled due to functionality tests!"
CFG_LIBSYSTRACE=no
fi
fi
fi

if [ "$CFG_LARGEFILE" = "auto" ]; then
#Large files should be enabled for all Linux systems
CFG_LARGEFILE=yes
Expand Down Expand Up @@ -7329,6 +7350,7 @@ report_support " libinput................" "$CFG_LIBINPUT"
report_support " Logging backends:"
report_support " journald ..............." "$CFG_JOURNALD"
report_support " syslog ..............." "$CFG_SYSLOG"
report_support " libsystrace ............" "$CFG_LIBSYSTRACE"
report_support " mtdev .................." "$CFG_MTDEV" yes "system library"
report_support " Networking:"
[ "$XPLATFORM_MAC" = "yes" ] && \
Expand Down
6 changes: 5 additions & 1 deletion qmake/Makefile.unix
Expand Up @@ -19,7 +19,7 @@ QOBJS=qtextcodec.o qutfcodec.o qstring.o qstring_compat.o qstringbuilder.o qtext
qbitarray.o qdir.o qdiriterator.o quuid.o qhash.o qfileinfo.o qdatetime.o qstringlist.o \
qabstractfileengine.o qtemporaryfile.o qmap.o qmetatype.o qsettings.o qsystemerror.o qlibraryinfo.o \
qvariant.o qvsnprintf.o qlocale.o qlocale_tools.o qlinkedlist.o qnumeric.o \
qcryptographichash.o qxmlstream.o qxmlutils.o qlogging.o \
qcryptographichash.o qxmlstream.o qxmlutils.o qsystrace.o qlogging.o \
qjson.o qjsondocument.o qjsonparser.o qjsonarray.o qjsonobject.o qjsonvalue.o \
$(QTOBJS)

Expand Down Expand Up @@ -83,6 +83,7 @@ DEPEND_SRC = \
$(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp \
$(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp \
$(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \
$(SOURCE_PATH)/src/corelib/global/qsystrace.cpp \
$(SOURCE_PATH)/src/corelib/global/qlogging.cpp \
$(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp \
$(SOURCE_PATH)/tools/shared/windows/registry.cpp \
Expand Down Expand Up @@ -400,6 +401,9 @@ qxmlstream.o: $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp
qxmlutils.o: $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp

qsystrace.o: $(SOURCE_PATH)/src/corelib/global/qsystrace.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qsystrace.cpp

qlogging.o: $(SOURCE_PATH)/src/corelib/global/qlogging.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlogging.cpp

Expand Down
6 changes: 5 additions & 1 deletion src/corelib/global/global.pri
Expand Up @@ -28,7 +28,8 @@ SOURCES += \
global/qmalloc.cpp \
global/qnumeric.cpp \
global/qlogging.cpp \
global/qhooks.cpp
global/qhooks.cpp \
global/qsystrace.cpp

VERSIONTAGGING_SOURCES = global/qversiontagging.cpp

Expand All @@ -45,6 +46,9 @@ if(linux*|hurd*):!cross_compile:!static:!*-armcc* {
QMAKE_LFLAGS += -Wl,-e,qt_core_boilerplate
prog=$$quote(if (/program interpreter: (.*)]/) { print $1; })
DEFINES += ELF_INTERPRETER=\\\"$$system(LC_ALL=C readelf -l /bin/ls | perl -n -e \'$$prog\')\\\"

CONFIG += link_pkgconfig
libsystrace: PKGCONFIG_PRIVATE += systrace
}

slog2 {
Expand Down
95 changes: 95 additions & 0 deletions src/corelib/global/qsystrace.cpp
@@ -0,0 +1,95 @@
/****************************************************************************
**
** Copyright (C) 2014 Jolla Ltd, author: <robin.burchell@jollamobile.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/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 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt 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.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsystrace_p.h"

#if !defined(QT_BOOTSTRAPPED) && !defined(QT_NO_DEBUG) && defined(QT_USE_LIBSYSTRACE)
# include <systrace.h>
#endif

void QSystrace::begin(const char *module, const char *tracepoint, const char *message, ...)
{
#if !defined(QT_BOOTSTRAPPED) && !defined(QT_NO_DEBUG) && defined(QT_USE_LIBSYSTRACE)
char buffer[1024];
va_list args;
va_start(args, message);
vsprintf(buffer, message, args);
va_end(args);
SYSTRACE_BEGIN(module, tracepoint, buffer);
#else
Q_UNUSED(module)
Q_UNUSED(tracepoint)
Q_UNUSED(message)
#endif
}

void QSystrace::end(const char *module, const char *tracepoint, const char *message, ...)
{
#if !defined(QT_BOOTSTRAPPED) && !defined(QT_NO_DEBUG) && defined(QT_USE_LIBSYSTRACE)
char buffer[1024];
va_list args;
va_start(args, message);
vsprintf(buffer, message, args);
va_end(args);
SYSTRACE_END(module, tracepoint, message);
#else
Q_UNUSED(module)
Q_UNUSED(tracepoint)
Q_UNUSED(message)
#endif
}

void QSystrace::counter(const char *module, const char *tracepoint, const char *message, ...)
{
#if !defined(QT_BOOTSTRAPPED) && !defined(QT_NO_DEBUG) && defined(QT_USE_LIBSYSTRACE)
char buffer[1024];
va_list args;
va_start(args, message);
vsprintf(buffer, message, args);
va_end(args);
SYSTRACE_COUNTER(module, tracepoint, message);
#else
Q_UNUSED(module)
Q_UNUSED(tracepoint)
Q_UNUSED(message)
#endif
}

91 changes: 91 additions & 0 deletions src/corelib/global/qsystrace_p.h
@@ -0,0 +1,91 @@
/****************************************************************************
**
** Copyright (C) 2014 Jolla Ltd, author: <robin.burchell@jollamobile.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/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 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt 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.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#ifndef QSYSTRACE_P_H
#define QSYSTRACE_P_H

#include <qglobal.h>

//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

QT_BEGIN_NAMESPACE

namespace QSystrace
{
void Q_CORE_EXPORT begin(const char *module, const char *tracepoint, const char *message, ...);
void Q_CORE_EXPORT end(const char *module, const char *tracepoint, const char *message, ...);
void Q_CORE_EXPORT counter(const char *module, const char *tracepoint, const char *message, ...);
};

// simple RAII wrapper we can use elsewhere in the codebase. must be inside Qt
// so QT_NO_DEBUG (& our feature macro) can easily disable the functionality
// while not littering the codebase with defines
struct QSystraceEvent
{
QSystraceEvent(const char *module, const char *tracepoint)
: m_module(module)
, m_tracepoint(tracepoint)
{
QSystrace::begin(m_module, m_tracepoint, "");
}

~QSystraceEvent()
{
QSystrace::end(m_module, m_tracepoint, "");
}

private:
const char *m_module;
const char *m_tracepoint;
};

QT_END_NAMESPACE

#endif // QSYSTRACE_P_H
9 changes: 9 additions & 0 deletions src/corelib/io/qfsfileengine.cpp
Expand Up @@ -53,6 +53,8 @@
# include <private/qcore_mac_p.h>
#endif

#include <private/qsystrace_p.h>

QT_BEGIN_NAMESPACE

#ifdef Q_OS_WIN
Expand Down Expand Up @@ -420,6 +422,7 @@ bool QFSFileEngine::syncToDisk()
Q_D(QFSFileEngine);
if ((d->openMode & QIODevice::WriteOnly) == 0)
return true;
QSystraceEvent systrace("io", "QFSFileEngine::syncToDisk");
return d->nativeSyncToDisk();
}

Expand Down Expand Up @@ -568,6 +571,8 @@ qint64 QFSFileEngine::read(char *data, qint64 maxlen)
{
Q_D(QFSFileEngine);

QSystraceEvent systrace("io", "QFSFileEngine::read");

// On Windows' stdlib implementation, the results of calling fread and
// fwrite are undefined if not called either in sequence, or if preceded
// with a call to fflush().
Expand All @@ -591,6 +596,7 @@ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len)
return -1;
}

QSystraceEvent systrace("io", "QFSFileEngine::readFdFh");
qint64 readBytes = 0;
bool eof = false;

Expand Down Expand Up @@ -699,6 +705,8 @@ qint64 QFSFileEngine::write(const char *data, qint64 len)
{
Q_D(QFSFileEngine);

QSystraceEvent systrace("io", "QFSFileEngine::write");

// On Windows' stdlib implementation, the results of calling fread and
// fwrite are undefined if not called either in sequence, or if preceded
// with a call to fflush().
Expand All @@ -723,6 +731,7 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len)
}

qint64 writtenBytes = 0;
QSystraceEvent systrace("io", "QFSFileEngine::writeFdFh");

if (len) { // avoid passing nullptr to fwrite() or QT_WRITE() (UB)

Expand Down

0 comments on commit 1ca6e3c

Please sign in to comment.