Merge branch 'rs/name-rev-with-mempool'

Many small allocations "git name-rev" makes have been updated to
allocate from a mem-pool.

* rs/name-rev-with-mempool:
  name-rev: use mem_pool_strfmt()
  mem-pool: add mem_pool_strfmt()
maint
Junio C Hamano 2024-03-05 09:44:43 -08:00
commit b5111647cb
3 changed files with 64 additions and 19 deletions

View File

@ -15,6 +15,7 @@
#include "commit-slab.h"
#include "commit-graph.h"
#include "wildmatch.h"
#include "mem-pool.h"

/*
* One day. See the 'name a rev shortly after epoch' test in t6120 when
@ -155,30 +156,25 @@ static struct rev_name *create_or_update_name(struct commit *commit,
return name;
}

static char *get_parent_name(const struct rev_name *name, int parent_number)
static char *get_parent_name(const struct rev_name *name, int parent_number,
struct mem_pool *string_pool)
{
struct strbuf sb = STRBUF_INIT;
size_t len;

strip_suffix(name->tip_name, "^0", &len);
if (name->generation > 0) {
strbuf_grow(&sb, len +
1 + decimal_width(name->generation) +
1 + decimal_width(parent_number));
strbuf_addf(&sb, "%.*s~%d^%d", (int)len, name->tip_name,
name->generation, parent_number);
return mem_pool_strfmt(string_pool, "%.*s~%d^%d",
(int)len, name->tip_name,
name->generation, parent_number);
} else {
strbuf_grow(&sb, len +
1 + decimal_width(parent_number));
strbuf_addf(&sb, "%.*s^%d", (int)len, name->tip_name,
parent_number);
return mem_pool_strfmt(string_pool, "%.*s^%d",
(int)len, name->tip_name, parent_number);
}
return strbuf_detach(&sb, NULL);
}

static void name_rev(struct commit *start_commit,
const char *tip_name, timestamp_t taggerdate,
int from_tag, int deref)
int from_tag, int deref, struct mem_pool *string_pool)
{
struct prio_queue queue;
struct commit *commit;
@ -195,9 +191,10 @@ static void name_rev(struct commit *start_commit,
if (!start_name)
return;
if (deref)
start_name->tip_name = xstrfmt("%s^0", tip_name);
start_name->tip_name = mem_pool_strfmt(string_pool, "%s^0",
tip_name);
else
start_name->tip_name = xstrdup(tip_name);
start_name->tip_name = mem_pool_strdup(string_pool, tip_name);

memset(&queue, 0, sizeof(queue)); /* Use the prio_queue as LIFO */
prio_queue_put(&queue, start_commit);
@ -235,7 +232,8 @@ static void name_rev(struct commit *start_commit,
if (parent_number > 1)
parent_name->tip_name =
get_parent_name(name,
parent_number);
parent_number,
string_pool);
else
parent_name->tip_name = name->tip_name;
ALLOC_GROW(parents_to_queue,
@ -415,7 +413,7 @@ static int name_ref(const char *path, const struct object_id *oid,
return 0;
}

static void name_tips(void)
static void name_tips(struct mem_pool *string_pool)
{
int i;

@ -428,7 +426,7 @@ static void name_tips(void)
struct tip_table_entry *e = &tip_table.table[i];
if (e->commit) {
name_rev(e->commit, e->refname, e->taggerdate,
e->from_tag, e->deref);
e->from_tag, e->deref, string_pool);
}
}
}
@ -561,6 +559,7 @@ static void name_rev_line(char *p, struct name_ref_data *data)

int cmd_name_rev(int argc, const char **argv, const char *prefix)
{
struct mem_pool string_pool;
struct object_array revs = OBJECT_ARRAY_INIT;
int all = 0, annotate_stdin = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
struct name_ref_data data = { 0, 0, STRING_LIST_INIT_NODUP, STRING_LIST_INIT_NODUP };
@ -587,6 +586,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
OPT_END(),
};

mem_pool_init(&string_pool, 0);
init_commit_rev_name(&rev_names);
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
@ -648,7 +648,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
adjust_cutoff_timestamp_for_slop();

for_each_ref(name_ref, &data);
name_tips();
name_tips(&string_pool);

if (annotate_stdin) {
struct strbuf sb = STRBUF_INIT;
@ -676,6 +676,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
always, allow_undefined, data.name_only);
}

UNLEAK(string_pool);
UNLEAK(revs);
return 0;
}

View File

@ -107,6 +107,45 @@ void *mem_pool_alloc(struct mem_pool *pool, size_t len)
return r;
}

static char *mem_pool_strvfmt(struct mem_pool *pool, const char *fmt,
va_list ap)
{
struct mp_block *block = pool->mp_block;
char *next_free = block ? block->next_free : NULL;
size_t available = block ? block->end - block->next_free : 0;
va_list cp;
int len, len2;
char *ret;

va_copy(cp, ap);
len = vsnprintf(next_free, available, fmt, cp);
va_end(cp);
if (len < 0)
BUG("your vsnprintf is broken (returned %d)", len);

ret = mem_pool_alloc(pool, len + 1); /* 1 for NUL */

/* Shortcut; relies on mem_pool_alloc() not touching buffer contents. */
if (ret == next_free)
return ret;

len2 = vsnprintf(ret, len + 1, fmt, ap);
if (len2 != len)
BUG("your vsnprintf is broken (returns inconsistent lengths)");
return ret;
}

char *mem_pool_strfmt(struct mem_pool *pool, const char *fmt, ...)
{
va_list ap;
char *ret;

va_start(ap, fmt);
ret = mem_pool_strvfmt(pool, fmt, ap);
va_end(ap);
return ret;
}

void *mem_pool_calloc(struct mem_pool *pool, size_t count, size_t size)
{
size_t len = st_mult(count, size);

View File

@ -47,6 +47,11 @@ void *mem_pool_calloc(struct mem_pool *pool, size_t count, size_t size);
char *mem_pool_strdup(struct mem_pool *pool, const char *str);
char *mem_pool_strndup(struct mem_pool *pool, const char *str, size_t len);

/*
* Allocate memory from the memory pool and format a string into it.
*/
char *mem_pool_strfmt(struct mem_pool *pool, const char *fmt, ...);

/*
* Move the memory associated with the 'src' pool to the 'dst' pool. The 'src'
* pool will be empty and not contain any memory. It still needs to be free'd