[cairo-commit] configure.ac util/cairo-script

Chris Wilson ickle at kemper.freedesktop.org
Sun Jan 6 02:25:16 PST 2013


 configure.ac                               |   12 +
 util/cairo-script/Makefile.am              |    2 
 util/cairo-script/cairo-script-file.c      |   32 ++++-
 util/cairo-script/cairo-script-objects.c   |    3 
 util/cairo-script/cairo-script-operators.c |   45 +++++--
 util/cairo-script/cairo-script-private.h   |    5 
 util/cairo-script/cairo-script-scanner.c   |  184 ++++++++++++++++++++++-------
 7 files changed, 227 insertions(+), 56 deletions(-)

New commits:
commit 45a4b42a361eb791c571b201e11c3505a0a1a396
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jan 4 17:32:46 2013 +0000

    script: Recompress strings using LZO whilst binding traces
    
    Try using the lighter-weight LZO decompressor in an effort to speed up
    replays (at the cost of making the bound traces slightly larger).
    Presuming that with the slight increase in file size (from -1% to +10%),
    the file data remains in the readahead buffer cache, replays see a
    performance improvement of between 5-10%.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/configure.ac b/configure.ac
index fc8d3b1..31123c7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -47,6 +47,18 @@ AC_CHECK_LIB(z, compress,
 	 [have_libz="no (requires zlib http://www.gzip.org/zlib/)"])],
 	 [have_libz="no (requires zlib http://www.gzip.org/zlib/)"])
 
+save_LIBS="$LIBS"
+AC_CHECK_LIB(lzo2, lzo2a_decompress,
+	 [AC_CHECK_HEADER(lzo/lzo2a.h, [
+	  have_lzo=yes
+	  AC_DEFINE(HAVE_LZO, 1, [Define to 1 if you have lzo available])
+	  lzo_LIBS="-llzo2"
+	 ],
+	 [have_lzo="no (requires lzpo http://www.oberhumer.com/opensource/lzo/)"])],
+	 [have_lzo="no (requires lzpo http://www.oberhumer.com/opensource/lzo/)"])
+AC_SUBST(lzo_LIBS)
+LIBS="$save_LIBS"
+
 AC_CHECK_LIB(dl, dlsym,
 	     [have_dlsym=yes; have_dl=yes],
 	     [have_dlsym=no; have_dl=no])
diff --git a/util/cairo-script/Makefile.am b/util/cairo-script/Makefile.am
index c2f55a3..d5c2998 100644
--- a/util/cairo-script/Makefile.am
+++ b/util/cairo-script/Makefile.am
@@ -15,7 +15,7 @@ libcairo_script_interpreter_la_SOURCES = \
 	$(NULL)
 libcairo_script_interpreter_la_CFLAGS = $(CAIRO_CFLAGS)
 libcairo_script_interpreter_la_LDFLAGS = -version-info $(CAIRO_LIBTOOL_VERSION_INFO) -no-undefined $(export_symbols)
-libcairo_script_interpreter_la_LIBADD = $(top_builddir)/src/libcairo.la $(CAIRO_LIBS) -lz
+libcairo_script_interpreter_la_LIBADD = $(top_builddir)/src/libcairo.la $(CAIRO_LIBS) $(lzo_LIBS) -lz
 
 csi_replay_SOURCES = csi-replay.c
 csi_replay_CFLAGS = $(CAIRO_CFLAGS)
diff --git a/util/cairo-script/cairo-script-file.c b/util/cairo-script/cairo-script-file.c
index 34f2964..85d292c 100644
--- a/util/cairo-script/cairo-script-file.c
+++ b/util/cairo-script/cairo-script-file.c
@@ -39,6 +39,10 @@
 #include <string.h>
 #include <zlib.h>
 
+#if HAVE_LZO
+#include <lzo/lzo2a.h>
+#endif
+
 #define CHUNK_SIZE 32768
 
 #define OWN_STREAM 0x1
