summaryrefslogtreecommitdiffstats
path: root/source/lib
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2003-09-04 01:12:39 +0000
committerJeremy Allison <jra@samba.org>2003-09-04 01:12:39 +0000
commitef140d15ea0d76a3e7cdcadbfd3e917c210a9411 (patch)
tree30fce18ef5279811d5786853c200e5aaa4b79d9d /source/lib
parentdc43c2dd1b4cd02e996fe10f1684a6571b2fd3de (diff)
downloadsamba-ef140d15ea0d76a3e7cdcadbfd3e917c210a9411.tar.gz
samba-ef140d15ea0d76a3e7cdcadbfd3e917c210a9411.tar.xz
samba-ef140d15ea0d76a3e7cdcadbfd3e917c210a9411.zip
Used cachegrind to track down some bottlenecks.
Removed calls to clobber_region when not compiling with developer as they were hiding speed problems. Added fast path to convert_string() when dealing with ascii -> ascii, ucs2-le to ascii and ascii to ucs2-le with values <= 0x7F. This gives a speedup of 22% on my nbench tests. Next I will do this on convert_string_allocate. Jeremy.
Diffstat (limited to 'source/lib')
-rw-r--r--source/lib/charcnv.c105
-rw-r--r--source/lib/util_str.c11
2 files changed, 104 insertions, 12 deletions
diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c
index 7f372b358fc..53182e13ecc 100644
--- a/source/lib/charcnv.c
+++ b/source/lib/charcnv.c
@@ -150,6 +150,7 @@ void init_iconv(void)
/**
* Convert string from one encoding to another, making error checking etc
+ * Slow path version - uses (slow) iconv.
*
* @param src pointer to source string (multibyte or singlebyte)
* @param srclen length of the source string in bytes
@@ -160,7 +161,8 @@ void init_iconv(void)
* Ensure the srclen contains the terminating zero.
*
**/
-size_t convert_string(charset_t from, charset_t to,
+
+static size_t convert_string_internal(charset_t from, charset_t to,
void const *src, size_t srclen,
void *dest, size_t destlen)
{
@@ -170,18 +172,13 @@ size_t convert_string(charset_t from, charset_t to,
char* outbuf = (char*)dest;
smb_iconv_t descriptor;
- if (srclen == (size_t)-1)
- srclen = strlen(src)+1;
- if (srclen == 0)
- return 0;
-
lazy_initialize_conv();
descriptor = conv_handles[from][to];
if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
if (!conv_silent)
- DEBUG(0,("convert_string: Conversion not supported.\n"));
+ DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
goto use_as_is;
}
@@ -194,12 +191,12 @@ size_t convert_string(charset_t from, charset_t to,
case EINVAL:
reason="Incomplete multibyte sequence";
if (!conv_silent)
- DEBUG(3,("convert_string: Conversion error: %s(%s)\n",reason,inbuf));
+ DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
goto use_as_is;
case E2BIG:
reason="No more room";
if (!conv_silent)
- DEBUG(3, ("convert_string: Required %lu, available %lu\n",
+ DEBUG(3, ("convert_string_internal: Required %lu, available %lu\n",
(unsigned long)srclen, (unsigned long)destlen));
/* we are not sure we need srclen bytes,
may be more, may be less.
@@ -209,11 +206,11 @@ size_t convert_string(charset_t from, charset_t to,
case EILSEQ:
reason="Illegal multibyte sequence";
if (!conv_silent)
- DEBUG(3,("convert_string: Conversion error: %s(%s)\n",reason,inbuf));
+ DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
goto use_as_is;
default:
if (!conv_silent)
- DEBUG(0,("convert_string: Conversion error: %s(%s)\n",reason,inbuf));
+ DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
break;
}
/* smb_panic(reason); */
@@ -232,6 +229,90 @@ size_t convert_string(charset_t from, charset_t to,
}
/**
+ * Convert string from one encoding to another, making error checking etc
+ * Fast path version - handles ASCII first.
+ *
+ * @param src pointer to source string (multibyte or singlebyte)
+ * @param srclen length of the source string in bytes
+ * @param dest pointer to destination string (multibyte or singlebyte)
+ * @param destlen maximal length allowed for string
+ * @returns the number of bytes occupied in the destination
+ *
+ * Ensure the srclen contains the terminating zero.
+ *
+ **/
+
+size_t convert_string(charset_t from, charset_t to,
+ void const *src, size_t srclen,
+ void *dest, size_t destlen)
+{
+ if (srclen == (size_t)-1) {
+ if (from == CH_UCS2)
+ srclen = strlen_w(src)+2;
+ else
+ srclen = strlen(src)+1;
+ }
+ if (srclen == 0)
+ return 0;
+
+ if (from != CH_UCS2 && to != CH_UCS2) {
+ const unsigned char *p = (const unsigned char *)src;
+ unsigned char *q = (unsigned char *)dest;
+ size_t retval = 0;
+
+ /* If all characters are ascii, fast path here. */
+ while (srclen && destlen) {
+ if (*p <= 0x7f) {
+ *q++ = *p++;
+ srclen--;
+ destlen--;
+ retval++;
+ } else {
+ return retval + convert_string_internal(from, to, p, srclen, q, destlen);
+ }
+ }
+ return retval;
+ } else if (from == CH_UCS2 && to != CH_UCS2) {
+ const unsigned char *p = (const unsigned char *)src;
+ unsigned char *q = (unsigned char *)dest;
+ size_t retval = 0;
+
+ /* If all characters are ascii, fast path here. */
+ while ((srclen >= 2) && destlen) {
+ if (*p <= 0x7f && p[1] == 0) {
+ *q++ = *p;
+ srclen -= 2;
+ p += 2;
+ destlen--;
+ retval++;
+ } else {
+ return retval + convert_string_internal(from, to, p, srclen, q, destlen);
+ }
+ }
+ return retval;
+ } else if (from != CH_UCS2 && to == CH_UCS2) {
+ const unsigned char *p = (const unsigned char *)src;
+ unsigned char *q = (unsigned char *)dest;
+ size_t retval = 0;
+
+ /* If all characters are ascii, fast path here. */
+ while (srclen && (destlen >= 2)) {
+ if (*p <= 0x7F) {
+ *q++ = *p++;
+ *q++ = '\0';
+ srclen--;
+ destlen -= 2;
+ retval += 2;
+ } else {
+ return retval + convert_string_internal(from, to, p, srclen, q, destlen);
+ }
+ }
+ return retval;
+ }
+ return convert_string_internal(from, to, src, srclen, dest, destlen);
+}
+
+/**
* Convert between character sets, allocating a new buffer for the result.
*
* @param ctx TALLOC_CTX to use to allocate with. If NULL use malloc.
@@ -925,8 +1006,10 @@ size_t push_string_fn(const char *function, unsigned int line, const void *base_
size_t pull_string_fn(const char *function, unsigned int line, const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
{
+#ifdef DEVELOPER
if (dest_len != (size_t)-1)
clobber_region(function, line, dest, dest_len);
+#endif
if (!(flags & STR_ASCII) && \
((flags & STR_UNICODE || \
diff --git a/source/lib/util_str.c b/source/lib/util_str.c
index f036d88da08..e1db93a1318 100644
--- a/source/lib/util_str.c
+++ b/source/lib/util_str.c
@@ -503,7 +503,9 @@ char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_
return NULL;
}
+#ifdef DEVELOPER
clobber_region(fn,line,dest, maxlength+1);
+#endif
if (!src) {
*dest = 0;
@@ -542,7 +544,9 @@ char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size
src_len = strnlen(src, maxlength + 1);
dest_len = strnlen(dest, maxlength + 1);
+#ifdef DEVELOPER
clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
+#endif
if (src_len + dest_len > maxlength) {
DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
@@ -569,7 +573,9 @@ char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, con
{
size_t len, i;
+#ifdef DEVELOPER
clobber_region(fn, line, dest, maxlength);
+#endif
if (!dest) {
DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
@@ -609,7 +615,9 @@ char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
{
char *d = dest;
+#ifdef DEVELOPER
clobber_region(fn, line, dest, n+1);
+#endif
if (!dest)
return(NULL);
@@ -639,8 +647,9 @@ static char *strncpyn(char *dest, const char *src, size_t n, char c)
char *p;
size_t str_len;
+#ifdef DEVELOPER
clobber_region(dest, n+1);
-
+#endif
p = strchr_m(src, c);
if (p == NULL) {
DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));