Author: stefan2
Date: Tue May 17 11:27:25 2011
New Revision: 1104160
URL: http://svn.apache.org/viewvc?rev=1104160&view=rev
Log:
Speed up UTF8 conversion, especially if APR_HAS_THREADS.
Provide global
* subversion/libsvn_subr/utf.c
(SVN_UTF_NTOU_XLATE_HANDLE, SVN_UTF_UTON_XLATE_HANDLE):
make them identifiable by address
(xlat_ntou_static_handle, xlat_uton_static_handle):
introduce global translation map pointers as 1st level cache
(get_xlate_handle_node): match standard xlat types by address;
try global map pointers first before falling back to the hash
(put_xlate_handle_node): match standard xlat types by address;
push old global maps to hash
Modified:
subversion/trunk/subversion/libsvn_subr/utf.c
Modified: subversion/trunk/subversion/libsvn_subr/utf.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/utf.c?rev=1104160&r1=1104159&r2=1104160&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/utf.c (original)
+++ subversion/trunk/subversion/libsvn_subr/utf.c Tue May 17 11:27:25 2011
@@ -29,6 +29,7 @@
#include <apr_strings.h>
#include <apr_lib.h>
#include <apr_xlate.h>
+#include <apr_atomic.h>
#include "svn_string.h"
#include "svn_error.h"
@@ -42,9 +43,13 @@
-#define SVN_UTF_NTOU_XLATE_HANDLE "svn-utf-ntou-xlate-handle"
-#define SVN_UTF_UTON_XLATE_HANDLE "svn-utf-uton-xlate-handle"
-#define SVN_APR_UTF8_CHARSET "UTF-8"
+/* Use these static strings to maximize performance on standard conversions.
+ * Any strings on other locations are still valid, however.
+ */
+static const char *SVN_UTF_NTOU_XLATE_HANDLE = "svn-utf-ntou-xlate-handle";
+static const char *SVN_UTF_UTON_XLATE_HANDLE = "svn-utf-uton-xlate-handle";
+
+static const char *SVN_APR_UTF8_CHARSET = "UTF-8";
#if APR_HAS_THREADS
static apr_thread_mutex_t *xlate_handle_mutex = NULL;
@@ -79,6 +84,13 @@ typedef struct xlate_handle_node_t {
memory leak. */
static apr_hash_t *xlate_handle_hash = NULL;
+/* "1st level cache" to standard conversion maps. We may access these
+ * using atomic xchange ops, i.e. without further thread synchronization.
+ * If the respective item is NULL, fallback to hash lookup.
+ */
+static volatile void *xlat_ntou_static_handle = NULL;
+static volatile void *xlat_uton_static_handle = NULL;
+
/* Clean up the xlate handle cache. */
static apr_status_t
xlate_cleanup(void *arg)
@@ -91,6 +103,10 @@ xlate_cleanup(void *arg)
#endif
xlate_handle_hash = NULL;
+ /* ensure no stale objects get accessed */
+ xlat_ntou_static_handle = NULL;
+ xlat_uton_static_handle = NULL;
+
return APR_SUCCESS;
}
@@ -183,6 +199,19 @@ get_xlate_handle_node(xlate_handle_node_
{
if (xlate_handle_hash)
{
+ /* 1st level: global, static items */
+ if (userdata_key == SVN_UTF_NTOU_XLATE_HANDLE)
+ old_node = apr_atomic_xchgptr(&xlat_ntou_static_handle, NULL);
+ else if (userdata_key == SVN_UTF_UTON_XLATE_HANDLE)
+ old_node = apr_atomic_xchgptr(&xlat_uton_static_handle, NULL);
+
+ if (old_node && old_node->valid)
+ {
+ *ret = old_node;
+ return SVN_NO_ERROR;
+ }
+
+ /* 2nd level: hash lookup */
#if APR_HAS_THREADS
apr_err = apr_thread_mutex_lock(xlate_handle_mutex);
if (apr_err != APR_SUCCESS)
@@ -321,9 +350,20 @@ put_xlate_handle_node(xlate_handle_node_
assert(node->next == NULL);
if (!userdata_key)
return;
+
+ /* push previous global node to the hash */
if (xlate_handle_hash)
{
xlate_handle_node_t **node_p;
+
+ /* 1st level: global, static items */
+ if (userdata_key == SVN_UTF_NTOU_XLATE_HANDLE)
+ node = apr_atomic_xchgptr(&xlat_ntou_static_handle, node);
+ else if (userdata_key == SVN_UTF_UTON_XLATE_HANDLE)
+ node = apr_atomic_xchgptr(&xlat_uton_static_handle, node);
+ if (node == NULL)
+ return;
+
#if APR_HAS_THREADS
if (apr_thread_mutex_lock(xlate_handle_mutex) != APR_SUCCESS)
SVN_ERR_MALFUNCTION_NO_RETURN();