2006-08-19 Aaron Bockover <abockover@novell.com>
authorAaron Bockover <abockover@novell.com>
Sun, 20 Aug 2006 04:24:58 +0000 (04:24 -0000)
committerAaron Bockover <abockover@novell.com>
Sun, 20 Aug 2006 04:24:58 +0000 (04:24 -0000)
    * src/gstring.c: optimize and generalize reallocation by providing
    a GROW_IF_NECESSARY macro, do not use strcpy/strcat as they are
    very, very slow; GString is now much closer to GLib's implementation
    in terms of performance

    * test/string.c: added speed-specific tests to beat on reallocation code

    * test/test-both: run make if the test drivers don't exist

svn path=/trunk/mono/; revision=64075

eglib/ChangeLog
eglib/src/gstring.c
eglib/test/string.c
eglib/test/test-both

index 22a8638bcd77544906b9018a0861e911a3452104..00444ec34d423c9a80187f9db2acc45657822a25 100644 (file)
@@ -1,3 +1,14 @@
+2006-08-19  Aaron Bockover  <abockover@novell.com>
+
+       * src/gstring.c: optimize and generalize reallocation by providing
+       a GROW_IF_NECESSARY macro, do not use strcpy/strcat as they are 
+       very, very slow; GString is now much closer to GLib's implementation
+       in terms of performance
+
+       * test/string.c: added speed-specific tests to beat on reallocation code
+
+       * test/test-both: run make if the test drivers don't exist
+
 2006-08-19  Jonathan Chambers  <jonathan.chambers@gmail.com>
 
        * src/gmodule.c: Add gmodule support for windows and fix
index ae0ff39abe2717309ab8b14d103e84f8f5bff16a..f5d899d2755e0258cee9957a7a5bdd37dac2b462 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Author:
  *   Miguel de Icaza (miguel@novell.com)
+ *   Aaron Bockover (abockover@novell.com)
  *
  * (C) 2006 Novell, Inc.
  *
 #include <stdio.h>
 #include <glib.h>
 
-GString *
-g_string_new (const gchar *init)
-{
-       GString *ret = g_new (GString, 1);
-       int len, alloc;
-
-       len = strlen (init);
-       if (len < 15)
-               alloc = 16;
-       else
-               alloc = len+1;
-       ret->str = g_malloc (alloc);
-       ret->len = len;
-       ret->allocated_len = alloc;
-       strcpy (ret->str, init);
-
-       return ret;
+#define GROW_IF_NECESSARY(s,l) { \
+       if(s->len + l >= s->allocated_len) { \
+               s->allocated_len = (s->allocated_len + l + 16) * 2; \
+               s->str = g_realloc(s->str, s->allocated_len); \
+       } \
 }
 
 GString *
@@ -53,16 +42,21 @@ g_string_new_len (const gchar *init, gssize len)
 {
        GString *ret = g_new (GString, 1);
 
-       ret->str = g_malloc (len+1);
-       ret->allocated_len = len + 1;
-       ret->len = len;
+       ret->len = len < 0 ? strlen(init) : len;
+       ret->allocated_len = MAX(ret->len + 1, 16);
+       ret->str = g_malloc(ret->allocated_len);
+       memcpy(ret->str, init, ret->len);
+       ret->str[ret->len] = 0;
 
-       memcpy (ret->str, init, len);
-       ret->str [len] = 0;
-       
        return ret;
 }
 
