git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH] pack-bitmaps: plug memory leak, fix allocation size for recent_bitmaps
@ 2015-05-18 23:24 René Scharfe
  2015-05-19  0:57 ` Stefan Beller
  2015-05-19  2:23 ` Jeff King
  0 siblings, 2 replies; 6+ messages in thread
From: René Scharfe @ 2015-05-18 23:24 UTC (permalink / raw
  To: Git Mailing List; +Cc: Stefan Beller, Jeff King, Vicent Marti

Use an automatic variable for recent_bitmaps, an array of pointers.
This way we don't allocate too much and don't have to free the memory
at the end.  The old code over-allocated because it reserved enough
memory to store all of the structs it is only pointing to and never
freed it.  160 64-bit pointers take up 1280 bytes, which is not too
much to be placed on the stack.

MAX_XOR_OFFSET is turned into a preprocessor constant to make it
constant enough for use in an non-variable array declaration.

Noticed-by: Stefan Beller <stefanbeller@gmail.com>
Suggested-by: Jeff King <peff@peff.net>
Signed-off-by: Rene Scharfe <l.s.r@web.de>
---
This seems to have fallen through the cracks, or did I just miss it?

 pack-bitmap.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/pack-bitmap.c b/pack-bitmap.c
index 62a98cc..e5abb8a 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -209,14 +209,12 @@ static inline uint8_t read_u8(const unsigned char *buffer, size_t *pos)
 	return buffer[(*pos)++];
 }
 
