diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-01-04 17:32:46 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2013-01-05 21:10:35 +0000 |
commit | 45a4b42a361eb791c571b201e11c3505a0a1a396 (patch) | |
tree | 726e108de16303b8e52a73d3309a4dadbefbbc59 | |
parent | 9194904fa838a115b4dc58e5bff7a235cc2a9a7a (diff) | |
download | cairo-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.ac | 12 | ||||
-rw-r--r-- | util/cairo-script/Makefile.am | 2 | ||||
-rw-r--r-- | util/cairo-script/cairo-script-file.c | 32 | ||||
-rw-r--r-- | util/cairo-script/cairo-script-objects.c | 3 | ||||
-rw-r--r-- | util/cairo-script/cairo-script-operators.c | 45 | ||||
-rw-r--r-- | util/cairo-script/cairo-script-private.h | 5 | ||||
-rw-r--r-- | util/cairo-script/cairo-script-scanner.c | 184 |
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; } |