From patchwork Sun Feb 25 11:39:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13570803 Received: from mout.web.de (mout.web.de [212.227.17.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D77D101DA for ; Sun, 25 Feb 2024 11:40:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.227.17.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708861204; cv=none; b=UlUE5fbNxwLY7D4NnpZJ1wq85YA/fNrfBiAEVdoZqnVEQs3FgNeiuTJBUQCFBH4HRwK+R13qzqvjsa3zhplF0oFabu2rTxBbQUuZPPVKtIjTx67FO9KuCzH5Rn+Ea5RkdMCLKaKqBpbpBf/jj6KGX57qCYy3KC10jSEBiACv6xM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708861204; c=relaxed/simple; bh=FYH++5g1qSoBKX8tiB4AelL1cCcVrS6Ul5pI+3KBgk0=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=u7ZMQI8wHZzAFgYIupCs5GglmMjqI4e3qa7FjQSSwWdeeAYH9vw1tCMaov2uwDVsuPQq+3qlWE1iB972/i1ctJAYhmD8HEdopWNeRyNGndb7dA9nxsfwEdZLNDdocB+EEK4sf+nugZECZvIVoNG8NEi4tpu3+GqpNd2hT2isN7w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de; spf=pass smtp.mailfrom=web.de; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b=Zfln+wlO; arc=none smtp.client-ip=212.227.17.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=web.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b="Zfln+wlO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1708861198; x=1709465998; i=l.s.r@web.de; bh=FYH++5g1qSoBKX8tiB4AelL1cCcVrS6Ul5pI+3KBgk0=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=Zfln+wlOx+Q9aKNHMpPR+WSGysXPgMu8d8iPZi4s60d61HCS/rmZD7aYN0Gj07Vl jxQmRlCYPDH8tV6zNK8/zZoOZFTAXqSi69lC2mwOIwyroXbzCKdiiFHM1WHDy9O5D xMOTS2AcLwF2avzuc96zKXhwhhU7JMtq5e7Ci1F942aPDQWZ7msmHH9Ok8cTYVo05 lVCgZ8d7T92ijdI04e5L4IBvt5pEmkjXtD+4i4nVlF2YaH2XSXhTyp/OBplD2GAED nGO3lp58ezP0tiN+0isKmPYoM5nBcOYK0ziT+JjD3nY5rhM/ALD/EuIn6ig5f4diy Vr6W+QSwRaP1heRx6w== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb106 [213.165.67.124]) with ESMTPSA (Nemesis) id 1MActe-1rkmRS2EKe-00BXdV for ; Sun, 25 Feb 2024 12:39:58 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH 1/2] mem-pool: add mem_pool_strfmt() Date: Sun, 25 Feb 2024 12:39:44 +0100 Message-ID: <20240225113947.89357-2-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240225113947.89357-1-l.s.r@web.de> References: <20240225113947.89357-1-l.s.r@web.de> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:7V0L47QAk4F5Xw35mif/RmTmiUSwR95kI1lZiB5Ips8TYbSDJeC Iyl8dl5/AfD7SLUWLuLn65jWYYRVNmxLNlxhrWcK1AjOgbfKb7INX05YdTnSMYXBFoXirvC j5RlaIOZ8kwJ5z7p/nyR6Z6f9F8fRY/x36/WoXwk2KjqPbJ5w6BirjAcY/MYEX8i2cDlBiv jE++L7uOkkOOGecpZiMyw== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:YikoBwScmCE=;ZnsILH2EVD1HG/okCqlm1VAp3eo q7lTJgckQxfBC4bCqPOOnIqHhTndjxyUXb49xq9eNhOJv6J6mBUatwlxg4A/nuaZ6pfn/sYxl dV6qzA5TkaqeKnZID84WgHFWgSgFRMm2+Z+0KAAquRlB2uZB1xWoklEHq+tUkocbMeGREjLA5 4F147hNY/ESWhV7xA58/laaYABkXvhGdXLr7101ley9RGVUptqoLJFpY5upVjJtuKrnRdGdy+ qosYc99OfQTcCqDxYV3NurvX2GSqHWn41LK6Sh3HqqST4vCSupUimLvsEQ32EqWrjXEfegDrN QPjQTFFsiqnaXHZ/2ykuAfBQtby5i5l1yGiR1Mb3j/0ArM9u8GRa9tB4TLwzukWivWY4FoBn3 w44rroxY/nzBIJLZY3hxDgnxRit3SYTWn/xPXFNcGFBNO+stV9h8k0+8CmN6AAfKgkdevyLIi R5BD/MlhOL63B/22NRCsrh/9f6A6nWKpAF1G/dUZ3AQC8PuMfqN9APJIIOvQ2ppefgn2sWyju YjNv5LIbLV87+gCaRP+BhfntPCaIuwE1odGNkUzBlHm/mR+OvOZFvSzHYhcsOmxiaI1oDvbM0 XKmVQ8GvMwlVZwk1spQpXY2rUNcrd9c5eDHvkz+x4Bqd/Br3wNiI5XHT6XTKdWdAr9G7zGNr7 TO2KQWZQg1Y2autb4lFBi6Hmx+Cx/0/MSb//CX5+iPov5Tg3ZGrjI6zoPe0wBfbtnRHSVUJc9 k3VTjTu6lxJWWF2mm5OcLmUGFjVs0XcLdcdMghwJA5goj9FBLedL+TPtQzBL4DSMgrHTNoWUz w8ROLmwX9k+Hi3aIErzL+vT7DbjOi2SZHWVu1zSXFXS24= Add a function for building a string, printf style, using a memory pool. It uses the free space in the current block in the first attempt. If that suffices then the result can already be used without copying or reformatting. For strings that are significantly shorter on average than the block size (ca. 1 MiB by default) this is the case most of the time, leading to a better perfomance than a solution that doesn't access mem-pool internals. Signed-off-by: René Scharfe --- mem-pool.c | 39 +++++++++++++++++++++++++++++++++++++++ mem-pool.h | 5 +++++ 2 files changed, 44 insertions(+) -- 2.44.0 diff --git a/mem-pool.c b/mem-pool.c index c7d6256020..2078c22b09 100644 --- a/mem-pool.c +++ b/mem-pool.c @@ -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); diff --git a/mem-pool.h b/mem-pool.h index fe7507f022..d1c66413ec 100644 --- a/mem-pool.h +++ b/mem-pool.h @@ -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 From patchwork Sun Feb 25 11:39:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_Scharfe?= X-Patchwork-Id: 13570802 Received: from mout.web.de (mout.web.de [212.227.17.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D739FC15 for ; Sun, 25 Feb 2024 11:40:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=212.227.17.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708861203; cv=none; b=GfFh1CfUMJFsKqntjBp0ajeJS3XZ/xlpCuNdeOmvQ2tevu81uhzYdprKH8uH08E4FZp2ywabYNWo8+hUQ/xLuyHcIDIfyQaBPj1noIff8YU91Kwo2lcmMsQevYEWpd3dx0YR5mUhAWcC65bf/+0QupfgblCsW6jVf67U44BuoLY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708861203; c=relaxed/simple; bh=lE1aebN+y80OzsCthD6RZZTGQy3aU+AuXEmU0Vy757c=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Q9hoefkJmU5g/XQH8WYn7V00ZA5pc3lysEm5HKKBjQgHFGVuavnzP4ue6gSInAem05XKSATfatfJSIu5peafdf4QOVUgM/pEcMFQJ9VFJG2DUhBcMSGClmk4EPagbDXMt7etgZaf223Nkzgi2WPAd294afk2iOFIems1fV5Rre8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de; spf=pass smtp.mailfrom=web.de; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b=ep0TVJQO; arc=none smtp.client-ip=212.227.17.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=web.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=web.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=web.de header.i=l.s.r@web.de header.b="ep0TVJQO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=s29768273; t=1708861198; x=1709465998; i=l.s.r@web.de; bh=lE1aebN+y80OzsCthD6RZZTGQy3aU+AuXEmU0Vy757c=; h=X-UI-Sender-Class:From:To:Subject:Date:In-Reply-To:References; b=ep0TVJQO6b9wX668eU0IUI7alHzWGh0CMYOXsd8k+wiH6FUJJbjqE5YBq5OTCPYZ lRBgBJzdgjmhEA0qJ4lqoObKY1ewYyYgP5B2U1iBIOywJunwQtFBpKNSuUv/Fq02O i0/OGwIGJ7Yyq+qoZYrnaSh6t8efZ6lVVPjTml7U19mTPhHbsQkM07Zi96u3BAeqp jKu92qdUtkhJBkv3aooMT6qeukEnIUNPnI/RoF1NxsALHHTmLEqgStv+EkbvAMOme PeLMRHccMD97R5m+EvVeKvkAF3wdtr9SUPJe+Vkg9NxHY8OtcnT6vwKwOYNVGLKh+ fGBaoZjGXMgxasf8YA== X-UI-Sender-Class: 814a7b36-bfc1-4dae-8640-3722d8ec6cd6 Received: from Mini-von-Rene.fritz.box ([79.203.19.211]) by smtp.web.de (mrweb106 [213.165.67.124]) with ESMTPSA (Nemesis) id 1MUCuv-1rUc6X2rRL-00R8i6 for ; Sun, 25 Feb 2024 12:39:58 +0100 From: =?utf-8?q?Ren=C3=A9_Scharfe?= To: git@vger.kernel.org Subject: [PATCH 2/2] name-rev: use mem_pool_strfmt() Date: Sun, 25 Feb 2024 12:39:45 +0100 Message-ID: <20240225113947.89357-3-l.s.r@web.de> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240225113947.89357-1-l.s.r@web.de> References: <20240225113947.89357-1-l.s.r@web.de> Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Provags-ID: V03:K1:QlDeAdtzFSqd9K2q6LB4fILnJep712Ex9Liv5jqMWTog5zAf3cv UGDclTSBA75Kt1r1r4sqdHLmBTxrAu04O5HnQmpNtX5CFK6MXs8ravBTiU1RqkPWjuCi5kx TFOJshXuGr9YU6jXS3howqbaqJ2rEwMJzW4XXML80ughe6Z0R1tDK6rbQEPIChOC4P2QXqg RjO1YBjgbF0n1ULkWdrgg== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:CCwA989U3Cg=;JA3X2O1bZg/R0a1EXbxBhnuXpWO VJcIpGu32AIrp5M/BzS6yCEiR9rdMVCBnd6o7T+T4SK/TkIADmix4mCcKlVG1ykhJhAV+AAfW OHa5Zd4IeDAuLec8X+t5+xBMB10CthC+TNId+20B/NuftnWwz7S3/6hlwtMsx/g2kpZTtUOlh VzCwMD8d5BxdU+moOBMEomWhrG0qBissEuYgYE98QLs51wljDnH0t5LTXHOBVwic7qIvDa7gv lZdfXX5XYqJ36AG3qk5noRaYgGjWhdFmCVITCTh+JDim1ohsH26p1LtTEEx7KpDoFyVMkR7H5 DrqGo3rwnGu19OB4a5+YgWQz3lv9tEz2Gm8lYmG5VJ9mS6dKzZ3CX4X0PXUPCpKmpMePb1dVg f7iJocFsHJ3ciBJuluL5xreNdLE+nnR6abLP65G5x6y/Hg1DJNCm4R3Xh1uyGn2Ej4XK+xg5C IPIGntPtDFTO7yzFddtOkD9uFUklwlvuhZxSsuxQ4LtA9ptZD2iI5fegt0RuvCHblxOkIfzFi E2obHTNVWoo1uxDZWyv4ynNrtxTuofZucCvnwn/cN8bl6AVjVJKt5V2vQhagjkDRm2YdIrWSc gCY9YpoTc/3u9zuj1dOJGITw3obT5g2dt3AdO7uDmJGckUyBP74TeeoqbNSsczMSbqeSOgeTK oyrJ3RgYrOqrK4EL0L70AOSH0Fza4wdBjK4gvCEe1kfGczSseo0ic2YDLQdhQCDsCP1WgXH5U cqMOJTWx8beAGoWtp1AjLKdg0UqlVnviKw7Q5pzA/NspmFbussLoiJ2FEfcmTJRwuMjSnxGRd gkBxVDnY/OXHrUNINI5A8pb0V8cgrD8579KN/aY7MQwiM= 1c56fc2084 (name-rev: pre-size buffer in get_parent_name(), 2020-02-04) got a big performance boost in an unusual repository by calculating the name length in advance. This is a bit awkward, as it references the name components twice. Use a memory pool to store the strings for the struct rev_name member tip_name. Using mem_pool_strfmt() allows efficient allocation without explicit size calculation. This simplifies the formatting part of the code without giving up performance: Benchmark 1: ./git_2.44.0 -C ../chromium/src name-rev --all Time (mean ± σ): 1.231 s ± 0.013 s [User: 1.082 s, System: 0.136 s] Range (min … max): 1.214 s … 1.252 s 10 runs Benchmark 2: ./git -C ../chromium/src name-rev --all Time (mean ± σ): 1.220 s ± 0.020 s [User: 1.083 s, System: 0.130 s] Range (min … max): 1.197 s … 1.254 s 10 runs Don't bother discarding the memory pool just before exiting. The effort for that would be very low, but actually measurable in the above example, with no benefit to users. At least UNLEAK it to calm down leak checkers. This addresses the leaks that 45a14f578e (Revert "name-rev: release unused name strings", 2022-04-22) brought back. Signed-off-by: René Scharfe --- This doesn't make any test script leak-free, though. builtin/name-rev.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) -- 2.44.0 diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 2dd1807c4e..ad9930c831 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -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; }