Ethereal-dev: [Ethereal-dev] Re: tvb_uncompress() performance improvements

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Jerry Talkington <jtalkington@xxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 9 May 2004 20:28:10 -0700
On Sun, May 09, 2004 at 08:27:31PM -0700, Jerry Talkington wrote:
> Here's a patch to speed up the tvb_uncompress() function.  The previous
> 4k buffer size made uncompressing large bodies extremely slow.  This
> patch makes the minimum buffer 32k, and the default twice as large as
> the uncompressed data, with a maximum of 10Mb.

Man, I need to work on my mutt attachment skills ;)

-- 
GPG public key:
http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x9D5B8762
Index: epan/tvbuff.c
===================================================================
RCS file: /cvsroot/ethereal/epan/tvbuff.c,v
retrieving revision 1.64
diff -u -r1.64 tvbuff.c
--- epan/tvbuff.c	7 May 2004 18:15:24 -0000	1.64
+++ epan/tvbuff.c	10 May 2004 03:21:53 -0000
@@ -2160,22 +2160,35 @@
  * length comprlen.  Returns an uncompressed tvbuffer if uncompression
  * succeeded or NULL if uncompression failed.
  */
-#define TVB_Z_BUFSIZ 4096
+#define TVB_Z_MIN_BUFSIZ 32768
+#define TVB_Z_MAX_BUFSIZ 1048576 * 10
+/* #define TVB_Z_DEBUG 1 */
+#undef TVB_Z_DEBUG
+
 tvbuff_t *
 tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
 {
 	
 
 	gint err = Z_OK;
-	gint bytes_out = 0;
+	guint bytes_out = 0;
 	guint8 *compr = NULL;
 	guint8 *uncompr = NULL;
 	tvbuff_t *uncompr_tvb = NULL;
 	z_streamp strm = NULL;
-	gchar strmbuf[TVB_Z_BUFSIZ];
-	gint inits_done = 0;
+	Bytef *strmbuf = NULL;
+	guint inits_done = 0;
 	gint wbits = MAX_WBITS;
 	guint8 *next = NULL;
+	guint bufsiz = TVB_Z_MIN_BUFSIZ;
+#ifdef TVB_Z_DEBUG
+	guint inflate_passes = 0;
+	guint bytes_in = tvb_length_remaining(tvb, offset);
+#endif
+
+	if (tvb == NULL) {
+		return NULL;
+	}
 
 	strm = g_malloc0(sizeof(z_stream));
 
@@ -2189,41 +2202,70 @@
 		return NULL;
 	}
 
+	/* 
+	 * Assume that the uncompressed data is at least twice as big as
+	 * the compressed size.
+	 */
+	bufsiz = tvb_length_remaining(tvb, offset) * 2;
+
+	if (bufsiz < TVB_Z_MIN_BUFSIZ) {
+		bufsiz = TVB_Z_MIN_BUFSIZ;
+	} else if (bufsiz > TVB_Z_MAX_BUFSIZ) {
+		bufsiz = TVB_Z_MIN_BUFSIZ;
+	}
+
+#ifdef TVB_Z_DEBUG
+	printf("bufsiz: %u bytes\n", bufsiz);
+#endif
+
 	next = compr;
 
 	strm->next_in = next;
 	strm->avail_in = comprlen;
 
-	memset(&strmbuf, 0, TVB_Z_BUFSIZ);
-	strm->next_out = (Bytef *)&strmbuf;
-	strm->avail_out = TVB_Z_BUFSIZ;
+
+	strmbuf = g_malloc0(bufsiz);
+
+	if(strmbuf == NULL) {
+		g_free(compr);
+		return NULL;
+	}
+
+	strm->next_out = strmbuf;
+	strm->avail_out = bufsiz;
 
 	err = inflateInit2(strm, wbits);
 	inits_done = 1;
 	if (err != Z_OK) {
 		g_free(strm);
 		g_free(compr);
+		g_free(strmbuf);
 		return NULL;
 	}
 
 	while (1) {
-		memset(&strmbuf, 0, TVB_Z_BUFSIZ);
-		strm->next_out = (Bytef *)&strmbuf;
-		strm->avail_out = TVB_Z_BUFSIZ;
+		memset(strmbuf, '\0', bufsiz);
+		strm->next_out = strmbuf;
+		strm->avail_out = bufsiz;
 
 		err = inflate(strm, Z_SYNC_FLUSH);
 
 		if (err == Z_OK || err == Z_STREAM_END) {
-			guint bytes_pass = TVB_Z_BUFSIZ - strm->avail_out;
+			guint bytes_pass = bufsiz - strm->avail_out;
+
+#ifdef TVB_Z_DEBUG
+			++inflate_passes;
+#endif
 
 			if (uncompr == NULL) {
-				uncompr = g_memdup(&strmbuf, bytes_pass);
+				uncompr = g_memdup(strmbuf, bytes_pass);
 			} else {
 				guint8 *new_data = g_malloc0(bytes_out +
 				    bytes_pass);
 
 				if (new_data == NULL) {
 					g_free(strm);
+					g_free(strmbuf);
 					g_free(compr);
 
 					if (uncompr != NULL) {
@@ -2234,7 +2276,7 @@
 				}
 				
 				g_memmove(new_data, uncompr, bytes_out);
-				g_memmove((new_data + bytes_out), &strmbuf,
+				g_memmove((new_data + bytes_out), strmbuf,
 				    bytes_pass);
 
 				g_free(uncompr);
@@ -2246,6 +2288,7 @@
 			if ( err == Z_STREAM_END) {
 				inflateEnd(strm);
 				g_free(strm);
+				g_free(strmbuf);
 				break;
 			}
 		} else if (err == Z_BUF_ERROR) {
@@ -2256,6 +2299,7 @@
 			 */
 
 			g_free(strm);
+			g_free(strmbuf);
 
 			if (uncompr != NULL) {
 				break;
@@ -2289,6 +2333,7 @@
 			} else {
 				g_free(strm);
 				g_free(compr);
+				g_free(strmbuf);
 				return NULL;
 			}
 
@@ -2350,9 +2395,9 @@
 			strm->next_in = next;
 			strm->avail_in = comprlen;
 
-			memset(&strmbuf, 0, TVB_Z_BUFSIZ);
-			strm->next_out = (Bytef *)&strmbuf;
-			strm->avail_out = TVB_Z_BUFSIZ;
+			memset(strmbuf, '\0', bufsiz);
+			strm->next_out = strmbuf;
+			strm->avail_out = bufsiz;
 
 			err = inflateInit2(strm, wbits);
 				
@@ -2360,6 +2405,7 @@
 			
 			if (err != Z_OK) {
 				g_free(strm);
+				g_free(strmbuf);
 				g_free(compr);
 				g_free(uncompr);
 
@@ -2367,6 +2413,7 @@
 			}
 		} else {
 			g_free(strm);
+			g_free(strmbuf);
 			g_free(compr);
 
 			if (uncompr == NULL) {
@@ -2376,6 +2423,11 @@
 			break;
 		}
 	}
+
+#ifdef TVB_Z_DEBUG
+	printf("inflate() total passes: %u\n", inflate_passes);
+	printf("bytes  in: %u\nbytes out: %u\n\n", bytes_in, bytes_out);
+#endif
 	
 	if (uncompr != NULL) {
 		uncompr_tvb =  tvb_new_real_data((guint8*) uncompr, bytes_out,