summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrian m. carlson <bk2204@github.com>2019-07-16 21:54:10 +0000
committerbrian m. carlson <bk2204@github.com>2019-07-17 13:37:41 +0000
commitc4df926b32d65f3e84da316bc1fa858e09baa1ac (patch)
tree011efa42949d7b74211893eec1644487d3e40ddb
parentf92d495d44bff2bdb6fd99524a93986ea268c9e8 (diff)
downloadlibgit2-c4df926b32d65f3e84da316bc1fa858e09baa1ac.tar.gz
pack-objects: allocate memory more efficiently
The packbuilder code allocates memory in chunks. When it needs to allocate, it tries to add 1024 to the number of objects and multiply by 3/2. However, it actually multiplies by 1 instead, since it performs an integral division in the expression "3 / 2" and only then multiplies by the increased number of objects. The current behavior causes the code to waste massive amounts of time copying memory when it reallocates, causing inserting all non-blob objects in the Linux repository into a new pack to take some indeterminate time greater than 5 minutes instead of 52 seconds. Correct this error by first dividing by two, and only then multiplying by 3. We still check for overflow for the multiplication, which is the only part that can overflow. This appears to be the only place in the code base which has this problem.
-rw-r--r--src/pack-objects.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/src/pack-objects.c b/src/pack-objects.c
index 32f51a3fd..49ded4a2e 100644
--- a/src/pack-objects.c
+++ b/src/pack-objects.c
@@ -223,7 +223,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
if (pb->nr_objects >= pb->nr_alloc) {
GIT_ERROR_CHECK_ALLOC_ADD(&newsize, pb->nr_alloc, 1024);
- GIT_ERROR_CHECK_ALLOC_MULTIPLY(&newsize, newsize, 3 / 2);
+ GIT_ERROR_CHECK_ALLOC_MULTIPLY(&newsize, newsize / 2, 3);
if (!git__is_uint32(newsize)) {
git_error_set(GIT_ERROR_NOMEMORY, "packfile too large to fit in memory.");