From 81a45e1f13fdf56129aed952a6e3479e16c14a2c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 26 Jul 2014 01:43:18 +0200 Subject: 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 --- src/corelib/tools/qtimezoneprivate_icu.cpp | 37 +++++++++++++++++------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'src/corelib/tools/qtimezoneprivate_icu.cpp') diff --git a/src/corelib/tools/qtimezoneprivate_icu.cpp b/src/corelib/tools/qtimezoneprivate_icu.cpp index 3ab42661c0..dd57464a72 100644 --- a/src/corelib/tools/qtimezoneprivate_icu.cpp +++ b/src/corelib/tools/qtimezoneprivate_icu.cpp @@ -37,6 +37,9 @@ #include #include +#include + +#include QT_BEGIN_NAMESPACE @@ -234,19 +237,21 @@ static QTimeZonePrivate::Data ucalTimeZoneTransition(UCalendar *m_ucal, #endif // U_ICU_VERSION_SHORT // Convert a uenum to a QList -static QSet uenumToIdSet(UEnumeration *uenum) +static QList uenumToIdList(UEnumeration *uenum) { - QSet set; + QList list; int32_t size = 0; UErrorCode status = U_ZERO_ERROR; // TODO Perhaps use uenum_unext instead? QByteArray result = uenum_next(uenum, &size, &status); while (U_SUCCESS(status) && !result.isEmpty()) { - set << result; + list << result; status = U_ZERO_ERROR; result = uenum_next(uenum, &size, &status); } - return set; + std::sort(list.begin(), list.end()); + list.erase(std::unique(list.begin(), list.end()), list.end()); + return list; } // Qt wrapper around ucal_getDSTSavings() @@ -453,41 +458,41 @@ QByteArray QIcuTimeZonePrivate::systemTimeZoneId() const return ucalDefaultTimeZoneId(); } -QSet QIcuTimeZonePrivate::availableTimeZoneIds() const +QList QIcuTimeZonePrivate::availableTimeZoneIds() const { UErrorCode status = U_ZERO_ERROR; UEnumeration *uenum = ucal_openTimeZones(&status); - QSet set; + QList result; if (U_SUCCESS(status)) - set = uenumToIdSet(uenum); + result = uenumToIdList(uenum); uenum_close(uenum); - return set; + return result; } -QSet QIcuTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const +QList QIcuTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const { QByteArray regionCode = QLocalePrivate::countryToCode(country).toUtf8(); UErrorCode status = U_ZERO_ERROR; UEnumeration *uenum = ucal_openCountryTimeZones(regionCode, &status); - QSet set; + QList result; if (U_SUCCESS(status)) - set = uenumToIdSet(uenum); + result = uenumToIdList(uenum); uenum_close(uenum); - return set; + return result; } -QSet QIcuTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) const +QList QIcuTimeZonePrivate::availableTimeZoneIds(int offsetFromUtc) const { // TODO Available directly in C++ api but not C api, from 4.8 onwards new filter method works #if U_ICU_VERSION_MAJOR_NUM >= 49 || (U_ICU_VERSION_MAJOR_NUM == 4 && U_ICU_VERSION_MINOR_NUM == 8) UErrorCode status = U_ZERO_ERROR; UEnumeration *uenum = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, 0, &offsetFromUtc, &status); - QSet set; + QList result; if (U_SUCCESS(status)) - set = uenumToIdSet(uenum); + result = uenumToIdList(uenum); uenum_close(uenum); - return set; + return result; #else return QTimeZonePrivate::availableTimeZoneIds(offsetFromUtc); #endif -- cgit v1.2.3