path: root/src/corelib/time/qtimezoneprivate_p.h
diff options
authorRobin Burchell <>2019-05-03 20:02:10 +0200
committerEdward Welbourne <>2020-03-20 16:58:09 +0200
commit2af04860f6536bbbf82ee21d6aa95ca33a60fbf5 (patch)
treeb5388ea57e36cccc6a2f50acd5013681bd6b019f /src/corelib/time/qtimezoneprivate_p.h
parentd535dfea1f2d801268396f328c5c99968ff164ec (diff)
qtimezoneprivate_tz: Apply a cache over the top of timezone data
Constantly re-reading the timezone information only to be told the exact same thing is wildly expensive, which can hurt in operations that cause a lot of QTimeZone creation, for example, V4's DateObject - which creates them a lot (in DaylightSavingTA). This performance problem was identified when I noticed that a QDateTime binding updated once per frame was causing >100% CPU usage (on a desktop!) thanks to a QtQuickControls 1 Calendar (which has a number of bindings to the date's properties like getMonth() and so on). The newly added tst_QTimeZone::systemTimeZone benchmark gets a ~90% decrease in instruction count: --- before +++ after PASS : tst_QTimeZone::systemTimeZone() RESULT : tst_QTimeZone::systemTimeZone(): - 0.024 msecs per iteration (total: 51, iterations: 2048) + 0.0036 msecs per iteration (total: 59, iterations: 16384) Also impacted (over in QDateTime) is tst_QDateTime::setMSecsSinceEpochTz(). The results here are - on the surface - less impressive (~0.17% drop), however, it isn't even creating QTimeZone on a hot path to begin with, so a large drop would have been a surprise. Added several further benchmarks to cover non-system zones and traverse transitions. Done-With: Edward Welbourne <> Task-number: QTBUG-75585 Change-Id: I044a84fc2d3a2dc965f63cd3a3299fc509750bf7 Reviewed-by: Ulf Hermann <> Reviewed-by: Simon Hausmann <>
Diffstat (limited to 'src/corelib/time/qtimezoneprivate_p.h')
1 files changed, 12 insertions, 4 deletions
diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
index 5f6491ef81..c3e9064b8c 100644
--- a/src/corelib/time/qtimezoneprivate_p.h
+++ b/src/corelib/time/qtimezoneprivate_p.h
@@ -287,6 +287,16 @@ Q_DECL_CONSTEXPR inline bool operator==(const QTzTransitionRule &lhs, const QTzT
Q_DECL_CONSTEXPR inline bool operator!=(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
{ return !operator==(lhs, rhs); }
+// These are stored separately from QTzTimeZonePrivate so that they can be
+// cached, avoiding the need to re-parse them from disk constantly.
+struct QTzTimeZoneCacheEntry
+ QVector<QTzTransitionTime> m_tranTimes;
+ QVector<QTzTransitionRule> m_tranRules;
+ QList<QByteArray> m_abbreviations;
+ QByteArray m_posixRule;
class Q_AUTOTEST_EXPORT QTzTimeZonePrivate final : public QTimeZonePrivate
QTzTimeZonePrivate(const QTzTimeZonePrivate &) = default;
@@ -334,13 +344,11 @@ private:
QVector<QTimeZonePrivate::Data> getPosixTransitions(qint64 msNear) const;
Data dataForTzTransition(QTzTransitionTime tran) const;
- QVector<QTzTransitionTime> m_tranTimes;
- QVector<QTzTransitionRule> m_tranRules;
- QList<QByteArray> m_abbreviations;
#if QT_CONFIG(icu)
mutable QSharedDataPointer<QTimeZonePrivate> m_icu;
- QByteArray m_posixRule;
+ QTzTimeZoneCacheEntry cached_data;
+ QVector<QTzTransitionTime> tranCache() const { return cached_data.m_tranTimes; }
#endif // Q_OS_UNIX