summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-01-04 17:32:46 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2013-01-05 21:10:35 +0000
commit45a4b42a361eb791c571b201e11c3505a0a1a396 (patch)
tree726e108de16303b8e52a73d3309a4dadbefbbc59
parent9194904fa838a115b4dc58e5bff7a235cc2a9a7a (diff)
downloadcairo-45a4b42a361eb791c571b201e11c3505a0a1a396.tar.gz
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@chris-wilson.co.uk>
-rw-r--r--configure.ac12
-rw-r--r--util/cairo-script/Makefile.am2
-rw-r--r--util/cairo-script/cairo-script-file.c32
-rw-r--r--util/cairo-script/cairo-script-objects.c3
-rw-r--r--util/cairo-script/cairo-script-operators.c45
-rw-r--r--util/cairo-script/cairo-script-private.h5
-rw-r--r--util/cairo-script/cairo-script-scanner.c184
7 files changed, 227 insertions, 56 deletions
diff --git a/configure.ac b/configure.ac
index fc8d3b196..31123c72b 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 c2f55a3d4..d5c2998ac 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 34f296405..85d292c47 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 adf616072..a625489b1 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 4b7d4fc40..9ba24f8fb 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 3286bb4f9..6bf41b4e5 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 eeec6861f..4254aa01e 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;
}