On Sat, Mar 24, 2018 at 07:33:46AM +0100, Nguyễn Thái Ngọc Duy wrote:

> diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
> index e1244918a5..b41610569e 100644
> --- a/builtin/pack-objects.c
> +++ b/builtin/pack-objects.c
> @@ -29,6 +29,8 @@
>  #include "list.h"
>  #include "packfile.h"
>  
> +#define IN_PACK(obj) oe_in_pack(&to_pack, obj)

How come this one gets a macro, but the earlier conversions don't?

I guess the problem is that oe_in_pack() is defined in the generic
pack-objects.h, but &to_pack is only in builtin/pack-objects.c?

I wonder if it would be that bad to just say oe_in_pack(&to_pack, obj)
everywhere. It's longer, but it makes the code slightly less magical to
read.

> @@ -1074,7 +1076,7 @@ static void create_object_entry(const struct object_id 
> *oid,
>       else
>               nr_result++;
>       if (found_pack) {
> -             entry->in_pack = found_pack;
> +             oe_set_in_pack(&to_pack, entry, found_pack);
>               entry->in_pack_offset = found_offset;
>       }

it's funny to see in_pack as an external thing, but in_pack_offset still
in the struct. I guess there's nothing to be gained there, since the
offset really does need to be individual (and large).

> diff --git a/cache.h b/cache.h
> index 862bdff83a..b90feb3802 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -1635,6 +1635,7 @@ extern struct packed_git {
>       int index_version;
>       time_t mtime;
>       int pack_fd;
> +     int index;              /* for builtin/pack-objects.c */
>       unsigned pack_local:1,
>                pack_keep:1,
>                freshened:1,

It's pretty gross to infect this global struct. But I'm not sure there's
an easier way to do it with constant-time lookups. You'd have to build
the packed_git index preemptively in pack-objects, and then always just
pass around the index numbers.  And even that is kind of dicey, since
the packed_git list can grow while we're running.

The alternative is a hash table mapping packed_git pointers into numeric
indices. Yuck.

> +static void prepare_in_pack_by_idx(struct packing_data *pdata)
> +{
> +     struct packed_git **mapping, *p;
> +     int cnt = 0, nr = 1 << OE_IN_PACK_BITS;
> +
> +     if (getenv("GIT_TEST_FULL_IN_PACK_ARRAY")) {
> +             /*
> +              * leave in_pack_by_idx NULL to force in_pack[] to be
> +              * used instead
> +              */
> +             return;
> +     }
> +
> +     ALLOC_ARRAY(mapping, nr);
> +     mapping[cnt++] = NULL; /* zero index must be mapped to NULL */

Why? I guess because index==0 is a sentinel for "we're using the small
index numbers?"

> +     prepare_packed_git();
> +     for (p = packed_git; p; p = p->next, cnt++) {
> +             if (cnt == nr) {
> +                     free(mapping);
> +                     return;
> +             }
> +             p->index = cnt;
> +             mapping[cnt] = p;
> +     }
> +     pdata->in_pack_by_idx = mapping;
> +}

What happens if we later have to reprepare_packed_git() and end up with
more packs? We only call this for the first pack.

It may well be handled, but I'm having trouble following the code to see
if it is. And I doubt that case is covered by our test suite (since it
inherently involves a race).

>  /*
> + * The size of struct nearly determines pack-objects's memory
> + * consumption. This struct is packed tight for that reason. When you
> + * add or reorder something in this struct, think a bit about this.
> + *

It's funny to see this warning come in the middle. Should it be part of
the final struct reordering at the end?

-Peff

Reply via email to