git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 1/2] mem-pool: add mem_pool_strfmt()

From
René Scharfe <l.s.r@web.de>
Date
Feb 25, 2024, 11:39 UTC
Message-ID
<20240225113947.89357-2-l.s.r@web.de>
In-Reply-To
<20240225113947.89357-1-l.s.r@web.de>

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 <l.s.r@web.de>
---
 mem-pool.c | 39 +++++++++++++++++++++++++++++++++++++++
 mem-pool.h |  5 +++++
 2 files changed, 44 insertions(+)
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
--
2.44.0
Previous: René ScharfeNext: Jeff King
Message 5 of 10 in “name-rev: use memory pool for name strings”
  1. 0/2 name-rev: use memory pool for name stringsRené Scharfe, Feb 25, 2024
  2. 2/2 name-rev: use mem_pool_strfmt()René Scharfe, Feb 25, 2024
  3. Junio C HamanoFeb 26, 2024
  4. René ScharfeFeb 26, 2024
  5. 1/2 mem-pool: add mem_pool_strfmt()René Scharfe, Feb 25, 2024
  6. Jeff KingFeb 26, 2024
  7. René ScharfeFeb 26, 2024
  8. Jeff KingFeb 27, 2024
  9. René ScharfeFeb 27, 2024
  10. Jeff KingMar 7, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.