]> git.ipfire.org Git - thirdparty/rsync.git/commitdiff
alloc: revert "zero all new memory from allocations" (#959)
authorAndrew Tridgell <andrew@tridgell.net>
Thu, 4 Jun 2026 04:43:38 +0000 (14:43 +1000)
committerAndrew Tridgell <andrew@tridgell.net>
Thu, 4 Jun 2026 20:35:12 +0000 (06:35 +1000)
Commit d046525d made my_alloc() calloc every fresh allocation and made
expand_item_list() memset the freshly grown tail, to hand out predictably
zeroed memory.  But that forces the kernel to back pages callers never
touch: each per-directory file_list pre-allocates a FLIST_START-entry
(32768) pointer array -- 256KB -- and calloc now zeroes the whole array
even for an empty directory.  With incremental recursion over many
directories the resident set explodes; 80000 empty dirs went from ~336MB
to ~10.8GB.

Restore the pre-d046525d malloc/calloc split: fresh allocations use
malloc (so untouched tails stay lazy) and only explicit do_calloc
requests (new_array0) are zeroed.  Callers that need zeroed memory
already ask for it, and the full test suite passes.

Fixes: #959
util1.c
util2.c

diff --git a/util1.c b/util1.c
index 12361057af321dca2873d9dc2d32f73f8a41d298..7a1f24b54e0d62f0b8cc1be03efef250961a4e99 100644 (file)
--- a/util1.c
+++ b/util1.c
@@ -1788,8 +1788,6 @@ void *expand_item_list(item_list *lp, size_t item_size, const char *desc, int in
                                new_ptr == lp->items ? " not" : "");
                }
 
-               memset((char *)new_ptr + lp->malloced * item_size, 0,
-                      (expand_size - lp->malloced) * item_size);
                lp->items = new_ptr;
                lp->malloced = expand_size;
        }
diff --git a/util2.c b/util2.c
index ce6f7de146d71924edfb3f06749c983f44a5b7cd..b59bff0a0b541b8f6837f6d87938ced8e5bac9b9 100644 (file)
--- a/util2.c
+++ b/util2.c
@@ -79,7 +79,9 @@ void *my_alloc(void *ptr, size_t num, size_t size, const char *file, int line)
                        who_am_i(), do_big_num(max_alloc, 0, NULL), src_file(file), line);
                exit_cleanup(RERR_MALLOC);
        }
-       if (!ptr || ptr == do_calloc)
+       if (!ptr)
+               ptr = malloc(num * size);
+       else if (ptr == do_calloc)
                ptr = calloc(num, size);
        else
                ptr = realloc(ptr, num * size);