cvs: php4 /ext/bz2 bz2.c

From: Date: Mon, 29 Oct 2001 02:29:13 +0000
Subject: cvs: php4 /ext/bz2 bz2.c
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-8016@lists.php.net to get a copy of this message
jeroen Sun Oct 28 21:29:13 2001 EDT Modified files: /php4/ext/bz2 bz2.c Log: Fix performance of bz(de)compress: - don't copy possibly large strings if it's not necessary - no slow linear incremental buffering until it succeeds on bzdecompress, but exponential and with smart starting value. - nuke some unnecessary vars - Performance gain of bzdecompress: about 50% in case of 100kB uncompressed data, 95% incase of 500kB uncompressed data. Memory gain (both compress and decompress): at least 50% of the size of the returned data in case of decompress, the size of the returned data in case of compress. And: - Output FALSE & warning in case of error, and not a positive integer This fixes bug 13860 Index: php4/ext/bz2/bz2.c diff -u php4/ext/bz2/bz2.c:1.25 php4/ext/bz2/bz2.c:1.26 --- php4/ext/bz2/bz2.c:1.25 Thu Oct 11 19:32:29 2001 +++ php4/ext/bz2/bz2.c Sun Oct 28 21:29:13 2001 @@ -13,10 +13,11 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Sterling Hughes <sterling@php.net> | + | Jeroen van Wolffelaar <jeroen@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: bz2.c,v 1.25 2001/10/11 23:32:29 ssb Exp $ */ +/* $Id: bz2.c,v 1.26 2001/10/29 02:29:13 jeroen Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -42,8 +43,10 @@ #define PHP_BZ_ERRSTR 1 #define PHP_BZ_ERRBOTH 2 -/* Blocksize of the decompression buffer */ -#define PHP_BZ_DECOMPRESS_SIZE 4096 +/* Incrementation of the buffer on each try. Uncompressedsize * + * (1-DECOMPRESS_INCREMENT) is the maximum amount of temporarily wasted + * memory. Higher numbers will increase speed. */ +#define PHP_BZ_DECOMPRESS_INCREMENT 1.50 function_entry bz2_functions[] = { PHP_FE(bzopen, NULL) @@ -282,51 +285,42 @@ char *dest = NULL; /* Destination to place the compressed data into */ int error, /* Error Container */ block_size = 4, /* Block size for compression algorithm */ - work_factor = 0, /* Work factor for compression algorithm */ - argc = ZEND_NUM_ARGS(); /* Argument count */ - unsigned int size, /* The size to "realloc" if the initial buffer wasn't big enough */ - source_len, /* Length of the source data */ - dest_len; /* Length of the destination buffer */ + work_factor = 0; /* Work factor for compression algorithm */ + unsigned int size; /* The size to "realloc" if the initial buffer wasn't big enough */ - if (argc < 1 || argc > 3 || - zend_get_parameters_ex(argc, &source, &zblock_size, &zwork_factor) == FAILURE) { + if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 3 || + zend_get_parameters_ex(ZEND_NUM_ARGS(), &source, &zblock_size, &zwork_factor) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(source); - /* Assign them to easy to use variables, dest_len is initially the length of the data - + .01 x length of data + 600 which is the largest size the results of the compression - could possibly be, at least that's what the libbz2 docs say (thanks to jeremy@nirvani.net - for pointing this out). */ - source_len = Z_STRLEN_PP(source); - dest_len = Z_STRLEN_PP(source) + (0.01 * Z_STRLEN_PP(source)) + 600; - - /* Allocate the destination buffer */ - dest = emalloc(dest_len + 1); + /* Allocate the destination buffer. The length of the data + .01 x length + * of data + 600 which is the largest size the results of the compression + * could possibly be, at least that's what the libbz2 docs say (thanks to + * jeremy@nirvani.net for pointing this out). */ + dest = emalloc(Z_STRLEN_PP(source) + (0.01 * Z_STRLEN_PP(source)) + 601); /* Handle the optional arguments */ - if (argc > 1) { + if (ZEND_NUM_ARGS() > 1) { convert_to_long_ex(zblock_size); block_size = Z_LVAL_PP(zblock_size); } - if (argc > 2) { + if (ZEND_NUM_ARGS() > 2) { convert_to_long_ex(zwork_factor); work_factor = Z_LVAL_PP(zwork_factor); } - error = BZ2_bzBuffToBuffCompress(dest, &size, Z_STRVAL_PP(source), source_len, block_size, 0, work_factor); + error = BZ2_bzBuffToBuffCompress(dest, &size, Z_STRVAL_PP(source), Z_STRLEN_PP(source), block_size, 0, work_factor); if (error != BZ_OK) { - RETVAL_LONG(error); - } else { - /* Copy the buffer, we have perhaps allocate alot more than we need, - so we want to copy the correct amount and then free the in-exactly - allocated buffer */ - RETVAL_STRINGL(dest, size, 1); + efree(dest); + php_error(E_WARNING, "bzcompress failed"); + RETURN_FALSE; } - - /* Free the buffer */ - efree(dest); + + /* size down... */ + dest = erealloc(dest, size); + RETURN_STRINGL(dest, size, 0); } /* }}} */ @@ -336,48 +330,47 @@ { zval **source, /* Source data to decompress */ **zsmall; /* (Optional) user specified small */ - char *dest = emalloc(PHP_BZ_DECOMPRESS_SIZE); /* Destination buffer, initially allocated */ + char *dest = NULL; /* Destination buffer */ int error, /* Error container */ - iter = 1, /* Iteration count for the compression loop */ size, /* Current size to realloc the dest buffer to */ - dest_len = PHP_BZ_DECOMPRESS_SIZE, /* Size of the destination length */ - small = 0, /* The actual small */ - argc = ZEND_NUM_ARGS(); /* Argument count */ + small = 0; /* The actual small */ - if (argc < 1 || argc > 2 || - zend_get_parameters_ex(argc, &source, &zsmall) == FAILURE) { + if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 || + zend_get_parameters_ex(ZEND_NUM_ARGS(), &source, &zsmall) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(source); /* optional small argument handling */ - if (argc > 1) { + if (ZEND_NUM_ARGS() > 1) { convert_to_long_ex(zsmall); small = Z_LVAL_PP(zsmall); } + + /* result will be at least the compressed size */ + size = Z_STRLEN_PP(source); /* (de)Compression Loop */ do { + /* exponentially increment size. */ + size = PHP_BZ_DECOMPRESS_INCREMENT * (float)size; + /* Handle the (re)allocation of the buffer */ - size = dest_len * iter; - if (iter > 1) { - dest = erealloc(dest, size); - } - ++iter; + dest = dest? erealloc(dest, size) : emalloc(size); /* Perform the decompression */ error = BZ2_bzBuffToBuffDecompress(dest, &size, Z_STRVAL_PP(source), Z_STRLEN_PP(source), small, 0); } while (error == BZ_OUTBUFF_FULL); if (error != BZ_OK) { - RETVAL_LONG(error); - } else { - /* we might have allocated a little to much, so copy the exact size and free the - in-exactly allocated buffer */ - RETVAL_STRINGL(dest, size, 1); + efree(dest); + php_error(E_WARNING, "bzdecompress failed"); + RETURN_FALSE; } - - efree(dest); + + /* we might have allocated a little to much, so realloc down. */ + dest = erealloc(dest, size); + RETURN_STRINGL(dest, size, 0); } /* }}} */

« previous php.cvs (#8016) next »