git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Be more careful about zlib return values
@ 2007-03-20 18:38 Linus Torvalds
  2007-03-21  8:11 ` Junio C Hamano
  0 siblings, 1 reply; 3+ messages in thread
From: Linus Torvalds @ 2007-03-20 18:38 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List


When creating a new object, we use "deflate(stream, Z_FINISH)" in a loop 
until it no longer returns Z_OK, and then we do "deflateEnd()" to finish 
up business.

That should all work, but the fact is, it's not how you're _supposed_ to 
use the zlib return values properly:

 - deflate() should never return Z_OK in the first place, except if we 
   need to increase the output buffer size (which we're not doing, and 
   should never need to do, since we pre-allocated a buffer that is 
   supposed to be able to hold the output in full). So the "while()" loop 
   was incorrect: Z_OK doesn't actually mean "ok, continue", it means "ok, 
   allocate more memory for me and continue"!

 - if we got an error return, we would consider it to be end-of-stream, 
   but it could be some internal zlib error.  In short, we should check 
   for Z_STREAM_END explicitly, since that's the only valid return value 
   anyway for the Z_FINISH case.

 - we never checked deflateEnd() return codes at all.

Now, admittedly, none of these issues should ever happen, unless there is 
some internal bug in zlib. So this patch should make zero difference, but 
it seems to be the right thing to do.

We should probablybe anal and check the return value of "deflateInit()" 
too!

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---

Somebody who has worked more with zlib should probably double-check me, 
but this is what <zlib.h> claims is the right thing to do.

		Linus

---
 sha1_file.c |   13 +++++++++----
 1 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index c445a24..bfcbbea 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1947,7 +1947,7 @@ int hash_sha1_file(void *buf, unsigned long len, const char *type,
 
 int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
 {
-	int size;
+	int size, ret;
 	unsigned char *compressed;
 	z_stream stream;
 	unsigned char sha1[20];
@@ -2007,9 +2007,14 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
 	/* Then the data itself.. */
 	stream.next_in = buf;
 	stream.avail_in = len;
-	while (deflate(&stream, Z_FINISH) == Z_OK)
-		/* nothing */;
-	deflateEnd(&stream);
+	ret = deflate(&stream, Z_FINISH);
+	if (ret != Z_STREAM_END)
+		die("unable to deflate new object %s (%d)", sha1_to_hex(sha1), ret);
+
+	ret = deflateEnd(&stream);
+	if (ret != Z_OK)
+		die("deflateEnd on object %s failed (%d)", sha1_to_hex(sha1), ret);
+
 	size = stream.total_out;
 
 	if (write_buffer(fd, compressed, size) < 0)

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: Be more careful about zlib return values
  2007-03-20 18:38 Be more careful about zlib return values Linus Torvalds
@ 2007-03-21  8:11 ` Junio C Hamano
  2007-03-21 15:29   ` Linus Torvalds
  0 siblings, 1 reply; 3+ messages in thread
From: Junio C Hamano @ 2007-03-21  8:11 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Git Mailing List

Linus Torvalds <torvalds@linux-foundation.org> writes:

> When creating a new object, we use "deflate(stream, Z_FINISH)" in a loop 
> until it no longer returns Z_OK, and then we do "deflateEnd()" to finish 
> up business.
>
> That should all work, but the fact is, it's not how you're _supposed_ to 
> use the zlib return values properly:
> ...
> Somebody who has worked more with zlib should probably double-check me, 
> but this is what <zlib.h> claims is the right thing to do.
>
> 		Linus

I am observing a very curious performance regression with this
patch.  I do not see anything obviously wrong correctness-wise
nor performance-wise with it.

This is driving me crazy, as the benchmark is in that repository
with a 1.7GB pack:

	$ git-rev-list HEAD -- org.eclipse.debug.ui/ >/dev/null

and the patch is ONLY ABOUT write_sha1_file() codepath.  The function
should not even be called!

Without the patch (3 typical runs):

16.16user 0.16system 0:16.32elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+79008minor)pagefaults 0swaps
15.84user 0.14system 0:16.02elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+79009minor)pagefaults 0swaps
16.04user 0.12system 0:16.17elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+79008minor)pagefaults 0swaps

With the patch:

17.62user 0.20system 0:17.94elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+79009minor)pagefaults 0swaps
17.79user 0.19system 0:18.03elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+79011minor)pagefaults 0swaps
17.40user 0.14system 0:17.63elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+79009minor)pagefaults 0swaps

Another funny thing is that if I replace the body of
write_sha1_file() with just:

int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
{
	setup_object_header(NULL, NULL, 0);
	die("foo");
}

I get somewhat faster number.

I guess I probably should write it off as some curiosity coming
from insn cacheline bouncing between hot functions, that is
caused by the size of this unused function changing.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Be more careful about zlib return values
  2007-03-21  8:11 ` Junio C Hamano
@ 2007-03-21 15:29   ` Linus Torvalds
  0 siblings, 0 replies; 3+ messages in thread
From: Linus Torvalds @ 2007-03-21 15:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List



On Wed, 21 Mar 2007, Junio C Hamano wrote:
> 
> I am observing a very curious performance regression with this
> patch.  I do not see anything obviously wrong correctness-wise
> nor performance-wise with it.

Ok, the test you are doing won't call the write function at all, so the 
performance effect you see is almost certainly due to [un]lucky I$ 
placement. It happens..

		Linus

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2007-03-21 15:30 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-20 18:38 Be more careful about zlib return values Linus Torvalds
2007-03-21  8:11 ` Junio C Hamano
2007-03-21 15:29   ` Linus Torvalds

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).