Used cachegrind to track down some bottlenecks.
authorJeremy Allison <jra@samba.org>
Thu, 4 Sep 2003 01:12:39 +0000 (01:12 +0000)
committerJeremy Allison <jra@samba.org>
Thu, 4 Sep 2003 01:12:39 +0000 (01:12 +0000)
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.
(This used to be commit ef140d15ea0d76a3e7cdcadbfd3e917c210a9411)

source3/lib/charcnv.c
source3/lib/util_str.c
source3/libsmb/clientgen.c
source3/smbd/process.c

index 7f372b358fcfa0d5816fecb3cc6bdd443d3ea143..53182e13eccabb8058188c44e8e8d9e044dbd17e 100644 (file)
@@ -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); */
@@ -231,6 +228,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.
  *
@@ -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 || \
index f036d88da0856f6711bc2da4534090d608486361..e1db93a131878552943a3a7d067b195545c024c6 100644 (file)
@@ -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));
index 308ce31fd08226776d4acc362326d95da2282161..0a134f715dcbd6e4276468441e0877d4b2f7fbc9 100644 (file)
@@ -299,9 +299,12 @@ struct cli_state *cli_initialise(struct cli_state *cli)
        memset(cli->outbuf, 0, cli->bufsize);
        memset(cli->inbuf, 0, cli->bufsize);
 
+
+#if defined(DEVELOPER)
        /* just because we over-allocate, doesn't mean it's right to use it */
        clobber_region(FUNCTION_MACRO, __LINE__, cli->outbuf+cli->bufsize, SAFETY_MARGIN);
        clobber_region(FUNCTION_MACRO, __LINE__, cli->inbuf+cli->bufsize, SAFETY_MARGIN);
+#endif
 
        /* initialise signing */
        cli_null_set_signing(cli);
index 457ba8cc63f07ecc0ea34426788f40b776314948..3c15cd18333711702431815cc7de279adb9c4231 100644 (file)
@@ -1265,8 +1265,10 @@ void smbd_process(void)
        if ((InBuffer == NULL) || (OutBuffer == NULL)) 
                return;
 
+#if defined(DEVELOPER)
        clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
        clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
+#endif
 
        max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
 
@@ -1295,7 +1297,9 @@ void smbd_process(void)
                        num_smbs = 0; /* Reset smb counter. */
                }
 
+#if defined(DEVELOPER)
                clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
+#endif
 
                while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
                        if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))