summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-02-02 07:29:03 (GMT)
committerJunio C Hamano <junkio@cox.net>2006-02-02 10:02:20 (GMT)
commit3c39e9bdebd68d8d45b3900bc21171642f4c6125 (patch)
tree26a0cd29977c37ca8c206cd4a4a34651af525ec6
parent6a1f79c1f1a54f97f122a86c71837fb1f1408b67 (diff)
downloadgit-3c39e9bdebd68d8d45b3900bc21171642f4c6125.zip
git-3c39e9bdebd68d8d45b3900bc21171642f4c6125.tar.gz
git-3c39e9bdebd68d8d45b3900bc21171642f4c6125.tar.bz2
combine-diff: reuse diff from the same blob.
When dealing with an insanely large Octopus, it is possible to optimize by noticing that more than one parents have the same blob and avoid running diff between a parent and the merge result by reusing an earlier result. Signed-off-by: Junio C Hamano <junkio@cox.net>
-rw-r--r--combine-diff.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/combine-diff.c b/combine-diff.c
index 243f967..0cc18fe 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -523,6 +523,30 @@ static void dump_sline(struct sline *sline, int cnt, int num_parent)
}
}
+static void reuse_combine_diff(struct sline *sline, unsigned long cnt,
+ int i, int j)
+{
+ /* We have already examined parent j and we know parent i
+ * and parent j are the same, so reuse the combined result
+ * of parent j for parent i.
+ */
+ unsigned long lno, imask, jmask;
+ imask = (1UL<<i);
+ jmask = (1UL<<j);
+
+ for (lno = 0; lno < cnt; lno++) {
+ struct lline *ll = sline->lost_head;
+ while (ll) {
+ if (ll->parent_map & jmask)
+ ll->parent_map |= imask;
+ ll = ll->next;
+ }
+ if (!(sline->flag & jmask))
+ sline->flag &= ~imask;
+ sline++;
+ }
+}
+
int show_combined_diff(struct combine_diff_path *elem, int num_parent,
int dense, const char *header, int show_empty)
{
@@ -596,8 +620,19 @@ int show_combined_diff(struct combine_diff_path *elem, int num_parent,
sline[cnt-1].flag = (1UL<<num_parent) - 1;
}
- for (i = 0; i < num_parent; i++)
- combine_diff(elem->parent_sha1[i], ourtmp, sline, cnt, i);
+ for (i = 0; i < num_parent; i++) {
+ int j;
+ for (j = 0; j < i; j++) {
+ if (!memcmp(elem->parent_sha1[i],
+ elem->parent_sha1[j], 20)) {
+ reuse_combine_diff(sline, cnt, i, j);
+ break;
+ }
+ }
+ if (i <= j)
+ combine_diff(elem->parent_sha1[i], ourtmp, sline,
+ cnt, i);
+ }
show_hunks = make_hunks(sline, cnt, num_parent, dense);