+#define MAX_XOR_OFFSET 160
+
 static int load_bitmap_entries_v1(struct bitmap_index *index)
 {
-	static const size_t MAX_XOR_OFFSET = 160;
-
 	uint32_t i;
-	struct stored_bitmap **recent_bitmaps;
-
-	recent_bitmaps = xcalloc(MAX_XOR_OFFSET, sizeof(struct stored_bitmap));
+	struct stored_bitmap *recent_bitmaps[MAX_XOR_OFFSET] = { NULL };
 
 	for (i = 0; i < index->entry_count; ++i) {
 		int xor_offset, flags;
-- 
2.4.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] pack-bitmaps: plug memory leak, fix allocation size for recent_bitmaps
  2015-05-18 23:24 [PATCH] pack-bitmaps: plug memory leak, fix allocation size for recent_bitmaps René Scharfe
@ 2015-05-19  0:57 ` Stefan Beller
  2015-05-19 20:29   ` René Scharfe
  2015-05-19  2:23 ` Jeff King
  1 sibling, 1 reply; 6+ messages in thread
From: Stefan Beller @ 2015-05-19  0:57 UTC (permalink / raw
  To: René Scharfe
  Cc: Git Mailing List, Stefan Beller, Jeff King, Vicent Marti

On Mon, May 18, 2015 at 4:24 PM, René Scharfe <l.s.r@web.de> wrote:
> Use an automatic variable for recent_bitmaps, an array of pointers.
> This way we don't allocate too much and don't have to free the memory
> at the end.  The old code over-allocated because it reserved enough
> memory to store all of the structs it is only pointing to and never
> freed it.  160 64-bit pointers take up 1280 bytes, which is not too
> much to be placed on the stack.
>
> MAX_XOR_OFFSET is turned into a preprocessor constant to make it
> constant enough for use in an non-variable array declaration.
>
> Noticed-by: Stefan Beller <stefanbeller@gmail.com>
> Suggested-by: Jeff King <peff@peff.net>
> Signed-off-by: Rene Scharfe <l.s.r@web.de>
> ---
> This seems to have fallen through the cracks, or did I just miss it?

I planned on resending it eventually. ;)
But with the usual definition of 'eventually',
it may take a while.

Thanks for picking this up!
Stefan



>
>  pack-bitmap.c | 8 +++-----
>  1 file changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/pack-bitmap.c b/pack-bitmap.c
> index 62a98cc..e5abb8a 100644
> --- a/pack-bitmap.c
> +++ b/pack-bitmap.c
> @@ -209,14 +209,12 @@ static inline uint8_t read_u8(const unsigned char *buffer, size_t *pos)
>         return buffer[(*pos)++];
>  }
>
> +#define MAX_XOR_OFFSET 160
> +
>  static int load_bitmap_entries_v1(struct bitmap_index *index)
>  {
> -       static const size_t MAX_XOR_OFFSET = 160;

Is there a reason why we prefer defines over a  static const size_t here?

> -
>         uint32_t i;
> -       struct stored_bitmap **recent_bitmaps;
> -
> -       recent_bitmaps = xcalloc(MAX_XOR_OFFSET, sizeof(struct stored_bitmap));
> +       struct stored_bitmap *recent_bitmaps[MAX_XOR_OFFSET] = { NULL };

This looks fine to me.

>
>         for (i = 0; i < index->entry_count; ++i) {
>                 int xor_offset, flags;
> --
> 2.4.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] pack-bitmaps: plug memory leak, fix allocation size for recent_bitmaps
  2015-05-18 23:24 [PATCH] pack-bitmaps: plug memory leak, fix allocation size for recent_bitmaps René Scharfe
  2015-05-19  0:57 ` Stefan Beller
@ 2015-05-19  2:23 ` Jeff King
  2015-05-19 19:45   ` Junio C Hamano
  1 sibling, 1 reply; 6+ messages in thread
From: Jeff King @ 2015-05-19  2:23 UTC (permalink / raw
  To: René Scharfe; +Cc: Git Mailing List, Stefan Beller, Vicent Marti

On Tue, May 19, 2015 at 01:24:09AM +0200, René Scharfe wrote:

> Use an automatic variable for recent_bitmaps, an array of pointers.
> This way we don't allocate too much and don't have to free the memory
> at the end.  The old code over-allocated because it reserved enough
> memory to store all of the structs it is only pointing to and never
> freed it.  160 64-bit pointers take up 1280 bytes, which is not too
> much to be placed on the stack.
> 
> MAX_XOR_OFFSET is turned into a preprocessor constant to make it
> constant enough for use in an non-variable array declaration.
> 
> Noticed-by: Stefan Beller <stefanbeller@gmail.com>
> Suggested-by: Jeff King <peff@peff.net>
> Signed-off-by: Rene Scharfe <l.s.r@web.de>
> ---
> This seems to have fallen through the cracks, or did I just miss it?

Thanks, this looks good.

I looked over the function one more time to make sure it is the function
that is wrong, and not my suggestion. :) The current code seems pretty
obviously wrong.

-Peff

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] pack-bitmaps: plug memory leak, fix allocation size for recent_bitmaps
  2015-05-19  2:23 ` Jeff King
@ 2015-05-19 19:45   ` Junio C Hamano
  2015-05-19 21:19     ` Jeff King
  0 siblings, 1 reply; 6+ messages in thread
From: Junio C Hamano @ 2015-05-19 19:45 UTC (permalink / raw
  To: Jeff King
  Cc: René Scharfe, Git Mailing List, Stefan Beller, Vicent Marti

Jeff King <peff@peff.net> writes:

> On Tue, May 19, 2015 at 01:24:09AM +0200, René Scharfe wrote:
>
>> Use an automatic variable for recent_bitmaps, an array of pointers.
>> This way we don't allocate too much and don't have to free the memory
>> at the end.  The old code over-allocated because it reserved enough
>> memory to store all of the structs it is only pointing to and never
>> freed it.  160 64-bit pointers take up 1280 bytes, which is not too
>> much to be placed on the stack.
>> 
>> MAX_XOR_OFFSET is turned into a preprocessor constant to make it
>> constant enough for use in an non-variable array declaration.
>> 
>> Noticed-by: Stefan Beller <stefanbeller@gmail.com>
>> Suggested-by: Jeff King <peff@peff.net>
>> Signed-off-by: Rene Scharfe <l.s.r@web.de>
>> ---
>> This seems to have fallen through the cracks, or did I just miss it?
>
> Thanks, this looks good.
>
> I looked over the function one more time to make sure it is the function
> that is wrong, and not my suggestion. :) The current code seems pretty
> obviously wrong.

I actually cannot guess what the current code is trying to do.  Was
it an attempt to cache that many entries, but instead allocated and
discarded the space it tried to use as a cache every time?

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] pack-bitmaps: plug memory leak, fix allocation size for recent_bitmaps
  2015-05-19  0:57 ` Stefan Beller
