cvs: php4 /ext/bz2 bz2.c
| From: | Jeroen van Wolffelaar | 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);
}
/* }}} */