Reuse one QCollator instance for QString::localeAwareCompare

Constructing a QCollator is somewhat expensive, and made
localeAwareCompare really slow. As QCollator (at least with
the ICU implementation) is not thread safe, use one collator
per thread. This speeds up collation of a long list of strings
by a factor of 250 for the test case in the bug below.

Task-number: QTBUG-36149
Change-Id: I645cdc3546347d1dcc7a03b7563b628c7f756944
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
This commit is contained in:
Lars Knoll 2014-01-21 10:35:01 +01:00 committed by The Qt Project
parent 5b00bb39f2
commit 5279134935
2 changed files with 10 additions and 6 deletions

View File

@ -78,6 +78,7 @@
#include "qchar.cpp"
#include "qstringmatcher.cpp"
#include "qstringiterator_p.h"
#include "qthreadstorage.h"
#ifdef Q_OS_WIN
# include <qt_windows.h>
@ -5319,6 +5320,10 @@ int QString::localeAwareCompare(const QString &other) const
return localeAwareCompare_helper(constData(), length(), other.constData(), other.length());
}
#if defined(QT_USE_ICU)
Q_GLOBAL_STATIC(QThreadStorage<QCollator>, defaultCollator)
#endif
/*!
\internal
\since 4.5
@ -5362,8 +5367,9 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
CFRelease(otherString);
return result;
#elif defined(QT_USE_ICU)
QCollator collator;
return collator.compare(data1, length1, data2, length2);
if (!defaultCollator()->hasLocalData())
defaultCollator()->setLocalData(QCollator());
return defaultCollator()->localData().compare(data1, length1, data2, length2);
#elif defined(Q_OS_UNIX)
// declared in <string.h>
int delta = strcoll(toLocal8Bit_helper(data1, length1).constData(), toLocal8Bit_helper(data2, length2).constData());

View File

@ -4876,10 +4876,8 @@ void tst_QString::localeAwareCompare()
DWORD oldLcid = GetUserDefaultLCID();
SetUserDefaultLCID(locale);
QCOMPARE(locale, GetUserDefaultLCID());
#elif defined (Q_OS_MAC)
QSKIP("Setting the locale is not supported on OS X (you can set the C locale, but that won't affect CFStringCompare which is used to compare strings)");
#elif defined(QT_USE_ICU)
QLocale::setDefault(QLocale(locale));
#elif defined (Q_OS_MAC) || defined(QT_USE_ICU)
QSKIP("Setting the locale is not supported on OS X or ICU (you can set the C locale, but that won't affect localeAwareCompare)");
#else
if (!locale.isEmpty()) {
const char *newLocale = setlocale(LC_ALL, locale.toLatin1());