summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPasi Keränen <pasi.keranen@qt.io>2018-10-31 14:43:14 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2018-11-13 12:33:03 +0000
commitdd682ac0c58cf0298d565cb8d567de6a63917241 (patch)
treeae8cf4a7d1bd5185a3f0ae7f5bcf77213a40a953
parent6f2129c53b20f47e52558a511b2263d2e1b9c26f (diff)
macOS: Implement CPU usage profiler reporting
Task-number: QT3DS-2586 Change-Id: Icc9017acf9222853f6345612906288cf4fd79348 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
-rw-r--r--src/runtime/q3dsprofiler.cpp91
-rw-r--r--src/runtime/q3dsprofiler_p.h12
-rw-r--r--src/runtime/q3dsprofilerhelper_mac.mm48
-rw-r--r--src/runtime/q3dsprofilerhelper_mac_p.h64
-rw-r--r--src/runtime/runtime.pro8
5 files changed, 218 insertions, 5 deletions
diff --git a/src/runtime/q3dsprofiler.cpp b/src/runtime/q3dsprofiler.cpp
index 8303498..727229a 100644
--- a/src/runtime/q3dsprofiler.cpp
+++ b/src/runtime/q3dsprofiler.cpp
@@ -45,6 +45,7 @@
#ifdef Q_OS_MACOS
#include <mach/mach_types.h>
#include <mach/mach.h>
+#include <sys/sysctl.h>
#endif
QT_BEGIN_NAMESPACE
@@ -263,8 +264,6 @@ float Q3DSProfiler::cpuLoadForCurrentProcess()
m_lastUserTimeSys = userTimeSys;
m_lastKernelTimeProc = kernelTimeProc;
m_lastUserTimeProc = userTimeProc;
-
- return m_lastCpuLoad;
#elif defined(Q_OS_LINUX)
if (!m_numCpus) {
QFile f(QLatin1String("/proc/cpuinfo"));
@@ -291,10 +290,81 @@ float Q3DSProfiler::cpuLoadForCurrentProcess()
m_lastTimestamp = timestamp;
m_lastKernel = processTimes.tms_stime;
m_lastUser = processTimes.tms_utime;
- return m_lastCpuLoad;
-#else
- return m_lastCpuLoad;
+#elif defined(Q_OS_MACOS)
+ // Get thread times
+ mach_port_t task = mach_task_self();
+ task_thread_times_info threadTimes = {};
+ mach_msg_type_number_t outCount = TASK_THREAD_TIMES_INFO_COUNT;
+
+ kern_return_t retVal = task_info(task, TASK_THREAD_TIMES_INFO,
+ task_info_t(&threadTimes), &outCount);
+ if (retVal != KERN_SUCCESS)
+ return m_lastCpuLoad;
+
+ // Get task info
+ mach_task_basic_info_data_t taskInfo = {};
+ outCount = MACH_TASK_BASIC_INFO_COUNT;
+ retVal = task_info(task, MACH_TASK_BASIC_INFO,
+ task_info_t(&taskInfo), &outCount);
+
+ if (retVal != KERN_SUCCESS)
+ return m_lastCpuLoad;
+
+ struct timeval userTimeVal, systemTimeVal, totalTimeVal;
+
+ // Thread info contains alive time
+ userTimeVal.tv_sec = threadTimes.user_time.seconds;
+ userTimeVal.tv_usec = threadTimes.user_time.microseconds;
+ systemTimeVal.tv_sec = threadTimes.system_time.seconds;
+ systemTimeVal.tv_usec = threadTimes.system_time.microseconds;
+
+ // Add user time and system time to total time
+ timeradd(&userTimeVal, &systemTimeVal, &totalTimeVal);
+
+ // Task info has terminated time
+ userTimeVal.tv_sec = taskInfo.user_time.seconds;
+ userTimeVal.tv_usec = taskInfo.user_time.microseconds;
+ systemTimeVal.tv_sec = taskInfo.system_time.seconds;
+ systemTimeVal.tv_usec = taskInfo.system_time.microseconds;
+
+ // Add user time and system time to total time
+ timeradd(&userTimeVal, &totalTimeVal, &totalTimeVal);
+ timeradd(&systemTimeVal, &totalTimeVal, &totalTimeVal);
+
+ // Get current time
+ struct timeval now;
+ int error = gettimeofday(&now, nullptr);
+ if (error)
+ return m_lastCpuLoad;
+
+ // Convert everything to microseconds
+ qint64 timestamp = timeValToMicroseconds(now);
+ qint64 totalTaskTime = timeValToMicroseconds(totalTimeVal);
+
+ // On first execution just store the current values
+ if (m_lastTimestamp == 0) {
+ m_lastTimestamp = timestamp;
+ m_lastTaskTime = totalTaskTime;
+ return m_lastCpuLoad;
+ }
+
+ // Calculate percentage of CPU time this task used over delta time
+ qint64 taskDeltaTime = totalTaskTime - m_lastTaskTime;
+ qint64 totalDeltaTime = timestamp - m_lastTimestamp;
+
+ if (totalDeltaTime == 0)
+ return m_lastCpuLoad;
+
+ m_lastTimestamp = timestamp;
+ m_lastTaskTime = totalTaskTime;
+
+ m_lastCpuLoad = (taskDeltaTime * 100.f)
+ / float(totalDeltaTime)
+ / float(m_macOSProfiler.numActiveProcessors());
+
#endif
+
+ return m_lastCpuLoad;
}
QPair<qint64, qint64> Q3DSProfiler::memUsageForCurrentProcess()
@@ -358,4 +428,15 @@ QPair<qint64, qint64> Q3DSProfiler::memUsageForCurrentProcess()
return m_lastMemUsage;
}
+#if defined(Q_OS_MACOS)
+qint64 Q3DSProfiler::timeValToMicroseconds(const struct timeval& timeVal)
+{
+ static const int microsecondsPerSecond = 1000000;
+ qint64 retVal = timeVal.tv_sec;
+ retVal *= microsecondsPerSecond;
+ retVal += timeVal.tv_usec;
+ return retVal;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/runtime/q3dsprofiler_p.h b/src/runtime/q3dsprofiler_p.h
index 732a5fb..7a65f45 100644
--- a/src/runtime/q3dsprofiler_p.h
+++ b/src/runtime/q3dsprofiler_p.h
@@ -48,6 +48,10 @@
#include <QHash>
#include <QSet>
+#if defined(Q_OS_MACOS)
+#include "q3dsprofilerhelper_mac_p.h"
+#endif
+
QT_BEGIN_NAMESPACE
class Q3DSSceneManager;
@@ -156,6 +160,10 @@ public:
QPair<qint64, qint64> memUsageForCurrentProcess();
private:
+#if defined(Q_OS_MACOS)
+ qint64 timeValToMicroseconds(const struct timeval& timeVal);
+#endif
+
bool m_enabled = false; // disabled by default, profiling is opt-in
QVector<FrameData> m_frameData;
QMultiMap<ObjectType, ObjectData> m_objectData;
@@ -190,6 +198,10 @@ private:
qint64 m_lastTimestamp = 0;
qint64 m_lastKernel = 0;
qint64 m_lastUser = 0;
+#elif defined(Q_OS_MACOS)
+ qint64 m_lastTimestamp = 0;
+ qint64 m_lastTaskTime = 0;
+ Q3DSProfilerHelperMacOS m_macOSProfiler;
#endif
};
diff --git a/src/runtime/q3dsprofilerhelper_mac.mm b/src/runtime/q3dsprofilerhelper_mac.mm
new file mode 100644
index 0000000..c09bebd
--- /dev/null
+++ b/src/runtime/q3dsprofilerhelper_mac.mm
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** 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$
+**
+****************************************************************************/
+#import <Foundation/Foundation.h>
+
+#include "q3dsprofilerhelper_mac_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q3DSProfilerHelperMacOS::Q3DSProfilerHelperMacOS()
+{
+}
+
+Q3DSProfilerHelperMacOS::~Q3DSProfilerHelperMacOS()
+{
+}
+
+quint32 Q3DSProfilerHelperMacOS::numActiveProcessors()
+{
+ return quint32([[NSProcessInfo processInfo] activeProcessorCount]);
+}
+
+QT_END_NAMESPACE
diff --git a/src/runtime/q3dsprofilerhelper_mac_p.h b/src/runtime/q3dsprofilerhelper_mac_p.h
new file mode 100644
index 0000000..a5bfa57
--- /dev/null
+++ b/src/runtime/q3dsprofilerhelper_mac_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** 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$
+**
+****************************************************************************/
+
+#ifndef Q3DSPROFILERMACOS_P_H
+#define Q3DSPROFILERMACOS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QVector>
+#include <QElapsedTimer>
+#include <QMultiMap>
+#include <QObject>
+#include <QHash>
+#include <QSet>
+
+QT_BEGIN_NAMESPACE
+
+class Q3DSProfilerHelperMacOS
+{
+public:
+ Q3DSProfilerHelperMacOS();
+ ~Q3DSProfilerHelperMacOS();
+
+ quint32 numActiveProcessors();
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3DSPROFILERMACOS_P_H
diff --git a/src/runtime/runtime.pro b/src/runtime/runtime.pro
index 3bfc422..98bb424 100644
--- a/src/runtime/runtime.pro
+++ b/src/runtime/runtime.pro
@@ -81,6 +81,14 @@ HEADERS += \
q3dsviewportsettings_p.h \
q3dsscenepicker_p.h
+macos: {
+LIBS += -framework Foundation
+OBJECTIVE_SOURCES += \
+ q3dsprofilerhelper_mac.mm
+HEADERS += \
+ q3dsprofilerhelper_mac_p.h
+}
+
qtHaveModule(widgets) {
QT += widgets
SOURCES += \