On Fri, Sep 20, 2019 at 08:14:07PM +0200, SZEDER Gábor wrote:
> On Fri, Sep 20, 2019 at 08:13:02PM +0200, SZEDER Gábor wrote:
> > > If the (re)introduced leak doesn't impact performance and memory
> > > usage too much then duplicating tip_name again in name_rev() or
> > > rather your new create_or_update_name() would likely make the
> > > lifetimes of those string buffers easier to manage.
> >
> > Yeah, the easiest would be when each 'struct rev_name' in the commit
> > slab would have its own 'tip_name' string, but that would result in
> > a lot of duplicated strings and increased memory usage.
>
> I didn't measure how much more memory would be used, though.
So, I tried the patch below to give each 'struct rev_name' instance
its own copy of 'tip_name', and the memory usage of 'git name-rev
--all' usually increased.
The increase depends on how many merges and how many refs there are
compared to the number of commits: the fewer merges and refs, the
higher the more the memory usage increased:
linux: +4.8%
gcc: +7.2%
gecko-dev: +9.2%
webkit: +12.4%
llvm-project: +19.0%
git.git is the exception with its unusually high number of merge
commits (about 25%), and the memory usage decresed by 4.4%.
--- >8 ---
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 6969af76c4..62ab78242b 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -88,6 +88,7 @@ static struct rev_name *create_or_update_name(struct commit
*commit,
set_commit_rev_name(commit, name);
goto copy_data;
} else if (is_better_name(name, taggerdate, distance, from_tag)) {
+ free((char*) name->tip_name);
copy_data:
name->tip_name = tip_name;
name->taggerdate = taggerdate;
@@ -106,21 +107,19 @@ static void name_rev(struct commit *start_commit,
{
struct commit_list *list = NULL;
const char *tip_name;
- char *to_free = NULL;
parse_commit(start_commit);
if (start_commit->date < cutoff)
return;
if (deref) {
- tip_name = to_free = xstrfmt("%s^0", start_tip_name);
- free((char*) start_tip_name);
+ tip_name = xstrfmt("%s^0", start_tip_name);
} else
- tip_name = start_tip_name;
+ tip_name = strdup(start_tip_name);
if (!create_or_update_name(start_commit, tip_name, taggerdate, 0, 0,
from_tag)) {
- free(to_free);
+ free((char*) tip_name);
return;
}
@@ -139,7 +138,6 @@ static void name_rev(struct commit *start_commit,
struct commit *parent = parents->item;
const char *new_name;
int generation, distance;
- const char *new_name_to_free = NULL;
parse_commit(parent);
if (parent->date < cutoff)
@@ -159,11 +157,10 @@ static void name_rev(struct commit *start_commit,
new_name = xstrfmt("%.*s^%d", (int)len,
name->tip_name,
parent_number);
- new_name_to_free = new_name;
generation = 0;
distance = name->distance +
MERGE_TRAVERSAL_WEIGHT;
} else {
- new_name = name->tip_name;
+ new_name = strdup(name->tip_name);
generation = name->generation + 1;
distance = name->distance + 1;
}
@@ -174,7 +171,7 @@ static void name_rev(struct commit *start_commit,
last_new_parent = commit_list_append(parent,
last_new_parent);
else
- free((char*) new_name_to_free);
+ free((char*) new_name);
}
*last_new_parent = list;
@@ -313,7 +310,7 @@ static int name_ref(const char *path, const struct
object_id *oid, int flags, vo
if (taggerdate == TIME_MAX)
taggerdate = commit->date;
path = name_ref_abbrev(path, can_abbreviate_output);
- name_rev(commit, xstrdup(path), taggerdate, from_tag, deref);
+ name_rev(commit, path, taggerdate, from_tag, deref);
}
return 0;
}
--
2.23.0.331.g4e51dcdf11