threads / discuss / 8615

Fix up ugly open-coded "alloc_nr()" user in object.c

Subject: Fix up ugly open-coded "alloc_nr()" user in object.c

## tl;dr

4 messages between Jun 16, 2007 and Jun 16, 2007.

replies: 3people: 3as markdown or json

Linus Torvalds· Jun 16, 2007, 17:30 UTC · lore

When adding objects to the object/mode array, we used to have our own alloc_nr() implementation, rather than use the normal one.

And since the normal one is arguably a bit nicer (still grows the allocation exponentially, just not by more-than-doubling it every time), why not just use it?

That array of objects ends up being really quite big when you force a while repack of a big project, and while we might end up doing a few more xreallocs in the process, we also hopefully don't end up with a final allocation that is quite as wastefully big.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
  That was an overkill of a situation for a trivial patch that I don't 
  think is in the least interesting or even important. I really don't care 
  if you take this, Junio, but it seemed the obvious one-liner to do, so 
  I'm sending it in anyway.
 object.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/object.c b/object.c
index 16793d9..fdd6ceb 100644
--- a/object.c
+++ b/object.c
@@ -245,7 +245,7 @@ void add_object_array_with_mode(struct object *obj, const char *name, struct obj
 	struct object_array_entry *objects = array->objects;
 
 	if (nr >= alloc) {
-		alloc = (alloc + 32) * 2;
+		alloc = alloc_nr(alloc);
 		objects = xrealloc(objects, alloc * sizeof(*objects));
 		array->alloc = alloc;
 		array->objects = objects;
Jeff King· Jun 16, 2007, 18:21 UTC · re: Linus Torvalds · lore

Re: Fix up ugly open-coded "alloc_nr()" user in object.c

On Sat, Jun 16, 2007 at 10:30:22AM -0700, Linus Torvalds wrote:
Show 6 quoted lines
> When adding objects to the object/mode array, we used to have our own 
> alloc_nr() implementation, rather than use the normal one.
> 
> And since the normal one is arguably a bit nicer (still grows the 
> allocation exponentially, just not by more-than-doubling it every time), 
> why not just use it?

How about using the new ALLOC_GROW macro to make it even shorter? I also got rid of the aliased variables, which IMO just make it harder to see what's going on.

---
 object.c |   19 +++++--------------
 1 files changed, 5 insertions(+), 14 deletions(-)
diff --git a/object.c b/object.c
index 16793d9..064e423 100644
--- a/object.c
+++ b/object.c
@@ -240,18 +240,9 @@ void add_object_array(struct object *obj, const char *name, struct object_array
 
 void add_object_array_with_mode(struct object *obj, const char *name, struct object_array *array, unsigned mode)
 {
-	unsigned nr = array->nr;
-	unsigned alloc = array->alloc;
-	struct object_array_entry *objects = array->objects;
-
-	if (nr >= alloc) {
-		alloc = (alloc + 32) * 2;
-		objects = xrealloc(objects, alloc * sizeof(*objects));
-		array->alloc = alloc;
-		array->objects = objects;
-	}
-	objects[nr].item = obj;
-	objects[nr].name = name;
-	objects[nr].mode = mode;
-	array->nr = ++nr;
+	ALLOC_GROW(array->objects, array->nr, array->alloc);
+	array->objects[array->nr].item = obj;
+	array->objects[array->nr].name = name;
+	array->objects[array->nr].mode = mode;
+	array->nr++;
 }
Olivier Galibert· Jun 16, 2007, 22:15 UTC · re: Jeff King · lore

Re: Fix up ugly open-coded "alloc_nr()" user in object.c

On Sat, Jun 16, 2007 at 02:21:34PM -0400, Jeff King wrote:
> How about using the new ALLOC_GROW macro to make it even shorter? I also
> got rid of the aliased variables, which IMO just make it harder to see
Show 6 quoted lines
> what's going on.
> +	ALLOC_GROW(array->objects, array->nr, array->alloc);
> +	array->objects[array->nr].item = obj;
> +	array->objects[array->nr].name = name;
> +	array->objects[array->nr].mode = mode;
> +	array->nr++;
Unless the ALLOC_GROW semantics are weird, shouldn't that be:
  ALLOC_GROW(array->objects, array->nr+1, array->alloc);
  OG.
Jeff King· Jun 16, 2007, 22:37 UTC · re: Olivier Galibert · lore

Re: Fix up ugly open-coded "alloc_nr()" user in object.c

On Sun, Jun 17, 2007 at 12:15:06AM +0200, Olivier Galibert wrote:
> > +	ALLOC_GROW(array->objects, array->nr, array->alloc);
> 
> Unless the ALLOC_GROW semantics are weird, shouldn't that be:
>   ALLOC_GROW(array->objects, array->nr+1, array->alloc);

The semantics are weird. They never seemed so to me before, since it was replacing some "grow by 1" areas where it is natural to assume that you need just one spot more. But the way Junio commented it and tweaked it, it can handle arbitrary growth (which is much better), but that means we are overly conservative about when to grow.

Junio, patch is below (call-sites using bare 'nr' need to be 'nr+1', but I will fix those up in a separate patch since they are in next and this is in master).

-- >8 -- fix ALLOC_GROW off-by-one

The ALLOC_GROW macro will never let us fill the array completely, instead allocating an extra chunk if that would be the case. This is because the 'nr' argument was originally treated as "how much we do have now" instead of "how much do we want". The latter makes much more sense because you can grow by more than one item.

This off-by-one never resulted in an error because it meant we were overly conservative about when to allocate. Any callers which passed "how we have now" need to be updated, or they will fail to allocate enough.

Signed-off-by: Jeff King <peff@peff.net>
---
 cache.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/cache.h b/cache.h
index c914c1c..ed83d92 100644
--- a/cache.h
+++ b/cache.h
@@ -234,7 +234,7 @@ extern void verify_non_filename(const char *prefix, const char *name);
  */
 #define ALLOC_GROW(x, nr, alloc) \
 	do { \
-		if ((nr) >= alloc) { \
+		if ((nr) > alloc) { \
 			if (alloc_nr(alloc) < (nr)) \
 				alloc = (nr); \
 			else \

← back to recent threads