[gmime] Improved performance using SIMD in gmime-parser.c



commit 4adb2778d09907abc2086d0eefa6ef326ded8a10
Author: Jeffrey Stedfast <fejj gnome org>
Date:   Wed Feb 19 08:32:01 2014 -0500

    Improved performance using SIMD in gmime-parser.c
    
    2014-02-19  Jeffrey Stedfast  <fejj gnome org>
    
        * gmime/gmime-parser.c (parser_scan_content): Improved performance
        by using a SIMD hack when scanning for the end of a line.

 ChangeLog            |    5 +++++
 gmime/gmime-parser.c |   23 ++++++++++++++++++++---
 2 files changed, 25 insertions(+), 3 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 01b3e9d..7f64cce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2014-02-19  Jeffrey Stedfast  <fejj gnome org>
 
+       * gmime/gmime-parser.c (parser_scan_content): Improved performance
+       by using a SIMD hack when scanning for the end of a line.
+
+2014-02-19  Jeffrey Stedfast  <fejj gnome org>
+
        * gmime/gmime-message.c (message_remove_header): Don't clear the
        mime_part header stream unless we actually remove a header.
        (message_write_to_stream): Only add nwritten to the total if we've
diff --git a/gmime/gmime-parser.c b/gmime/gmime-parser.c
index 720866a..1f7bf30 100644
--- a/gmime/gmime-parser.c
+++ b/gmime/gmime-parser.c
@@ -127,7 +127,7 @@ struct _GMimeParserPrivate {
        gint64 offset;
        
        /* i/o buffers */
-       char realbuf[SCAN_HEAD + SCAN_BUF + 1];
+       char realbuf[SCAN_HEAD + SCAN_BUF + 4];
        char *inbuf;
        char *inptr;
        char *inend;
@@ -1455,11 +1455,13 @@ static int
 parser_scan_content (GMimeParser *parser, GByteArray *content, guint *crlf)
 {
        struct _GMimeParserPrivate *priv = parser->priv;
+       char *aligned, *start, *inend;
        register char *inptr;
-       char *start, *inend;
+       register int *dword;
        size_t nleft, len;
        size_t atleast;
        int found = 0;
+       int mask;
        
        d(printf ("scan-content\n"));
        
@@ -1493,11 +1495,26 @@ parser_scan_content (GMimeParser *parser, GByteArray *content, guint *crlf)
                priv->midline = FALSE;
                
                while (inptr < inend) {
+                       aligned = (char *) (((long) (inptr + 3)) & ~3);
                        start = inptr;
+                       
                        /* Note: see optimization comment [1] */
-                       while (*inptr != '\n')
+                       while (inptr < aligned && *inptr != '\n')
                                inptr++;
                        
+                       if (inptr == aligned) {
+                               dword = (int *) inptr;
+                               
+                               do {
+                                       mask = *dword++ ^ 0x0A0A0A0A;
+                                       mask = ((mask - 0x01010101) & (~mask & 0x80808080));
+                               } while (mask == 0);
+                               
+                               inptr = (char *) (dword - 1);
+                               while (*inptr != '\n')
+                                       inptr++;
+                       }
+                       
                        len = (size_t) (inptr - start);
                        
                        if (inptr < inend) {


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