Make git-pack-redundant non-horribly slow on large sets of packs
Change the smallest-set detection algortithm so that when we have found a good set, we don't check any larger sets. Signed-off-by: Lukas Sandström <lukass@etek.chalmers.se> Signed-off-by: Junio C Hamano <junkio@cox.net>maint
parent
0adb3358f6
commit
751a71e2b5
|
@ -33,6 +33,7 @@ struct pack_list {
|
||||||
struct pll {
|
struct pll {
|
||||||
struct pll *next;
|
struct pll *next;
|
||||||
struct pack_list *pl;
|
struct pack_list *pl;
|
||||||
|
size_t pl_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void llist_free(struct llist *list)
|
inline void llist_free(struct llist *list)
|
||||||
|
@ -249,18 +250,45 @@ void cmp_two_packs(struct pack_list *p1, struct pack_list *p2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pll_insert(struct pll **pll, struct pll **hint_table)
|
||||||
|
{
|
||||||
|
struct pll *prev;
|
||||||
|
int i = (*pll)->pl_size - 1;
|
||||||
|
|
||||||
|
if (hint_table[i] == NULL) {
|
||||||
|
hint_table[i--] = *pll;
|
||||||
|
for (; i >= 0; --i) {
|
||||||
|
if (hint_table[i] != NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (hint_table[i] == NULL) /* no elements in list */
|
||||||
|
die("Why did this happen?");
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = hint_table[i];
|
||||||
|
while (prev->next && prev->next->pl_size < (*pll)->pl_size)
|
||||||
|
prev = prev->next;
|
||||||
|
|
||||||
|
(*pll)->next = prev->next;
|
||||||
|
prev->next = *pll;
|
||||||
|
}
|
||||||
|
|
||||||
/* all the permutations have to be free()d at the same time,
|
/* all the permutations have to be free()d at the same time,
|
||||||
* since they refer to each other
|
* since they refer to each other
|
||||||
*/
|
*/
|
||||||
struct pll * get_all_permutations(struct pack_list *list)
|
struct pll * get_all_permutations(struct pack_list *list)
|
||||||
{
|
{
|
||||||
struct pll *subset, *pll, *new_pll = NULL; /*silence warning*/
|
struct pll *subset, *pll, *new_pll = NULL; /*silence warning*/
|
||||||
|
static struct pll **hint = NULL;
|
||||||
|
if (hint == NULL)
|
||||||
|
hint = xcalloc(pack_list_size(list), sizeof(struct pll *));
|
||||||
|
|
||||||
if (list == NULL)
|
if (list == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (list->next == NULL) {
|
if (list->next == NULL) {
|
||||||
new_pll = xmalloc(sizeof(struct pll));
|
new_pll = xmalloc(sizeof(struct pll));
|
||||||
|
hint[0] = new_pll;
|
||||||
new_pll->next = NULL;
|
new_pll->next = NULL;
|
||||||
new_pll->pl = list;
|
new_pll->pl = list;
|
||||||
return new_pll;
|
return new_pll;
|
||||||
|
@ -268,24 +296,30 @@ struct pll * get_all_permutations(struct pack_list *list)
|
||||||
|
|
||||||
pll = subset = get_all_permutations(list->next);
|
pll = subset = get_all_permutations(list->next);
|
||||||
while (pll) {
|
while (pll) {
|
||||||
|
if (pll->pl->pack == list->pack) {
|
||||||
|
pll = pll->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
new_pll = xmalloc(sizeof(struct pll));
|
new_pll = xmalloc(sizeof(struct pll));
|
||||||
new_pll->next = pll->next;
|
|
||||||
pll->next = new_pll;
|
|
||||||
|
|
||||||
new_pll->pl = xmalloc(sizeof(struct pack_list));
|
new_pll->pl = xmalloc(sizeof(struct pack_list));
|
||||||
memcpy(new_pll->pl, list, sizeof(struct pack_list));
|
memcpy(new_pll->pl, list, sizeof(struct pack_list));
|
||||||
new_pll->pl->next = pll->pl;
|
new_pll->pl->next = pll->pl;
|
||||||
|
new_pll->pl_size = pll->pl_size + 1;
|
||||||
|
|
||||||
pll = new_pll->next;
|
pll_insert(&new_pll, hint);
|
||||||
|
|
||||||
|
pll = pll->next;
|
||||||
}
|
}
|
||||||
/* add ourself to the end */
|
/* add ourself */
|
||||||
new_pll->next = xmalloc(sizeof(struct pll));
|
new_pll = xmalloc(sizeof(struct pll));
|
||||||
new_pll->next->pl = xmalloc(sizeof(struct pack_list));
|
new_pll->pl = xmalloc(sizeof(struct pack_list));
|
||||||
new_pll->next->next = NULL;
|
memcpy(new_pll->pl, list, sizeof(struct pack_list));
|
||||||
memcpy(new_pll->next->pl, list, sizeof(struct pack_list));
|
new_pll->pl->next = NULL;
|
||||||
new_pll->next->pl->next = NULL;
|
new_pll->pl_size = 1;
|
||||||
|
pll_insert(&new_pll, hint);
|
||||||
|
|
||||||
return subset;
|
return hint[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_superset(struct pack_list *pl, struct llist *list)
|
int is_superset(struct pack_list *pl, struct llist *list)
|
||||||
|
@ -401,6 +435,8 @@ void minimize(struct pack_list **min)
|
||||||
/* find the permutations which contain all missing objects */
|
/* find the permutations which contain all missing objects */
|
||||||
perm_all = perm = get_all_permutations(non_unique);
|
perm_all = perm = get_all_permutations(non_unique);
|
||||||
while (perm) {
|
while (perm) {
|
||||||
|
if (perm_ok && perm->pl_size > perm_ok->pl_size)
|
||||||
|
break; /* ignore all larger permutations */
|
||||||
if (is_superset(perm->pl, missing)) {
|
if (is_superset(perm->pl, missing)) {
|
||||||
new_perm = xmalloc(sizeof(struct pll));
|
new_perm = xmalloc(sizeof(struct pll));
|
||||||
new_perm->pl = perm->pl;
|
new_perm->pl = perm->pl;
|
||||||
|
|
Loading…
Reference in New Issue