diff options
author | Jarek Kobus <jaroslaw.kobus@qt.io> | 2023-05-02 19:47:49 +0200 |
---|---|---|
committer | Jarek Kobus <jaroslaw.kobus@qt.io> | 2023-05-04 09:44:16 +0000 |
commit | a059f87754c68aec9095b092f23a8cab325a5dfc (patch) | |
tree | f0543a624a8c3125c9e16a723744f2e517e7f9f0 /src/shared | |
parent | de247bff2b15a9eb1eaece9077abecd4369176ba (diff) |
QtSingleApplication: Introduce QTC_FREEZE_DETECTOR env var
This may help with tracking the freezes in main thread.
By default, when QTC_FREEZE_DETECTOR is set, it detects
freezes above the 100 ms and prints the receiver object
and event type that triggered the freeze.
Change the default 100 ms threshold by setting the
QTC_FREEZE_DETECTOR to some different numeric value.
Change-Id: Ifb68c7648c09a5329f1f2aa39cd7e29e69a76052
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/qtsingleapplication/qtsingleapplication.cpp | 68 | ||||
-rw-r--r-- | src/shared/qtsingleapplication/qtsingleapplication.h | 3 |
2 files changed, 69 insertions, 2 deletions
diff --git a/src/shared/qtsingleapplication/qtsingleapplication.cpp b/src/shared/qtsingleapplication/qtsingleapplication.cpp index 4a79f4eee6b..0f8fa8b6d13 100644 --- a/src/shared/qtsingleapplication/qtsingleapplication.cpp +++ b/src/shared/qtsingleapplication/qtsingleapplication.cpp @@ -148,13 +148,11 @@ void QtSingleApplication::setActivationWindow(QWidget *aw, bool activateOnMessag disconnect(pidPeer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow); } - QWidget* QtSingleApplication::activationWindow() const { return actWin; } - void QtSingleApplication::activateWindow() { if (actWin) { @@ -164,4 +162,70 @@ void QtSingleApplication::activateWindow() } } +static const char s_freezeDetector[] = "QTC_FREEZE_DETECTOR"; + +static std::optional<int> isUsingFreezeDetector() +{ + if (!qEnvironmentVariableIsSet(s_freezeDetector)) + return {}; + + bool ok = false; + const int threshold = qEnvironmentVariableIntValue(s_freezeDetector, &ok); + return ok ? threshold : 100; // default value 100ms +} + +class ApplicationWithFreezerDetector : public SharedTools::QtSingleApplication +{ +public: + ApplicationWithFreezerDetector(const QString &id, int &argc, char **argv) + : QtSingleApplication(id, argc, argv) + , m_align(21, QChar::Space) + {} + void setFreezeTreshold(std::chrono::milliseconds freezeAbove) { m_threshold = freezeAbove; } + + bool notify(QObject *receiver, QEvent *event) override { + using namespace std::chrono; + const auto start = system_clock::now(); + const QPointer<QObject> p(receiver); + const QString className = QLatin1String(receiver->metaObject()->className()); + const QString name = receiver->objectName(); + + const bool ret = QtSingleApplication::notify(receiver, event); + + const auto end = system_clock::now(); + const auto freeze = duration_cast<milliseconds>(end - start); + if (freeze > m_threshold) { + const QString time = QTime::currentTime().toString(Qt::ISODateWithMs); + qDebug().noquote() << QString("FREEZE [%1]").arg(time) + << "of" << freeze.count() << "ms, on:" << event; + const QString receiverMessage = name.isEmpty() + ? QString("receiver class: %1").arg(className) + : QString("receiver class: %1, object name: %2").arg(className, name); + qDebug().noquote() << m_align << receiverMessage; + if (!p) + qDebug().noquote() << m_align << "THE RECEIVER GOT DELETED inside the event filter!"; + } + return ret; + } + +private: + const QString m_align; + std::chrono::milliseconds m_threshold = std::chrono::milliseconds(100); +}; + +QtSingleApplication *createApplication(const QString &id, int &argc, char **argv) +{ + const std::optional<int> freezeDetector = isUsingFreezeDetector(); + if (!freezeDetector) + return new SharedTools::QtSingleApplication(id, argc, argv); + + qDebug() << s_freezeDetector << "evn var is set. The freezes of main thread, above" + << *freezeDetector << "ms, will be reported."; + qDebug() << "Change the freeze detection threshold by setting the" << s_freezeDetector + << "env var to a different numeric value (in ms)."; + ApplicationWithFreezerDetector *app = new ApplicationWithFreezerDetector(id, argc, argv); + app->setFreezeTreshold(std::chrono::milliseconds(*freezeDetector)); + return app; +} + } // namespace SharedTools diff --git a/src/shared/qtsingleapplication/qtsingleapplication.h b/src/shared/qtsingleapplication/qtsingleapplication.h index 2adbe185426..fdc485bd98c 100644 --- a/src/shared/qtsingleapplication/qtsingleapplication.h +++ b/src/shared/qtsingleapplication/qtsingleapplication.h @@ -46,4 +46,7 @@ private: bool block; }; +// Instantiates Freeze Detector when QTC_FREEZE_DETECTOR env var is set. +QtSingleApplication *createApplication(const QString &id, int &argc, char **argv); + } // namespace SharedTools |