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

[PATCH v3 6/8] reftable/record: store "val2" hashes as static arrays

From
Patrick Steinhardt <ps@pks.im>
Date
Jan 3, 2024, 06:22 UTC
Message-ID
<6ec02d6775c0f3e3274d57ef4a7dfeefac8308a9.1704262787.git.ps@pks.im>
In-Reply-To
<cover.1704262787.git.ps@pks.im>

Similar to the preceding commit, convert ref records of type "val2" to store their object IDs in static arrays instead of allocating them for every single record.

We're using the same benchmark as in the preceding commit, with `git show-ref --quiet` in a repository with ~350k refs. This time around though the effects aren't this huge. Before:

    HEAP SUMMARY:
        in use at exit: 21,163 bytes in 193 blocks
      total heap usage: 1,419,040 allocs, 1,418,847 frees, 62,153,868 bytes allocated
After:
    HEAP SUMMARY:
        in use at exit: 21,163 bytes in 193 blocks
      total heap usage: 1,410,148 allocs, 1,409,955 frees, 61,976,068 bytes allocated

This is because "val2"-type records are typically only stored for peeled tags, and the number of annotated tags in the benchmark repository is rather low. Still, it can be seen that this change leads to a reduction of allocations overall, even if only a small one.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 reftable/readwrite_test.c  | 12 ++++--------
 reftable/record.c          |  6 ------
 reftable/record_test.c     |  4 ----
 reftable/reftable-record.h |  4 ++--
 4 files changed, 6 insertions(+), 20 deletions(-)
diff --git a/reftable/readwrite_test.c b/reftable/readwrite_test.c
index 87b238105c..178766dfa8 100644
--- a/reftable/readwrite_test.c
+++ b/reftable/readwrite_test.c
@@ -547,8 +547,6 @@ static void test_table_refs_for(int indexed)
 		uint8_t hash[GIT_SHA1_RAWSZ];
 		char fill[51] = { 0 };
 		char name[100];
-		uint8_t hash1[GIT_SHA1_RAWSZ];
-		uint8_t hash2[GIT_SHA1_RAWSZ];
 		struct reftable_ref_record ref = { NULL };
 
 		memset(hash, i, sizeof(hash));
@@ -558,11 +556,9 @@ static void test_table_refs_for(int indexed)
 		name[40] = 0;
 		ref.refname = name;
 
-		set_test_hash(hash1, i / 4);
-		set_test_hash(hash2, 3 + i / 4);
 		ref.value_type = REFTABLE_REF_VAL2;
-		ref.value.val2.value = hash1;
-		ref.value.val2.target_value = hash2;
+		set_test_hash(ref.value.val2.value, i / 4);
+		set_test_hash(ref.value.val2.target_value, 3 + i / 4);
 
 		/* 80 bytes / entry, so 3 entries per block. Yields 17
 		 */
@@ -570,8 +566,8 @@ static void test_table_refs_for(int indexed)
 		n = reftable_writer_add_ref(w, &ref);
 		EXPECT(n == 0);
 
-		if (!memcmp(hash1, want_hash, GIT_SHA1_RAWSZ) ||
-		    !memcmp(hash2, want_hash, GIT_SHA1_RAWSZ)) {
+		if (!memcmp(ref.value.val2.value, want_hash, GIT_SHA1_RAWSZ) ||
+		    !memcmp(ref.value.val2.target_value, want_hash, GIT_SHA1_RAWSZ)) {
 			want_names[want_names_len++] = xstrdup(name);
 		}
 	}
diff --git a/reftable/record.c b/reftable/record.c
index a67a6b4d8a..5c3fbb7b2a 100644
--- a/reftable/record.c
+++ b/reftable/record.c
@@ -222,9 +222,7 @@ static void reftable_ref_record_copy_from(void *rec, const void *src_rec,
 		memcpy(ref->value.val1, src->value.val1, hash_size);
 		break;
 	case REFTABLE_REF_VAL2:
-		ref->value.val2.value = reftable_malloc(hash_size);
 		memcpy(ref->value.val2.value, src->value.val2.value, hash_size);
-		ref->value.val2.target_value = reftable_malloc(hash_size);
 		memcpy(ref->value.val2.target_value,
 		       src->value.val2.target_value, hash_size);
 		break;
@@ -298,8 +296,6 @@ void reftable_ref_record_release(struct reftable_ref_record *ref)
 		reftable_free(ref->value.symref);
 		break;
 	case REFTABLE_REF_VAL2:
-		reftable_free(ref->value.val2.target_value);
-		reftable_free(ref->value.val2.value);
 		break;
 	case REFTABLE_REF_VAL1:
 		break;
@@ -401,11 +397,9 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
 			return -1;
 		}
 
-		r->value.val2.value = reftable_malloc(hash_size);
 		memcpy(r->value.val2.value, in.buf, hash_size);
 		string_view_consume(&in, hash_size);
 
-		r->value.val2.target_value = reftable_malloc(hash_size);
 		memcpy(r->value.val2.target_value, in.buf, hash_size);
 		string_view_consume(&in, hash_size);
 		break;
