提交 f382b756 编写于 作者: J Junio C Hamano

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()
...@@ -1877,15 +1877,9 @@ int discard_index(struct index_state *istate) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 istate->cache_changed |= SOMETHING_CHANGED;
* be shared with the_index.cache[]. So yeah we're
* leaking a bit here.
*/
istate->split_index = NULL;
istate->cache_changed |= SOMETHING_CHANGED;
}
} }
...@@ -33,5 +33,6 @@ void finish_writing_split_index(struct index_state *istate); ...@@ -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' ...@@ -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' ' ...@@ -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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册