"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Omar Polo <op@omarpolo.com>
Subject:
reduce the reallocarray() calls in read_fileindex_path()
To:
gameoftrees@openbsd.org
Date:
Fri, 28 Jul 2023 10:52:25 +0200

Download raw body.

Thread
We spend a decent amount of time reading the fileindex in
reallocarray().  The fileindex has the path stored (NUL included) with
a final padding to the next multiple of eight bytes, so we read 8
bytes per iteration.  That's fine.  Calling reallocarray() to increase
the size of the allocation by 8 byte each iteration however is a
waste.

Instead, use a local buffer and strdup() on exit.

Git paths don't have an implicit length limit, but this is the
fileindex of a worktree and AFAIK we can't check-out files whose path
is more than PATH_MAX anyway.

ok?

-----------------------------------------------
commit 1772f04de18f32fe8a4b91869eaf51da7ce85167
from: Omar Polo <op@omarpolo.com>
date: Fri Jul 28 08:48:01 2023 UTC
 
 read_fileindex_path: avoid many reallocarray() calls, use local buffer
 
diff c2eedbd13a618c74343a8d8d645acecdfb677b8f 1772f04de18f32fe8a4b91869eaf51da7ce85167
commit - c2eedbd13a618c74343a8d8d645acecdfb677b8f
commit + 1772f04de18f32fe8a4b91869eaf51da7ce85167
blob - 1575b0dd69dc7a97d0d393fa46ba56957b8ee0b7
blob + 62f7df1b95d5d56bd0b23c83df32e7d74f3d4b00
--- lib/fileindex.c
+++ lib/fileindex.c
@@ -579,38 +579,26 @@ read_fileindex_path(char **path, struct got_hash *ctx,
 static const struct got_error *
 read_fileindex_path(char **path, struct got_hash *ctx, FILE *infile)
 {
-	const struct got_error *err = NULL;
 	const size_t chunk_size = 8;
-	size_t n, len = 0, totlen = chunk_size;
+	char p[PATH_MAX];
+	size_t n, len = 0;
 
-	*path = malloc(totlen);
-	if (*path == NULL)
-		return got_error_from_errno("malloc");
-
 	do {
-		if (len + chunk_size > totlen) {
-			char *p = reallocarray(*path, totlen + chunk_size, 1);
-			if (p == NULL) {
-				err = got_error_from_errno("reallocarray");
-				break;
-			}
-			totlen += chunk_size;
-			*path = p;
-		}
-		n = fread(*path + len, 1, chunk_size, infile);
-		if (n != chunk_size) {
-			err = got_ferror(infile, GOT_ERR_FILEIDX_BAD);
-			break;
-		}
-		got_hash_update(ctx, *path + len, chunk_size);
+		if (len + chunk_size > sizeof(p))
+			return got_error(GOT_ERR_FILEIDX_BAD);
+
+		n = fread(&p[len], 1, chunk_size, infile);
+		if (n != chunk_size)
+			return got_ferror(infile, GOT_ERR_FILEIDX_BAD);
+
+		got_hash_update(ctx, &p[len], chunk_size);
 		len += chunk_size;
-	} while (memchr(*path + len - chunk_size, '\0', chunk_size) == NULL);
+	} while (memchr(&p[len - chunk_size], '\0', chunk_size) == NULL);
 
-	if (err) {
-		free(*path);
-		*path = NULL;
-	}
-	return err;
+	*path = strdup(p);
+	if (*path == NULL)
+		return got_error_from_errno("strdup");
+	return NULL;
 }
 
 static const struct got_error *