diff --git a/reftable/record_test.c b/reftable/record_test.c
index 5c94d26e35..2876db7d27 100644
--- a/reftable/record_test.c
+++ b/reftable/record_test.c
@@ -122,11 +122,7 @@ static void test_reftable_ref_record_roundtrip(void)
 			set_hash(in.u.ref.value.val1, 1);
 			break;
 		case REFTABLE_REF_VAL2:
-			in.u.ref.value.val2.value =
-				reftable_malloc(GIT_SHA1_RAWSZ);
 			set_hash(in.u.ref.value.val2.value, 1);
-			in.u.ref.value.val2.target_value =
-				reftable_malloc(GIT_SHA1_RAWSZ);
 			set_hash(in.u.ref.value.val2.target_value, 2);
 			break;
 		case REFTABLE_REF_SYMREF:
diff --git a/reftable/reftable-record.h b/reftable/reftable-record.h
index 7f3a0df635..bb6e99acd3 100644
--- a/reftable/reftable-record.h
+++ b/reftable/reftable-record.h
@@ -41,8 +41,8 @@ struct reftable_ref_record {
 	union {
 		unsigned char val1[GIT_MAX_RAWSZ];
 		struct {
-			uint8_t *value; /* first value, malloced hash  */
-			uint8_t *target_value; /* second value, malloced hash */
+			unsigned char value[GIT_MAX_RAWSZ]; /* first hash  */
+			unsigned char target_value[GIT_MAX_RAWSZ]; /* second hash */
 		} val2;
 		char *symref; /* referent, malloced 0-terminated string */
 	} value;
-- 
2.43.GIT
Previous: Patrick SteinhardtNext: Patrick Steinhardt
Message 33 of 36 in “reftable: fixes and optimizations (pt.2)”
  1. 0/7 reftable: fixes and optimizations (pt.2)Patrick Steinhardt, Dec 20, 2023
  2. 1/7 reftable/stack: do not overwrite errors when compactingPatrick Steinhardt, Dec 20, 2023
  3. 2/7 reftable/writer: fix index corruption when writing multiple indicesPatrick Steinhardt, Dec 20, 2023
  4. 3/7 reftable/record: constify some parts of the interfacePatrick Steinhardt, Dec 20, 2023
  5. 4/7 reftable/record: store "val1" hashes as static arraysPatrick Steinhardt, Dec 20, 2023
  6. Patrick SteinhardtDec 20, 2023
  7. 5/7 reftable/record: store "val2" hashes as static arraysPatrick Steinhardt, Dec 20, 2023
  8. 6/7 reftable/merged: really reuse buffers to compute record keysPatrick Steinhardt, Dec 20, 2023
  9. 7/7 reftable/merged: transfer ownership of records when iteratingPatrick Steinhardt, Dec 20, 2023
  10. Junio C HamanoDec 20, 2023
  11. 0/8 reftable: fixes and optimizations (pt.2)Patrick Steinhardt, Dec 28, 2023
  12. 1/8 reftable/stack: do not overwrite errors when compactingPatrick Steinhardt, Dec 28, 2023
  13. 2/8 reftable/stack: do not auto-compact twice in `reftable_stack_add()`Patrick Steinhardt, Dec 28, 2023
  14. 3/8 reftable/writer: fix index corruption when writing multiple indicesPatrick Steinhardt, Dec 28, 2023
  15. 4/8 reftable/record: constify some parts of the interfacePatrick Steinhardt, Dec 28, 2023
  16. 5/8 reftable/record: store "val1" hashes as static arraysPatrick Steinhardt, Dec 28, 2023
  17. Junio C HamanoDec 28, 2023
  18. 6/8 reftable/record: store "val2" hashes as static arraysPatrick Steinhardt, Dec 28, 2023
  19. 7/8 reftable/merged: really reuse buffers to compute record keysPatrick Steinhardt, Dec 28, 2023
  20. Junio C HamanoDec 28, 2023
  21. 8/8 reftable/merged: transfer ownership of records when iteratingPatrick Steinhardt, Dec 28, 2023
  22. Junio C HamanoDec 28, 2023
  23. 0/8 reftable: fixes and optimizations (pt.2)Patrick Steinhardt, Jan 3, 2024
  24. 1/8 reftable/stack: do not overwrite errors when compactingPatrick Steinhardt, Jan 3, 2024
  25. Han-Wen NienhuysFeb 14, 2024
  26. Patrick SteinhardtFeb 15, 2024
  27. 2/8 reftable/stack: do not auto-compact twice in `reftable_stack_add()`Patrick Steinhardt, Jan 3, 2024
  28. 3/8 reftable/writer: fix index corruption when writing multiple indicesPatrick Steinhardt, Jan 3, 2024
  29. 4/8 reftable/record: constify some parts of the interfacePatrick Steinhardt, Jan 3, 2024
  30. 5/8 reftable/record: store "val1" hashes as static arraysPatrick Steinhardt, Jan 3, 2024
  31. Karthik NayakFeb 5, 2024
  32. Patrick SteinhardtFeb 6, 2024
  33. 6/8 reftable/record: store "val2" hashes as static arraysPatrick Steinhardt, Jan 3, 2024
  34. 7/8 reftable/merged: really reuse buffers to compute record keysPatrick Steinhardt, Jan 3, 2024
  35. 8/8 reftable/merged: transfer ownership of records when iteratingPatrick Steinhardt, Jan 3, 2024
  36. Karthik NayakFeb 5, 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.