[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Call to locale_charset within wcwidth
From: |
Daiki Ueno |
Subject: |
Re: Call to locale_charset within wcwidth |
Date: |
Tue, 27 Jan 2015 15:14:36 +0900 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux) |
Daiki Ueno <address@hidden> writes:
> Gavin Smith <address@hidden> writes:
>
>> It appears you can have thread-local variables with gcc using
>> "__thread", for example, "static __thread const char *encoding". (I
>> don't know about other compilers.) Would something like this work? As
>> well as threads, updating the cached encoding when the encoding
>> changes would be a problem.
>
> If the overhead of a single setlocale call is acceptable, how about
> using the return address of setlocale as a cache key and bypass the
> later part?
>
> Something like:
I took a bit more serious attempt to this, and ended up with the
attached patch. Using the following test program:
#include "config.h"
#include "localcharset.h"
#include <stdio.h>
int main (void)
{
int i;
printf ("%s\n", locale_charset ());
for (i = 0; i < 1000000; i++)
locale_charset ();
printf ("%s\n", locale_charset ());
return 0;
}
it resulted in a significant performance improvement, although my test
environment is on Wine (I guess Eli could do testing under a more
practical setting).
Before:
CP1252
CP1252
real 0m3.048s
user 0m0.100s
sys 0m0.070s
After:
CP1252
CP1252
real 0m0.314s
user 0m0.120s
sys 0m0.050s
Regards,
--
Daiki Ueno
>From 6670a7c43dce4c7dc3c812af7e2bb493a0d3dc7c Mon Sep 17 00:00:00 2001
From: Daiki Ueno <address@hidden>
Date: Tue, 27 Jan 2015 14:56:30 +0900
Subject: [PATCH] localcharset: optimize on Windows
* lib/localcharset.c (locale_charset) [WINDOWS_NATIVE]: Bypass
GetACP and alias resolution by using thread-local cache.
Problem reported by Gavin Smith in:
https://lists.gnu.org/archive/html/bug-gnulib/2015-01/msg00040.html
---
ChangeLog | 8 ++++++++
lib/localcharset.c | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/ChangeLog b/ChangeLog
index a57bdd0..162e534 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2015-01-27 Daiki Ueno <address@hidden>
+
+ localcharset: optimize on Windows
+ * lib/localcharset.c (locale_charset) [WINDOWS_NATIVE]: Bypass
+ GetACP and alias resolution by using thread-local cache.
+ Problem reported by Gavin Smith in:
+ https://lists.gnu.org/archive/html/bug-gnulib/2015-01/msg00040.html
+
2015-01-24 Daiki Ueno <address@hidden>
unictype: avoid undefined left-shift behavior
diff --git a/lib/localcharset.c b/lib/localcharset.c
index b4af28c..2eb4a5c 100644
--- a/lib/localcharset.c
+++ b/lib/localcharset.c
@@ -491,6 +491,9 @@ locale_charset (void)
#elif defined WINDOWS_NATIVE
static char buf[2 + 10 + 1];
+ static DWORD tls_locale_index;
+ static DWORD tls_codeset_index;
+ static int tls_initialized;
/* The Windows API has a function returning the locale's codepage as
a number, but the value doesn't change according to what the
@@ -506,6 +509,28 @@ locale_charset (void)
if (strchr (current_locale, ';'))
current_locale = setlocale (LC_CTYPE, NULL);
+ /* The 'GetACP' call and alias resolution below are costly. Bypass
+ the rest of operations from the next call of this function, using
+ per-thread cache. */
+ if (!tls_initialized)
+ {
+ tls_locale_index = TlsAlloc ();
+ tls_codeset_index = TlsAlloc ();
+ tls_initialized = 1;
+ }
+
+ if (tls_locale_index != TLS_OUT_OF_INDEXES
+ && tls_codeset_index != TLS_OUT_OF_INDEXES)
+ {
+ const char *tls_locale = TlsGetValue (tls_locale_index);
+ if (current_locale == tls_locale)
+ {
+ const char *tls_codeset = TlsGetValue (tls_codeset_index);
+ if (tls_codeset != NULL)
+ return tls_codeset;
+ }
+ }
+
pdot = strrchr (current_locale, '.');
if (pdot)
sprintf (buf, "CP%s", pdot + 1);
@@ -609,5 +634,14 @@ locale_charset (void)
codeset = "ASCII";
#endif
+#ifdef WINDOWS_NATIVE
+ if (tls_locale_index != TLS_OUT_OF_INDEXES
+ && tls_codeset_index != TLS_OUT_OF_INDEXES)
+ {
+ TlsSetValue (tls_locale_index, (LPVOID) current_locale);
+ TlsSetValue (tls_codeset_index, (LPVOID) codeset);
+ }
+#endif
+
return codeset;
}
--
2.1.0