Merge branch 'nd/split-index-unshare'
Plug some leaks and updates internal API used to implement the split index feature to make it easier to avoid such a leak in the future. * nd/split-index-unshare: p3400: add perf tests for rebasing many changes split-index: add and use unshare_split_index()
This commit is contained in:
commit
f382b756a6
10
read-cache.c
10
read-cache.c
@ -1877,15 +1877,9 @@ int discard_index(struct index_state *istate)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < istate->cache_nr; i++) {
|
unshare_split_index(istate, 1);
|
||||||
if (istate->cache[i]->index &&
|
for (i = 0; i < istate->cache_nr; i++)
|
||||||
istate->split_index &&
|
|
||||||
istate->split_index->base &&
|
|
||||||
istate->cache[i]->index <= istate->split_index->base->cache_nr &&
|
|
||||||
istate->cache[i] == istate->split_index->base->cache[istate->cache[i]->index - 1])
|
|
||||||
continue;
|
|
||||||
free(istate->cache[i]);
|
free(istate->cache[i]);
|
||||||
}
|
|
||||||
resolve_undo_clear_index(istate);
|
resolve_undo_clear_index(istate);
|
||||||
istate->cache_nr = 0;
|
istate->cache_nr = 0;
|
||||||
istate->cache_changed = 0;
|
istate->cache_changed = 0;
|
||||||
|
@ -73,10 +73,17 @@ void move_cache_to_base_index(struct index_state *istate)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do not delete old si->base, its index entries may be shared
|
* If "si" is shared with another index_state (e.g. by
|
||||||
* with istate->cache[]. Accept a bit of leaking here because
|
* unpack-trees code), we will need to duplicate split_index
|
||||||
* this code is only used by short-lived update-index.
|
* struct. It's not happening now though, luckily.
|
||||||
*/
|
*/
|
||||||
|
assert(si->refcount <= 1);
|
||||||
|
|
||||||
|
unshare_split_index(istate, 0);
|
||||||
|
if (si->base) {
|
||||||
|
discard_index(si->base);
|
||||||
|
free(si->base);
|
||||||
|
}
|
||||||
si->base = xcalloc(1, sizeof(*si->base));
|
si->base = xcalloc(1, sizeof(*si->base));
|
||||||
si->base->version = istate->version;
|
si->base->version = istate->version;
|
||||||
/* zero timestamp disables racy test in ce_write_index() */
|
/* zero timestamp disables racy test in ce_write_index() */
|
||||||
@ -275,11 +282,41 @@ void finish_writing_split_index(struct index_state *istate)
|
|||||||
istate->cache_nr = si->saved_cache_nr;
|
istate->cache_nr = si->saved_cache_nr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unshare_split_index(struct index_state *istate, int discard)
|
||||||
|
{
|
||||||
|
struct split_index *si = istate->split_index;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!si || !si->base)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < istate->cache_nr; i++) {
|
||||||
|
struct cache_entry *ce = istate->cache[i];
|
||||||
|
struct cache_entry *new = NULL;
|
||||||
|
|
||||||
|
if (!ce->index ||
|
||||||
|
ce->index > si->base->cache_nr ||
|
||||||
|
ce != si->base->cache[ce->index - 1])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!discard) {
|
||||||
|
int len = ce_namelen(ce);
|
||||||
|
new = xcalloc(1, cache_entry_size(len));
|
||||||
|
copy_cache_entry(new, ce);
|
||||||
|
memcpy(new->name, ce->name, len);
|
||||||
|
new->index = 0;
|
||||||
|
}
|
||||||
|
istate->cache[i] = new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void discard_split_index(struct index_state *istate)
|
void discard_split_index(struct index_state *istate)
|
||||||
{
|
{
|
||||||
struct split_index *si = istate->split_index;
|
struct split_index *si = istate->split_index;
|
||||||
if (!si)
|
if (!si)
|
||||||
return;
|
return;
|
||||||
|
unshare_split_index(istate, 0);
|
||||||
istate->split_index = NULL;
|
istate->split_index = NULL;
|
||||||
si->refcount--;
|
si->refcount--;
|
||||||
if (si->refcount)
|
if (si->refcount)
|
||||||
@ -328,14 +365,8 @@ void add_split_index(struct index_state *istate)
|
|||||||
|
|
||||||
void remove_split_index(struct index_state *istate)
|
void remove_split_index(struct index_state *istate)
|
||||||
{
|
{
|
||||||
if (istate->split_index) {
|
if (!istate->split_index)
|
||||||
/*
|
return;
|
||||||
* can't discard_split_index(&the_index); because that
|
discard_split_index(istate);
|
||||||
* will destroy split_index->base->cache[], which may
|
|
||||||
* be shared with the_index.cache[]. So yeah we're
|
|
||||||
* leaking a bit here.
|
|
||||||
*/
|
|
||||||
istate->split_index = NULL;
|
|
||||||
istate->cache_changed |= SOMETHING_CHANGED;
|
istate->cache_changed |= SOMETHING_CHANGED;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -33,5 +33,6 @@ void finish_writing_split_index(struct index_state *istate);
|
|||||||
void discard_split_index(struct index_state *istate);
|
void discard_split_index(struct index_state *istate);
|
||||||
void add_split_index(struct index_state *istate);
|
void add_split_index(struct index_state *istate);
|
||||||
void remove_split_index(struct index_state *istate);
|
void remove_split_index(struct index_state *istate);
|
||||||
|
void unshare_split_index(struct index_state *istate, int discard);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,7 +5,7 @@ test_description='Tests rebase performance'
|
|||||||
|
|
||||||
test_perf_default_repo
|
test_perf_default_repo
|
||||||
|
|
||||||
test_expect_success 'setup' '
|
test_expect_success 'setup rebasing on top of a lot of changes' '
|
||||||
git checkout -f -b base &&
|
git checkout -f -b base &&
|
||||||
git checkout -b to-rebase &&
|
git checkout -b to-rebase &&
|
||||||
git checkout -b upstream &&
|
git checkout -b upstream &&
|
||||||
@ -33,4 +33,24 @@ test_perf 'rebase on top of a lot of unrelated changes' '
|
|||||||
git rebase --onto base HEAD^
|
git rebase --onto base HEAD^
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'setup rebasing many changes without split-index' '
|
||||||
|
git config core.splitIndex false &&
|
||||||
|
git checkout -b upstream2 to-rebase &&
|
||||||
|
git checkout -b to-rebase2 upstream
|
||||||
|
'
|
||||||
|
|
||||||
|
test_perf 'rebase a lot of unrelated changes without split-index' '
|
||||||
|
git rebase --onto upstream2 base &&
|
||||||
|
git rebase --onto base upstream2
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'setup rebasing many changes with split-index' '
|
||||||
|
git config core.splitIndex true
|
||||||
|
'
|
||||||
|
|
||||||
|
test_perf 'rebase a lot of unrelated changes with split-index' '
|
||||||
|
git rebase --onto upstream2 base &&
|
||||||
|
git rebase --onto base upstream2
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user