diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2014-07-26 01:43:18 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2015-02-17 15:02:45 +0000 |
commit | 81a45e1f13fdf56129aed952a6e3479e16c14a2c (patch) | |
tree | ac8bbaa74a61735e98cce177791b034ac1bd38fd /src/corelib/tools/qtimezoneprivate.cpp | |
parent | b63c721a0e8d637dd2a34cc5d335195349443366 (diff) |
QTimeZone: don't use QSet, use sorted QList
QSet, as a node-based container, requires one memory allocation per element
inserted. QList, as a contiguous-memory container (at least in the case of
a QByteArray payload), requires one memory allocation per container.
The higher lookup speed might still speak for using QSet, but there are only
two uses of the sets:
1. Checking for existence (or lack thereof) of timezone names.
For this, first generating a container full of data just to check for
existence of one item of data is extremely wasteful. The QTZPrivate
API should be extended to allow said lookup to be performed on the
native data store instead.
That leaves
2. Returning a sorted(!) list(!) from the public QTimeZone API.
There is no reason why, during the construction of those sorted
lists, the data should be held in a set. Instead, the well-known
technique of first cramming everything into a result container,
which is subsequently sorted and has its duplicates removed,
can be used here.
Saves more than 8K of text size on AMD64 stripped release builds.
Change-Id: I71c2298e94e02d55b0c9fb6f7ebeaed79a1fe2db
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools/qtimezoneprivate.cpp')
-rw-r--r-- | src/corelib/tools/qtimezoneprivate.cpp | 74 |
1 files changed, 42 insertions, 32 deletions
diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp index 337f0e6bfb..164db5ed0c 100644 --- a/src/corelib/tools/qtimezoneprivate.cpp +++ b/src/corelib/tools/qtimezoneprivate.cpp @@ -39,6 +39,8 @@ #include <qdatastream.h> #include <qdebug.h> +#include <algorithm> + QT_BEGIN_NAMESPACE enum { @@ -341,36 +343,38 @@ QByteArray QTimeZonePrivate::systemTimeZoneId() const return QByteArray(); } -QSet<QByteArray> QTimeZonePrivate::availableTimeZoneIds() const +QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds() const { - return QSet<QByteArray>(); + return QList<QByteArray>(); } -QSet<QByteArray> QTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const +QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const { // Default fall-back mode, use the zoneTable to find Region of know Zones - QSet<QByteArray> regionSet; + QList<QByteArray> regions; // First get all Zones in the Zones table belonging to the Region for (int i = 0; i < zoneDataTableSize; ++i) { if (zoneData(i)->country == country) - regionSet += ianaId(zoneData(i)).split(' ').toSet(); + regions += ianaId(zoneData(i)).split(' '); } - // Then select just those that are available - QSet<QByteArray> set; - foreach (const QByteArray &ianaId, availableTimeZoneIds()) { - if (regionSet.contains(ianaId)) - set << ianaId; - } + std::sort(regions.begin(), regions.end()); + regions.erase(std::unique(regions.begin(), regions.end()), regions.end()); - return set; + // Then select just those that are available + const QList<QByteArray> all = availableTimeZoneIds(); + QList<QByteArray> result; + result.reserve(qMin(all.size(), regions.size())); + std::set_intersection(all.begin(), all.end(), regions.cbegin(), regions.cend(), + std::back_inserter(result)); + return result; } -QSet<QByteArray> QTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) const +QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) const { // Default fall-back mode, use the zoneTable to find Offset of know Zones - QSet<QByteArray> offsetSet; + QList<QByteArray> offsets; // First get all Zones in the table using the Offset for (int i = 0; i < windowsDataTableSize; ++i) { const QWindowsData *winData = windowsData(i); @@ -378,19 +382,21 @@ QSet<QByteArray> QTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) const for (int j = 0; j < zoneDataTableSize; ++j) { const QZoneData *data = zoneData(j); if (data->windowsIdKey == winData->windowsIdKey) - offsetSet += ianaId(data).split(' ').toSet(); + offsets += ianaId(data).split(' '); } } } - // Then select just those that are available - QSet<QByteArray> set; - foreach (const QByteArray &ianaId, availableTimeZoneIds()) { - if (offsetSet.contains(ianaId)) - set << ianaId; - } + std::sort(offsets.begin(), offsets.end()); + offsets.erase(std::unique(offsets.begin(), offsets.end()), offsets.end()); - return set; + // Then select just those that are available + const QList<QByteArray> all = availableTimeZoneIds(); + QList<QByteArray> result; + result.reserve(qMin(all.size(), offsets.size())); + std::set_intersection(all.begin(), all.end(), offsets.cbegin(), offsets.cend(), + std::back_inserter(result)); + return result; } #ifndef QT_NO_DATASTREAM @@ -682,31 +688,35 @@ QByteArray QUtcTimeZonePrivate::systemTimeZoneId() const return utcQByteArray(); } -QSet<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds() const +QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds() const { - QSet<QByteArray> set; + QList<QByteArray> result; for (int i = 0; i < utcDataTableSize; ++i) - set << utcId(utcData(i)); - return set; + result << utcId(utcData(i)); + std::sort(result.begin(), result.end()); // ### or already sorted?? + // ### assuming no duplicates + return result; } -QSet<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const +QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const { // If AnyCountry then is request for all non-region offset codes if (country == QLocale::AnyCountry) return availableTimeZoneIds(); - return QSet<QByteArray>(); + return QList<QByteArray>(); } -QSet<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(qint32 offsetSeconds) const +QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(qint32 offsetSeconds) const { - QSet<QByteArray> set; + QList<QByteArray> result; for (int i = 0; i < utcDataTableSize; ++i) { const QUtcData *data = utcData(i); if (data->offsetFromUtc == offsetSeconds) - set << utcId(data); + result << utcId(data); } - return set; + std::sort(result.begin(), result.end()); // ### or already sorted?? + // ### assuming no duplicates + return result; } #ifndef QT_NO_DATASTREAM |