@@ -166,12 +170,32 @@ csi_file_new_from_string (csi_t *ctx,
 	    return status;
 
 	tmp_str = tmp_obj.datum.string;
-	if (uncompress ((Bytef *) tmp_str->string, &len,
-			(Bytef *) src->string, src->len) != Z_OK)
-	{
+	switch (src->method) {
+	case NONE:
+	default:
+	    status = _csi_error (CAIRO_STATUS_NO_MEMORY);
+	    break;
+
+#if HAVE_ZLIB
+	case ZLIB:
+	    if (uncompress ((Bytef *) tmp_str->string, &len,
+			    (Bytef *) src->string, src->len) != Z_OK)
+		status = _csi_error (CAIRO_STATUS_NO_MEMORY);
+	    break;
+#endif
+#if HAVE_LZO
+	case LZO:
+	    if (lzo2a_decompress ((lzo_bytep) src->string, src->len,
+				  (lzo_bytep) tmp_str->string, &len,
+				  NULL))
+		status = _csi_error (CAIRO_STATUS_NO_MEMORY);
+	    break;
+#endif
+	}
+	if (_csi_unlikely (status)) {
 	    csi_string_free (ctx, tmp_str);
 	    _csi_slab_free (ctx, file, sizeof (csi_file_t));
-	    return _csi_error (CAIRO_STATUS_NO_MEMORY);
+	    return status;
 	}
 
 	file->src  = tmp_str;
diff --git a/util/cairo-script/cairo-script-objects.c b/util/cairo-script/cairo-script-objects.c
index adf6160..a625489 100644
--- a/util/cairo-script/cairo-script-objects.c
+++ b/util/cairo-script/cairo-script-objects.c
@@ -508,6 +508,7 @@ csi_string_new (csi_t *ctx,
     }
     string->len = len;
     string->deflate = 0;
+    string->method = NONE;
 
     string->base.type = CSI_OBJECT_TYPE_STRING;
     string->base.ref = 1;
@@ -534,6 +535,7 @@ csi_string_deflate_new (csi_t *ctx,
 
     string = obj->datum.string;
     string->deflate = out_len;
+    string->method = ZLIB;
 
     return CSI_STATUS_SUCCESS;
 }
@@ -556,6 +558,7 @@ csi_string_new_from_bytes (csi_t *ctx,
     string->string = bytes;
     string->len = len;
     string->deflate = 0;
+    string->method = NONE;
 
     string->base.type = CSI_OBJECT_TYPE_STRING;
     string->base.ref = 1;
diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c
index 4b7d4fc..9ba24f8 100644
--- a/util/cairo-script/cairo-script-operators.c
+++ b/util/cairo-script/cairo-script-operators.c
@@ -52,7 +52,14 @@
 #include <math.h>
 #include <limits.h> /* INT_MAX */
 #include <assert.h>
+
+#if HAVE_ZLIB
 #include <zlib.h>
+#endif
+
+#if HAVE_LZO
+#include <lzo/lzo2a.h>
+#endif
 
 #ifdef HAVE_MMAP
 # ifdef HAVE_UNISTD_H
@@ -1756,17 +1763,37 @@ inflate_string (csi_t *ctx, csi_string_t *src)
     if (bytes == NULL)
 	return NULL;
 
-    if (uncompress ((Bytef *) bytes, &len,
-		    (Bytef *) src->string, src->len) != Z_OK)
-    {
-	_csi_free (ctx, bytes);
-	bytes = NULL;
-    }
-    else
-    {
-	bytes[len] = '\0';
+    switch (src->method) {
+    default:
+    case NONE:
+	free (bytes);
+	return NULL;
+
+#if HAVE_ZLIB
+    case ZLIB:
+	if (uncompress ((Bytef *) bytes, &len,
+			(Bytef *) src->string, src->len) != Z_OK)
+	{
+	    _csi_free (ctx, bytes);
+	    return NULL;
+	}
+	break;
+#endif
+
+#if HAVE_LZO
+    case LZO:
+	if (lzo2a_decompress ((Bytef *) src->string, src->len,
+			      (Bytef *) bytes, &len,
+			      NULL))
+	{
+	    _csi_free (ctx, bytes);
+	    return NULL;
+	}
+	break;
+#endif
     }
 
+    bytes[len] = '\0';
     return bytes;
 }
 
diff --git a/util/cairo-script/cairo-script-private.h b/util/cairo-script/cairo-script-private.h
index 3286bb4..6bf41b4 100644
--- a/util/cairo-script/cairo-script-private.h
+++ b/util/cairo-script/cairo-script-private.h
@@ -392,6 +392,11 @@ struct _csi_string {
     csi_compound_object_t base;
     csi_integer_t len;
     csi_integer_t deflate;
+    enum {
+	NONE,
+	ZLIB,
+	LZO,
+    } method;
     char *string;
 };
 
diff --git a/util/cairo-script/cairo-script-scanner.c b/util/cairo-script/cairo-script-scanner.c
index eeec686..4254aa0 100644
--- a/util/cairo-script/cairo-script-scanner.c
+++ b/util/cairo-script/cairo-script-scanner.c
@@ -38,10 +38,15 @@
 #include <math.h> /* pow */
 #include <stdio.h> /* EOF */
 #include <stdint.h> /* for {INT,UINT}*_{MIN,MAX} */
+#include <stdlib.h> /* malloc/free */
 #include <string.h> /* memset */
 #include <assert.h>
 #include <zlib.h>
 
+#if HAVE_LZO
+#include <lzo/lzo2a.h>
+#endif
+
 #define DEBUG_SCAN 0
 
 #if WORDS_BIGENDIAN
@@ -124,7 +129,8 @@ fprintf_obj (FILE *stream, csi_t *ctx, const csi_object_t *obj)
 		    obj->datum.matrix->matrix.y0);
 	    break;
 	case CSI_OBJECT_TYPE_STRING:
-	    fprintf (stream, "string: len=%ld\n", obj->datum.string->len);
+	    fprintf (stream, "string: len=%ld, defate=%ld, method=%d\n",
+		     obj->datum.string->len, obj->datum.string->deflate, obj->datum.string->method);
 	    break;
 
 	    /* cairo */
@@ -799,6 +805,7 @@ string_read (csi_t *ctx,
 	uint32_t u32;
 	scan_read (scan, src, &u32, 4);
 	obj->datum.string->deflate = be32 (u32);
+	obj->datum.string->method = compressed;
     }
 
     if (_csi_likely (len))
@@ -994,8 +1001,13 @@ scan_none:
 	    obj.type &= ~CSI_OBJECT_ATTR_EXECUTABLE;
 	    break;
 
+#define STRING_LZO 154
+	case STRING_LZO:
+	    scan_read (scan, src, &u.u32, 4);
+	    string_read (ctx, scan, src, be32 (u.u32), LZO, &obj);
+	    break;
+
 	    /* unassigned */
-	case 154:
 	case 155:
 	case 156:
 	case 157:
@@ -1569,51 +1581,139 @@ _translate_string (csi_t *ctx,
 	uint16_t u16;
 	uint32_t u32;
     } u;
-    int len;
+    void *buf;
+    unsigned long hdr_len, buf_len, deflate;
+    int method;
+
+    buf = string->string;
+    buf_len = string->len;
+    deflate = string->deflate;
+    method = string->method;
+
+#if HAVE_LZO
+    if (method == NONE && buf_len > 16) {
+	unsigned long mem_len = 2*string->len > LZO2A_999_MEM_COMPRESS ? 2*string->len : LZO2A_999_MEM_COMPRESS;
+	void *mem = malloc (mem_len);
+	void *work = malloc(LZO2A_999_MEM_COMPRESS);
+
+	if (lzo2a_999_compress ((lzo_bytep) buf, buf_len,
+				(lzo_bytep) mem, &mem_len,
+				work) == 0 &&
+	    8+2*mem_len < buf_len)
+	{
+	    method = LZO;
+	    deflate = buf_len;
+	    buf_len = mem_len;
+	    buf = mem;
+	}
+	else
+	{
+	    free (mem);
+	}
 
-#if WORDS_BIGENDIAN
-    if (string->len <= UINT8_MAX) {
-	hdr = STRING_1;
-	u.u8 = string->len;
-	len = 1;
-    } else if (string->len <= UINT16_MAX) {
-	hdr = STRING_2_MSB;
-	u.u16 = string->len;
-	len = 2;
-    } else {
-	hdr = STRING_4_MSB;
-	u.u32 = string->len;
-	len = 4;
+	free (work);
     }
-#else
-    if (string->len <= UINT8_MAX) {
-	hdr = STRING_1;
-	u.u8 = string->len;
-	len = 1;
-    } else if (string->len <= UINT16_MAX) {
-	hdr = STRING_2_LSB;
-	u.u16 = string->len;
-	len = 2;
-    } else {
-	hdr = STRING_4_LSB;
-	u.u32 = string->len;
-	len = 4;
+#if HAVE_ZLIB
+    if (method == ZLIB) {
+	buf_len = string->deflate;
+	buf = malloc (string->deflate);
+	if (uncompress ((Bytef *) buf, &buf_len,
+			(Bytef *) string->string, string->len) == Z_OK)
+	{
+	    if (buf_len <= 8 + 2*string->len) {
+		method = NONE;
+		deflate = 0;
+	    } else {
+		unsigned long mem_len = 2*string->deflate;
+		void *mem = malloc (mem_len);
+		void *work = malloc(LZO2A_999_MEM_COMPRESS);
+
+		if (lzo2a_999_compress ((lzo_bytep) buf, buf_len,
+					(lzo_bytep) mem, &mem_len,
+					work) == 0)
+		{
+		    if (8 + mem_len > buf_len) {
+			method = NONE;
+			deflate = 0;
+		    } else {
+			free (buf);
+			method = LZO;
+			deflate = buf_len;
+			buf_len = mem_len;
+			buf = mem;
+			assert(deflate);
+		    }
+		}
+		else
+		{
+		    free (buf);
+		    buf = string->string;
+		    buf_len = string->len;
+		}
+
+		free (work);
+	    }
+	}
+	else
+	{
+	    free (buf);
+	    buf = string->string;
+	    buf_len = string->len;
+	}
     }
 #endif
-    if (string->deflate)
-	hdr |= STRING_DEFLATE;
-
-    closure->write_func (closure->closure,
-	                 (unsigned char *) &hdr, 1);
-    closure->write_func (closure->closure,
-	                 (unsigned char *) &u, len);
-    if (string->deflate) {
-	uint32_t u32 = to_be32 (string->deflate);
-	closure->write_func (closure->closure,
-			     (unsigned char *) &u32, 4);
+#endif
+
+    if (method == LZO) {
+	hdr = STRING_LZO;
+	u.u32 = to_be32 (buf_len);
+	hdr_len = 4;
+    } else {
+#if WORDS_BIGENDIAN
+	if (buf_len <= UINT8_MAX) {
+	    hdr = STRING_1;
+	    u.u8 = buf_len;
+	    hdr_len = 1;
+	} else if (buf_len <= UINT16_MAX) {
+	    hdr = STRING_2_MSB;
+	    u.u16 = buf_len;
+	    hdr_len = 2;
+	} else {
+	    hdr = STRING_4_MSB;
+	    u.u32 = buf_len;
+	    hdr_len = 4;
+	}
+#else
+	if (buf_len <= UINT8_MAX) {
+	    hdr = STRING_1;
+	    u.u8 = buf_len;
+	    hdr_len = 1;
+	} else if (buf_len <= UINT16_MAX) {
+	    hdr = STRING_2_LSB;
+	    u.u16 = buf_len;
+	    hdr_len = 2;
+	} else {
+	    hdr = STRING_4_LSB;
+	    u.u32 = buf_len;
+	    hdr_len = 4;
+	}
+#endif
+	if (deflate) {
+	    assert (method == ZLIB);
+	    hdr |= STRING_DEFLATE;
+	}
     }
-    closure->write_func (closure->closure,
-	                 (unsigned char *) string->string, string->len);
+
+    closure->write_func (closure->closure, (unsigned char *) &hdr, 1);
+    closure->write_func (closure->closure, (unsigned char *) &u, hdr_len);
+    if (deflate) {
+	uint32_t u32 = to_be32 (deflate);
+	closure->write_func (closure->closure, (unsigned char *) &u32, 4);
+    }
+    closure->write_func (closure->closure, (unsigned char *) buf, buf_len);
+
+    if (buf != string->string)
+	free (buf);
 
     return CSI_STATUS_SUCCESS;
 }


More information about the cairo-commit mailing list