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>
This commit is contained in:
Chris Wilson 2013-01-04 17:32:46 +00:00
parent 9194904fa8
commit 45a4b42a36
7 changed files with 226 additions and 55 deletions

View file

@ -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])

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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;
#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;
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);
}
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;
#endif
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);
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;
}