diff: release blobs after generating textual diff.
authorJunio C Hamano <junkio@cox.net>
Thu, 3 May 2007 20:05:48 +0000 (13:05 -0700)
committerJunio C Hamano <junkio@cox.net>
Mon, 7 May 2007 22:54:32 +0000 (15:54 -0700)
This reduces the memory pressure when dealing with many paths.

An unscientific test of running "diff-tree --stat --summary -M"
between v2.6.19 and v2.6.20-rc1 in the linux kernel repository
indicates that the number of minor faults are reduced by 2/3.

Signed-off-by: Junio C Hamano <junkio@cox.net>
diff.c
diff --git a/diff.c b/diff.c
index 7bbe7590b2e6b8c1f153902e0375df193c5268f2..2979bc57e4a98a7ea24412b5359cd8afd614256e 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1236,6 +1236,8 @@ static void builtin_diff(const char *name_a,
        }
 
  free_ab_and_return:
+       diff_free_filespec_data(one);
+       diff_free_filespec_data(two);
        free(a_one);
        free(b_two);
        return;
@@ -1262,7 +1264,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
                diff_populate_filespec(two, 0);
                data->deleted = count_lines(one->data, one->size);
                data->added = count_lines(two->data, two->size);
-               return;
+               goto free_and_return;
        }
        if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
                die("unable to read files to diff");
@@ -1284,6 +1286,10 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
                ecb.priv = diffstat;
                xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
        }
+
+ free_and_return:
+       diff_free_filespec_data(one);
+       diff_free_filespec_data(two);
 }
 
 static void builtin_checkdiff(const char *name_a, const char *name_b,
@@ -1306,7 +1312,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
                die("unable to read files to diff");
 
        if (file_is_binary(two))
-               return;
+               goto free_and_return;
        else {
                /* Crazy xdl interfaces.. */
                xpparam_t xpp;
@@ -1320,6 +1326,9 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
                ecb.priv = &data;
                xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
        }
+ free_and_return:
+       diff_free_filespec_data(one);
+       diff_free_filespec_data(two);
 }
 
 struct diff_filespec *alloc_filespec(const char *path)
@@ -1507,7 +1516,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
                size_only = 0;
 
        if (s->data)
-               return err;
+               return 0;
 
        if (S_ISDIRLNK(s->mode))
                return diff_populate_gitlink(s, size_only);
@@ -1597,8 +1606,11 @@ void diff_free_filespec_data(struct diff_filespec *s)
                free(s->data);
        else if (s->should_munmap)
                munmap(s->data, s->size);
-       s->should_free = s->should_munmap = 0;
-       s->data = NULL;
+
+       if (s->should_free || s->should_munmap) {
+               s->should_free = s->should_munmap = 0;
+               s->data = NULL;
+       }
        free(s->cnt_data);
        s->cnt_data = NULL;
 }