Skip to content

Commit

Permalink
sha1write: don't copy full sized buffers
Browse files Browse the repository at this point in the history
No need to memcpy() source buffer data when we might just process the
data in place instead of accumulating it into a separate buffer.
This is the case when a whole buffer would have been copied, summed,
written out and then discarded right away.

Also move the CRC32 processing within the loop so the data is more likely
to remain in the L1 CPU cache between the CRC32 sum, SHA1 sum and the
write call.

Signed-off-by: Nicolas Pitre <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
  • Loading branch information
Nicolas Pitre authored and gitster committed Sep 3, 2008
1 parent 59d94bc commit a8032d1
Showing 1 changed file with 17 additions and 10 deletions.
27 changes: 17 additions & 10 deletions csum-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@
#include "progress.h"
#include "csum-file.h"

static void sha1flush(struct sha1file *f, unsigned int count)
static void sha1flush(struct sha1file *f, void *buf, unsigned int count)
{
void *buf = f->buffer;

for (;;) {
int ret = xwrite(f->fd, buf, count);
if (ret > 0) {
Expand All @@ -39,15 +37,15 @@ int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags)

if (offset) {
SHA1_Update(&f->ctx, f->buffer, offset);
sha1flush(f, offset);
sha1flush(f, f->buffer, offset);
f->offset = 0;
}
SHA1_Final(f->buffer, &f->ctx);
if (result)
hashcpy(result, f->buffer);
if (flags & (CSUM_CLOSE | CSUM_FSYNC)) {
/* write checksum and close fd */
sha1flush(f, 20);
sha1flush(f, f->buffer, 20);
if (flags & CSUM_FSYNC)
fsync_or_die(f->fd, f->name);
if (close(f->fd))
Expand All @@ -62,21 +60,30 @@ int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags)

int sha1write(struct sha1file *f, void *buf, unsigned int count)
{
if (f->do_crc)
f->crc32 = crc32(f->crc32, buf, count);
while (count) {
unsigned offset = f->offset;
unsigned left = sizeof(f->buffer) - offset;
unsigned nr = count > left ? left : count;
void *data;

if (f->do_crc)
f->crc32 = crc32(f->crc32, buf, nr);

if (nr == sizeof(f->buffer)) {
/* process full buffer directly without copy */
data = buf;
} else {
memcpy(f->buffer + offset, buf, nr);
data = f->buffer;
}

memcpy(f->buffer + offset, buf, nr);
count -= nr;
offset += nr;
buf = (char *) buf + nr;
left -= nr;
if (!left) {
SHA1_Update(&f->ctx, f->buffer, offset);
sha1flush(f, offset);
SHA1_Update(&f->ctx, data, offset);
sha1flush(f, data, offset);
offset = 0;
}
f->offset = offset;
Expand Down

0 comments on commit a8032d1

Please sign in to comment.