@ 2015-05-19 20:29   ` René Scharfe
  0 siblings, 0 replies; 6+ messages in thread
From: René Scharfe @ 2015-05-19 20:29 UTC (permalink / raw
  To: Stefan Beller; +Cc: Git Mailing List, Stefan Beller, Jeff King, Vicent Marti

Am 19.05.2015 um 02:57 schrieb Stefan Beller:
> On Mon, May 18, 2015 at 4:24 PM, René Scharfe <l.s.r@web.de> wrote:
>> diff --git a/pack-bitmap.c b/pack-bitmap.c
>> index 62a98cc..e5abb8a 100644
>> --- a/pack-bitmap.c
>> +++ b/pack-bitmap.c
>> @@ -209,14 +209,12 @@ static inline uint8_t read_u8(const unsigned char *buffer, size_t *pos)
>>          return buffer[(*pos)++];
>>   }
>>
>> +#define MAX_XOR_OFFSET 160
>> +
>>   static int load_bitmap_entries_v1(struct bitmap_index *index)
>>   {
>> -       static const size_t MAX_XOR_OFFSET = 160;
>
> Is there a reason why we prefer defines over a  static const size_t here?

Yes, see below.

>> -
>>          uint32_t i;
>> -       struct stored_bitmap **recent_bitmaps;
>> -
>> -       recent_bitmaps = xcalloc(MAX_XOR_OFFSET, sizeof(struct stored_bitmap));
>> +       struct stored_bitmap *recent_bitmaps[MAX_XOR_OFFSET] = { NULL };

If MAX_XOR_OFFSET is a const then C89 does not allow this declaration. 
C99 gives you a variable-length array here.  VLAs can't be initialized 
at declaration time, so we'd need to add a memset() call (at least with 
GCC 4.9).  Overall it's simpler and shorter to use a macro.

We could also use an enum, but that's not exactly common.

René

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] pack-bitmaps: plug memory leak, fix allocation size for recent_bitmaps
  2015-05-19 19:45   ` Junio C Hamano
@ 2015-05-19 21:19     ` Jeff King
  0 siblings, 0 replies; 6+ messages in thread
From: Jeff King @ 2015-05-19 21:19 UTC (permalink / raw
  To: Junio C Hamano
  Cc: René Scharfe, Git Mailing List, Stefan Beller, Vicent Marti

On Tue, May 19, 2015 at 12:45:46PM -0700, Junio C Hamano wrote:

> > I looked over the function one more time to make sure it is the function
> > that is wrong, and not my suggestion. :) The current code seems pretty
> > obviously wrong.
> 
> I actually cannot guess what the current code is trying to do.  Was
> it an attempt to cache that many entries, but instead allocated and
> discarded the space it tried to use as a cache every time?

Sort of. There are two caches at work.

The bitmaps on disk may be stored as XORs against nearby bitmaps up to
MAX_XOR_OFFSET slots away. So our goal is to reconstruct the actual
bitmaps and put them in our cache for later use. That's actually done by
store_bitmap(), which puts them into a hash table indexed by sha1.

But because we get the XOR base as an offset, we also need to be able to
quickly say "what was the bitmap that was N slots ago?", and the hash
cannot answer that quickly. So we keep a sliding window of the last
MAX_XOR_OFFSET bitmaps (pointing to the cached bitmaps stored in the
hash), and then we can index that directly by offset. And we can reuse
the array as a circular buffer (notice we always index it modulo the max
offset).

So you can think of the recent_bitmaps as an auxiliary index into the
bitmaps already cached by store_bitmap(). We don't need it after the xor
reconstruction (actually I think we don't do the xor reconstruction
here, but instead retain a pointer to the xor base and lazily do it, but
the point is that we've created that pointer).

-Peff

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-05-19 21:20 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-18 23:24 [PATCH] pack-bitmaps: plug memory leak, fix allocation size for recent_bitmaps René Scharfe
2015-05-19  0:57 ` Stefan Beller
2015-05-19 20:29   ` René Scharfe
2015-05-19  2:23 ` Jeff King
2015-05-19 19:45   ` Junio C Hamano
2015-05-19 21:19     ` Jeff King

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).