+GString *
+g_string_new (const gchar *init)
+{
+       return g_string_new_len(init, -1);
+}
+
 GString *
 g_string_sized_new (gsize default_size)
 {
@@ -79,106 +73,79 @@ g_string_sized_new (gsize default_size)
 gchar *
 g_string_free (GString *string, gboolean free_segment)
 {
-       char *data;
+       gchar *data;
+       
        g_return_val_if_fail (string != NULL, NULL);
 
        data = string->str;
-       if (free_segment)
-               g_free (data);
-       g_free (string);
-
-       if (free_segment)
-               return NULL;
-       else
-               return data;
+       g_free(string);
        
+       if(!free_segment) {
+               return data;
+       }
+
+       g_free(data);
+       return NULL;
 }
 
 GString *
-g_string_append (GString *string, const gchar *val)
+g_string_append_len (GString *string, const gchar *val, gssize len)
 {
-       int len, size;
-       char *new;
-       
-       g_return_val_if_fail (string != NULL, NULL);
-       g_return_val_if_fail (val != NULL, string);
-       
-       len = strlen (val);
-       if ((string->len + len) < string->allocated_len){
-               strcat (string->str, val);
-               string->len += len;
-               return string;
+       g_return_val_if_fail(string != NULL, NULL);
+       g_return_val_if_fail(val != NULL, string);
+
+       if(len < 0) {
+               len = strlen(val);
        }
-       size = (len + string->len + 16) * 2;
-       new = g_malloc (size);
-       memcpy (new, string->str, string->len);
-       memcpy (new + string->len, val, len);
-       g_free (string->str);
-       string->str = new;
-       string->allocated_len = size;
+
+       GROW_IF_NECESSARY(string, len);
+       memcpy(string->str + string->len, val, len);
        string->len += len;
-       new [string->len] = 0;
-       
+       string->str[string->len] = 0;
+
        return string;
 }
 
+GString *
+g_string_append (GString *string, const gchar *val)
+{
+       g_return_val_if_fail(string != NULL, NULL);
+       g_return_val_if_fail(val != NULL, string);
+
+       return g_string_append_len(string, val, -1);
+}
+
 GString *
 g_string_append_c (GString *string, gchar c)
 {
-       gsize size;
-       char *new;
-       
-       g_return_val_if_fail (string != NULL, NULL);
+       g_return_val_if_fail(string != NULL, NULL);
 
-       if (string->len + 1 < string->allocated_len){
-               string->str [string->len] = c;
-               string->str [string->len+1] = 0;
-               string->len++;
-               return string;
-       }
-       size = (string->allocated_len + 16) * 2;
-       new = g_malloc (size);
-       memcpy (new, string->str, string->len);
-       new [string->len] = c;
-       new [string->len+1] = 0;
+       GROW_IF_NECESSARY(string, 1);
        
-       g_free (string->str);
-       string->allocated_len = size;
+       string->str[string->len] = c;
+       string->str[string->len + 1] = 0;
        string->len++;
-       string->str = new;
 
        return string;
 }
 
 GString *
-g_string_append_len (GString *string, const gchar *val, gssize len)
+g_string_prepend (GString *string, const gchar *val)
 {
-       int size;
-       char *new;
+       gssize len;
        
-       g_return_val_if_fail (string != NULL, NULL);
+       g_return_val_if_fail (string != NULL, string);
        g_return_val_if_fail (val != NULL, string);
-       if (len < 0)
-               return g_string_append (string, val);
-       
-       if ((string->len + len) < string->allocated_len){
-               memcpy (string->str+string->len, val, len);
-               string->len += len;
-               return string;
-       }
-       size = (len + string->len + 16) * 2;
-       new = g_malloc (size);
-       memcpy (new, string->str, string->len);
-       memcpy (new + string->len, val, len);
-       g_free (string->str);
-       string->str = new;
-       string->allocated_len = size;
-       string->len += len;
-       new [string->len] = 0;
+
+       len = strlen (val);
        
+       GROW_IF_NECESSARY(string, len); 
+       memmove(string->str + len, string->str, string->len + 1);
+       memcpy(string->str, val, len);
+
        return string;
 }
-       
+
 void
 g_string_append_printf (GString *string, const gchar *format, ...)
 {
@@ -220,52 +187,12 @@ g_string_truncate (GString *string, gsize len)
        g_return_val_if_fail (string != NULL, string);
 
        /* Silent return */
-       if (len < 0)
-               return string;
-       
-       if (len >= string->len)
+       if (len < 0 || len >= string->len) {
                return string;
-       string->len = len;
-       string->str [len] = 0;
-       return string;
-}
-
-GString *
-g_string_prepend (GString *string, const gchar *val)
-{
-       int vallen;
-       g_return_val_if_fail (string != NULL, string);
-       g_return_val_if_fail (val != NULL, string);
-
-       vallen = strlen (val);
-       
-       if ((string->len + vallen + 1) < string->allocated_len){
-               memmove (string->str+vallen, string->str, string->len+1);
-               memcpy (string->str, val, vallen);
-       } else {
-               /*
-                * Add some extra space, so we do not reallocate too often
-                * maybe we should centralize this decision somewhere else. 
-                */
-               char *new;
-               int nl = MAX (string->len + vallen + 1, string->allocated_len);
-               nl = nl < 8192 ? (nl * 3) : nl + 1024;
-
-               new = malloc (nl);
-               /* Failure */
-               if (new == NULL) {
-                       g_error ("No more memory");
-                       return string;
-               }
-               strcpy (new, val);
-               /* To cope with embedded nulls */
-               memcpy (new + vallen, string->str, string->len);
-               string->len = string->len + vallen;
-               g_free (string->str);
-               string->str = new;
-               string->allocated_len = nl;
        }
        
+       string->len = len;
+       string->str[len] = 0;
        return string;
 }
 
index cb33afab2a50aa709df74f87db8e4193e8464f41..d75f11ca7c6f07de13674fe0e6e2b95c6f5c46ae 100644 (file)
@@ -5,6 +5,46 @@
 
 #define sfail(k,p) if (s->str [p] != k) { g_string_free (s,TRUE); return FAILED("Got %s, Failed at %d, expected '%c'", s->str, p, k);}
 
+RESULT
+test_append_speed()
+{
+       GString *s = g_string_new("");
+       gint i;
+       
+       for(i = 0; i < 1024; i++) {
+               g_string_append(s, "x");
+       }
+       
+       if(strlen (s->str) != 1024) {
+               return FAILED("Incorrect string size, got: %s %d", 
+                       s->str, strlen(s->str));
+       }
+       
+       g_string_free (s, TRUE);
+
+       return OK;
+}
+
+RESULT
+test_append_c_speed()
+{
+       GString *s = g_string_new("");
+       gint i;
+       
+       for(i = 0; i < 1024; i++) {
+               g_string_append_c(s, 'x');
+       }
+       
+       if(strlen(s->str) != 1024) {
+               return FAILED("Incorrect string size, got: %s %d", s->str, 
+                       strlen(s->str));
+       }
+       
+       g_string_free(s, TRUE);
+
+       return OK;
+}
+
 RESULT
 test_gstring ()
 {
@@ -30,14 +70,6 @@ test_gstring ()
                return FAILED("Did not copy correctly, got: %s", s->str+4);
        }
 
-       g_string_free (s, TRUE);
-       s = g_string_new ("");
-       for (i = 0; i < 1024; i++){
-               g_string_append (s, "x");
-       }
-       if (strlen (s->str) != 1024){
-               return FAILED("Incorrect string size, got: %s %d", s->str, strlen (s->str));
-       }
        g_string_free (s, TRUE);
 
        s = g_string_new ("");
@@ -76,7 +108,7 @@ test_gstring ()
        return OK;
 }
 
-static char *
+RESULT
 test_sized ()
 {
        GString *s = g_string_sized_new (20);
@@ -91,7 +123,7 @@ test_sized ()
        return NULL;
 }
 
-static char *
+RESULT
 test_truncate ()
 {
        GString *s = g_string_new ("0123456789");
@@ -117,7 +149,7 @@ test_truncate ()
        return NULL;
 }
 
-static char *
+RESULT
 test_prepend ()
 {
        GString *s = g_string_new ("dingus");
@@ -149,7 +181,7 @@ test_prepend ()
        return NULL;
 }
 
-static char *
+RESULT
 test_appendlen ()
 {
        GString *s = g_string_new ("");
@@ -170,6 +202,8 @@ test_appendlen ()
 }
 
 static Test string_tests [] = {
+       {"append-speed", test_append_speed},
+    {"append_c-speed", test_append_c_speed},
        {"constructors+append", test_gstring },
        {"constructor-sized", test_sized },
        {"truncate", test_truncate },
index cd357c4ae86535c0899aea36fd2d3acc47b4814b..038c927eb258f20a998739c1473e7789a6674d0b 100755 (executable)
@@ -24,6 +24,10 @@ for arg in $@; do
        fi
 done
 
+if [ ! -x "./test-glib" -o ! -x "./test-eglib" ]; then
+       make
+fi
+
 if [ "x$1" = "x--speed-compare" ]; then
        ITERATIONS=100000
        if [ ! -z "$2" ]; then