[PATCH] kernelbase: Cache last used locale->sortguid mapping.
Torge Matthies
openglfreak at googlemail.com
Sun Apr 4 23:24:04 CDT 2021
get_language_sort reads from the registry, which is not particularly fast.
Staging's implementation of CompareStringEx calls this function, and if
CompareStringEx is used in a loop over many elements, it will slow down the
application by a lot (> 30 seconds vs a few hundred ms in osu!, depends
on the CPU and the number of installed beatmaps).
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50923
Signed-off-by: Torge Matthies <openglfreak at googlemail.com>
---
This could be put into the Staging patchset libs-Unicode_Collation, if deemed
not appropriate for vanilla. I could also make it cache all requested locales
in an rbtree, if desired. However most applications should only ever need one
locale.
dlls/kernelbase/locale.c | 42 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c
index c58c2cbe434..3b4191078ad 100644
--- a/dlls/kernelbase/locale.c
+++ b/dlls/kernelbase/locale.c
@@ -618,6 +618,21 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
};
static CRITICAL_SECTION locale_section = { &critsect_debug, -1, 0, 0, 0, 0 };
+static struct
+{
+ WCHAR locale[LOCALE_NAME_MAX_LENGTH]; /* The locale name */
+ const struct sortguid *guid; /* The cached associated GUID */
+} sortguid_cache;
+
+static CRITICAL_SECTION sortguid_cache_section;
+static CRITICAL_SECTION_DEBUG sortguid_cache_section_debug =
+{
+ 0, 0, &sortguid_cache_section,
+ { &sortguid_cache_section_debug.ProcessLocksList, &sortguid_cache_section_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": sortguid_cache_section") }
+};
+static CRITICAL_SECTION sortguid_cache_section = { &sortguid_cache_section_debug, -1, 0, 0, 0, 0 };
+
static void init_sortkeys( DWORD *ptr )
{
@@ -655,7 +670,7 @@ static const struct sortguid *find_sortguid( const GUID *guid )
}
-static const struct sortguid *get_language_sort( const WCHAR *locale )
+static const struct sortguid *get_language_sort_uncached( const WCHAR *locale )
{
WCHAR *p, *end, buffer[LOCALE_NAME_MAX_LENGTH], guidstr[39];
const struct sortguid *ret;
@@ -698,6 +713,31 @@ done:
}
+static const struct sortguid *get_language_sort( const WCHAR *locale )
+{
+ const struct sortguid *ret = NULL;
+
+ if (!locale) return get_language_sort_uncached( locale );
+
+ RtlEnterCriticalSection( &sortguid_cache_section );
+
+ if (sortguid_cache.guid && !wcsncmp( sortguid_cache.locale, locale, LOCALE_NAME_MAX_LENGTH ))
+ {
+ ret = sortguid_cache.guid;
+ goto done;
+ }
+
+ ret = get_language_sort_uncached( locale );
+
+ lstrcpynW( sortguid_cache.locale, locale, LOCALE_NAME_MAX_LENGTH );
+ sortguid_cache.guid = ret;
+
+done:
+ RtlLeaveCriticalSection( &sortguid_cache_section );
+ return ret;
+}
+
+
static LCID locale_to_lcid( WCHAR *win_name )
{
WCHAR *p;
--
2.31.1
More information about the wine-devel
mailing list