diff options
-rw-r--r-- | src/libs/utils/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/libs/utils/qtcassert.cpp | 28 | ||||
-rw-r--r-- | src/libs/utils/qtcassert.h | 20 | ||||
-rw-r--r-- | src/libs/utils/scopedtimer.cpp | 64 | ||||
-rw-r--r-- | src/libs/utils/scopedtimer.h | 38 | ||||
-rw-r--r-- | src/libs/utils/utils.qbs | 2 |
6 files changed, 105 insertions, 48 deletions
diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt index e3bbfcf7a9..f05398094a 100644 --- a/src/libs/utils/CMakeLists.txt +++ b/src/libs/utils/CMakeLists.txt @@ -147,6 +147,7 @@ add_qtc_library(Utils runextensions.cpp runextensions.h savefile.cpp savefile.h scopedswap.h + scopedtimer.cpp scopedtimer.h searchresultitem.cpp searchresultitem.h set_algorithm.h settingsaccessor.cpp settingsaccessor.h diff --git a/src/libs/utils/qtcassert.cpp b/src/libs/utils/qtcassert.cpp index 019c223ef7..78baa41a4a 100644 --- a/src/libs/utils/qtcassert.cpp +++ b/src/libs/utils/qtcassert.cpp @@ -8,8 +8,6 @@ #include <QMutex> #include <QTime> -#include <chrono> - #if defined(Q_OS_UNIX) #include <stdio.h> #include <signal.h> @@ -132,30 +130,4 @@ void writeAssertLocation(const char *msg) dumpBacktrace(maxdepth); } -using namespace std::chrono; - -class ScopedTimerPrivate -{ -public: - const char *m_fileName = nullptr; - const int m_line = 0; - const time_point<system_clock, nanoseconds> m_start = system_clock::now(); -}; - -ScopedTimer::ScopedTimer(const char *fileName, int line) - : d(new ScopedTimerPrivate{fileName, line}) -{ - const QByteArray time = QTime::currentTime().toString(Qt::ISODateWithMs).toLatin1(); - qDebug("SCOPED TIMER [%s] in %s:%d started", time.data(), d->m_fileName, d->m_line); -} - -ScopedTimer::~ScopedTimer() -{ - const auto end = system_clock::now(); - const auto elapsed = duration_cast<milliseconds>(end - d->m_start); - const QByteArray time = QTime::currentTime().toString(Qt::ISODateWithMs).toLatin1(); - qDebug("SCOPED TIMER [%s] in %s:%d stopped with timeout: %ldms", - time.data(), d->m_fileName, d->m_line, elapsed.count()); -} - } // namespace Utils diff --git a/src/libs/utils/qtcassert.h b/src/libs/utils/qtcassert.h index aab7ab93d0..8f6b2ec5b8 100644 --- a/src/libs/utils/qtcassert.h +++ b/src/libs/utils/qtcassert.h @@ -5,25 +5,9 @@ #include "utils_global.h" -#include <memory> - namespace Utils { - QTCREATOR_UTILS_EXPORT void writeAssertLocation(const char *msg); QTCREATOR_UTILS_EXPORT void dumpBacktrace(int maxdepth); - -class ScopedTimerPrivate; - -class QTCREATOR_UTILS_EXPORT ScopedTimer -{ -public: - ScopedTimer(const char *fileName, int line); - ~ScopedTimer(); - -private: - std::unique_ptr<ScopedTimerPrivate> d; -}; - } // Utils #define QTC_ASSERT_STRINGIFY_HELPER(x) #x @@ -37,7 +21,3 @@ private: #define QTC_ASSERT(cond, action) if (Q_LIKELY(cond)) {} else { QTC_ASSERT_STRING(#cond); action; } do {} while (0) #define QTC_CHECK(cond) if (Q_LIKELY(cond)) {} else { QTC_ASSERT_STRING(#cond); } do {} while (0) #define QTC_GUARD(cond) ((Q_LIKELY(cond)) ? true : (QTC_ASSERT_STRING(#cond), false)) - -#define QTC_CONCAT_HELPER(x, y) x ## y -#define QTC_CONCAT(x, y) QTC_CONCAT_HELPER(x, y) -#define QTC_SCOPED_TIMER() ::Utils::ScopedTimer QTC_CONCAT(_qtc_scoped_timer_, __LINE__)(__FILE__, __LINE__) diff --git a/src/libs/utils/scopedtimer.cpp b/src/libs/utils/scopedtimer.cpp new file mode 100644 index 0000000000..97b8beffda --- /dev/null +++ b/src/libs/utils/scopedtimer.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "scopedtimer.h" + +#include <QByteArray> +#include <QDebug> +#include <QTime> + +#include <chrono> + +namespace Utils { + +static QString currentTime() { return QTime::currentTime().toString(Qt::ISODateWithMs); } + +using namespace std::chrono; + +class ScopedTimerPrivate +{ +public: + const char *m_fileName = nullptr; + const int m_line = 0; + std::atomic<int64_t> *m_cumulative = nullptr; + const time_point<system_clock, nanoseconds> m_start = system_clock::now(); +}; + +static const char s_scoped[] = "SCOPED TIMER"; +static const char s_scopedCumulative[] = "STATIC SCOPED TIMER"; + +ScopedTimer::ScopedTimer(const char *fileName, int line, std::atomic<int64_t> *cumulative) + : d(new ScopedTimerPrivate{fileName, line, cumulative}) +{ + if (d->m_cumulative) + return; + qDebug().noquote().nospace() << s_scoped << " [" << currentTime() << "] in " << d->m_fileName + << ':' << d->m_line << " started"; +} + +static int64_t toMs(int64_t ns) { return ns / 1000000; } + +ScopedTimer::~ScopedTimer() +{ + const auto elapsed = duration_cast<nanoseconds>(system_clock::now() - d->m_start); + QString suffix; + if (d->m_cumulative) { + const int64_t nsOld = d->m_cumulative->fetch_add(elapsed.count()); + const int64_t msOld = toMs(nsOld); + const int64_t nsNew = nsOld + elapsed.count(); + const int64_t msNew = toMs(nsNew); + // Always report the first hit, and later, as not to clog the debug output, + // only at 10ms resolution. + if (nsOld != 0 && msOld / 10 == msNew / 10) + return; + + suffix = " cumulative timeout: " + QString::number(msNew) + "ms"; + } else { + suffix = " stopped with timeout: " + QString::number(toMs(elapsed.count())) + "ms"; + } + const char *header = d->m_cumulative ? s_scopedCumulative : s_scoped; + qDebug().noquote().nospace() << header << " [" << currentTime() << "] in " << d->m_fileName + << ':' << d->m_line << suffix; +} + +} // namespace Utils diff --git a/src/libs/utils/scopedtimer.h b/src/libs/utils/scopedtimer.h new file mode 100644 index 0000000000..e6ec42e6f4 --- /dev/null +++ b/src/libs/utils/scopedtimer.h @@ -0,0 +1,38 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "utils_global.h" + +#include <atomic> +#include <memory> + +namespace Utils { + +class ScopedTimerPrivate; + +class QTCREATOR_UTILS_EXPORT ScopedTimer +{ +public: + ScopedTimer(const char *fileName, int line, std::atomic<int64_t> *cumulative = nullptr); + ~ScopedTimer(); + +private: + std::unique_ptr<ScopedTimerPrivate> d; +}; + +} // Utils + +#define QTC_CONCAT_HELPER(x, y) x ## y +#define QTC_CONCAT(x, y) QTC_CONCAT_HELPER(x, y) +#define QTC_SCOPED_TIMER() ::Utils::ScopedTimer QTC_CONCAT(_qtc_scoped_timer_, __LINE__)\ +(__FILE__, __LINE__) + +// The macro below expands as follows (in one line): +// static std::atomic<int64_t> _qtc_static_scoped_timer___LINE__ = 0; +// ScopedTimer _qtc_scoped_timer___LINE__(__FILE__, __LINE__, &_qtc_static_scoped_timer___LINE__) +#define QTC_STATIC_SCOPED_TIMER() static std::atomic<int64_t> \ +QTC_CONCAT(_qtc_static_scoped_timer_, __LINE__) = 0; \ +::Utils::ScopedTimer QTC_CONCAT(_qtc_scoped_timer_, __LINE__)\ +(__FILE__, __LINE__, &QTC_CONCAT(_qtc_static_scoped_timer_, __LINE__)) diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index fa766b8bc4..f1940a053d 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -275,6 +275,8 @@ Project { "savefile.cpp", "savefile.h", "scopedswap.h", + "scopedtimer.cpp", + "scopedtimer.h", "searchresultitem.cpp", "searchresultitem.h", "set_algorithm.h", |