[glib] Optimize reading strings when deserializing gdbus messages



commit fe0b77fea8c9e5e5d1dd1cada4c18f17b6c9085a
Author: Mike Gorse <mgorse suse com>
Date:   Thu Nov 29 16:51:59 2012 -0600

    Optimize reading strings when deserializing gdbus messages
    
    Now that we're directly accessing the memory holding a message blob,
    we can access strings directly while reading them. This speeds up
    read_string significantly, since we no longer malloc/memcpy/free.

 gio/gdbusmessage.c |   98 ++++++++++++++-------------------------------------
 1 files changed, 27 insertions(+), 71 deletions(-)
---
diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c
index 0bbf1b2..ecbc033 100644
--- a/gio/gdbusmessage.c
+++ b/gio/gdbusmessage.c
@@ -66,27 +66,6 @@ struct _GMemoryBuffer
   GDataStreamByteOrder byte_order;
 };
 
-static gssize
-g_memory_buffer_read  (GMemoryBuffer *mbuf,
-		       void          **buffer,
-		       gsize          count,
-		       GError       **error)
-{
-  gssize res;
-
-  if (((gssize) count) < 0)
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
-		   _("Too large count value passed to %s"), G_STRFUNC);
-      return -1;
-    }
-
-  res = MIN (count, mbuf->valid_len - mbuf->pos);
-  *buffer = mbuf->data + mbuf->pos;
-  mbuf->pos += res;
-  return res;
-}
-
 static guchar
 g_memory_buffer_read_byte (GMemoryBuffer  *mbuf,
 			   GError            **error)
@@ -1384,28 +1363,17 @@ ensure_input_padding (GMemoryBuffer         *buf,
   return TRUE;
 }
 
-static gchar *
+static const gchar *
 read_string (GMemoryBuffer          *mbuf,
              gsize                  len,
              GError               **error)
 {
   gchar *str;
-  guchar nul;
-  GError *local_error;
   const gchar *end_valid;
-  gssize num_read;
-  gchar *ptr;
 
-  str = g_malloc (len + 1);
-
-  num_read = g_memory_buffer_read (mbuf,
-                                   (void **)&ptr,
-                                   len,
-                                   error);
-  if (num_read < 0)
-    goto fail;
-  if (num_read < len)
+  if (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
     {
+      mbuf->pos = mbuf->valid_len;
       /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
       g_set_error (error,
                    G_IO_ERROR,
@@ -1415,19 +1383,27 @@ read_string (GMemoryBuffer          *mbuf,
                                 "Wanted to read %lu byte but only got %lu",
                                 (gulong)len),
                                 (gulong)len,
-                   (gulong)num_read);
-      goto fail;
+                   (gulong)mbuf->valid_len - mbuf->pos);
+      mbuf->pos = mbuf->valid_len;
+      return NULL;
     }
 
-  memcpy (str, ptr, len);
-  local_error = NULL;
-  nul = g_memory_buffer_read_byte (mbuf, &local_error);
-  if (local_error != NULL)
+  if (mbuf->data[mbuf->pos + len] != '\0')
     {
-      g_propagate_error (error, local_error);
-      goto fail;
+      str = g_strndup (mbuf->data + mbuf->pos, len);
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_INVALID_ARGUMENT,
+                   _("Expected NUL byte after the string `%s' but found byte %d"),
+                   str, mbuf->data[mbuf->pos + len]);
+      g_free (str);
+      mbuf->pos += len + 1;
+      return NULL;
     }
-  str[num_read] = '\0';
+
+  str = mbuf->data + mbuf->pos;
+  mbuf->pos += len + 1;
+
   if (!g_utf8_validate (str, -1, &end_valid))
     {
       gint offset;
@@ -1440,26 +1416,13 @@ read_string (GMemoryBuffer          *mbuf,
                    _("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
                      "The valid UTF-8 string up until that point was `%s'"),
                    offset,
-                   (gint) num_read,
+                   (gint) len,
                    valid_str);
       g_free (valid_str);
-      goto fail;
-    }
-  if (nul != '\0')
-    {
-      g_set_error (error,
-                   G_IO_ERROR,
-                   G_IO_ERROR_INVALID_ARGUMENT,
-                   _("Expected NUL byte after the string `%s' but found byte %d"),
-                   str, nul);
-      goto fail;
+      return NULL;
     }
 
   return str;
-
- fail:
-  g_free (str);
-  return NULL;
 }
 
 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
@@ -1623,7 +1586,7 @@ parse_value_from_blob (GMemoryBuffer          *buf,
       if (!just_align)
         {
           guint32 len;
-          gchar *v;
+          const gchar *v;
           len = g_memory_buffer_read_uint32 (buf, &local_error);
           if (local_error != NULL)
             goto fail;
@@ -1631,7 +1594,6 @@ parse_value_from_blob (GMemoryBuffer          *buf,
           if (v == NULL)
             goto fail;
           ret = g_variant_new_string (v);
-          g_free (v);
         }
       break;
 
@@ -1641,7 +1603,7 @@ parse_value_from_blob (GMemoryBuffer          *buf,
       if (!just_align)
         {
           guint32 len;
-          gchar *v;
+          const gchar *v;
           len = g_memory_buffer_read_uint32 (buf, &local_error);
           if (local_error != NULL)
             goto fail;
@@ -1655,11 +1617,9 @@ parse_value_from_blob (GMemoryBuffer          *buf,
                            G_IO_ERROR_INVALID_ARGUMENT,
                            _("Parsed value `%s' is not a valid D-Bus object path"),
                            v);
-              g_free (v);
               goto fail;
             }
           ret = g_variant_new_object_path (v);
-          g_free (v);
         }
       break;
 
@@ -1667,7 +1627,7 @@ parse_value_from_blob (GMemoryBuffer          *buf,
       if (!just_align)
         {
           guchar len;
-          gchar *v;
+          const gchar *v;
           len = g_memory_buffer_read_byte (buf, &local_error);
           if (local_error != NULL)
             goto fail;
@@ -1681,11 +1641,9 @@ parse_value_from_blob (GMemoryBuffer          *buf,
                            G_IO_ERROR_INVALID_ARGUMENT,
                            _("Parsed value `%s' is not a valid D-Bus signature"),
                        v);
-              g_free (v);
               goto fail;
             }
           ret = g_variant_new_signature (v);
-          g_free (v);
         }
       break;
 
@@ -1874,7 +1832,7 @@ parse_value_from_blob (GMemoryBuffer          *buf,
           if (!just_align)
             {
               guchar siglen;
-              gchar *sig;
+              const gchar *sig;
               GVariantType *variant_type;
               GVariant *value;
 
@@ -1891,11 +1849,9 @@ parse_value_from_blob (GMemoryBuffer          *buf,
                                G_IO_ERROR_INVALID_ARGUMENT,
                                _("Parsed value `%s' for variant is not a valid D-Bus signature"),
                                sig);
-                  g_free (sig);
                   goto fail;
                 }
               variant_type = g_variant_type_new (sig);
-              g_free (sig);
               value = parse_value_from_blob (buf,
                                              variant_type,
                                              FALSE,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]