Thread (75 messages) 75 messages, 10 authors, 2021-09-28

Re: [PATCH v2 5/5] oidtree: a crit-bit tree for odb_loose_cache

flat view

From: Eric Wong <hidden>
Date: 2021-07-06 23:22:00

René Scharfe [off-list ref] wrote:
Am 29.06.21 um 22:53 schrieb Eric Wong:
quoted
--- a/alloc.c
+++ b/alloc.c
@@ -14,6 +14,7 @@
 #include "tree.h"
 #include "commit.h"
 #include "tag.h"
+#include "oidtree.h"
 #include "alloc.h"

 #define BLOCKING 1024
@@ -123,6 +124,11 @@ void *alloc_commit_node(struct repository *r)
 	return c;
 }

+void *alloc_from_state(struct alloc_state *alloc_state, size_t n)
+{
+	return alloc_node(alloc_state, n);
+}
+
Why extend alloc.c instead of using mem-pool.c?  (I don't know which fits
better, but when you say "memory pool" and not use mem-pool.c I just have
to ask..)
I didn't know mem-pool.c existed :x  (And I've always known
about alloc.c).

Perhaps we could merge them in another series to avoid further
confusion.
quoted
+void oidtree_insert(struct oidtree *ot, const struct object_id *oid)
+{
+	struct oidtree_node *on;
+
+	if (!ot->mempool)
+		ot->mempool = allocate_alloc_state();
+	if (!oid->algo)
+		BUG("oidtree_insert requires oid->algo");
+
+	on = alloc_from_state(ot->mempool, sizeof(*on) + sizeof(*oid));
+	oidcpy_with_padding((struct object_id *)on->n.k, oid);
+
+	/*
+	 * n.b. we shouldn't get duplicates, here, but we'll have
+	 * a small leak that won't be freed until oidtree_destroy
+	 */
Why shouldn't we get duplicates?  That depends on the usage of oidtree,
right?  The current user is fine because we avoid reading the same loose
object directory twice using the loose_objects_subdir_seen bitmap.
Yes, it reflects the current caller.
The leak comes from the allocation above, which is not used in case we
already have the key in the oidtree.  So we need memory for all
candidates, not just the inserted candidates.  That's probably
acceptable in most use cases.
Yes, I think the small, impossible-due-to-current-usage leak is
an acceptable trade off.
We can do better by keeping track of the unnecessary allocation in
struct oidtree and recycling it at the next insert attempt, however.
That way we'd only waste at most one slot.
It'd involve maintaining a free list; which may be better
suited to being in alloc_state or mem_pool.  That would also
increase the size of a struct *somewhere* and add a small
amount of code complexity, too.
quoted
+	cb_insert(&ot->t, &on->n, sizeof(*oid));
+}
+
+int oidtree_contains(struct oidtree *ot, const struct object_id *oid)
+{
+	struct object_id k = { 0 };
+	size_t klen = sizeof(k);
+	oidcpy_with_padding(&k, oid);
Why initialize k; isn't oidcpy_with_padding() supposed to overwrite it
completely?
Ah, I only added oidcpy_with_padding later into the development
of this patch.
quoted
+
+	if (oid->algo == GIT_HASH_UNKNOWN) {
+		k.algo = hash_algo_by_ptr(the_hash_algo);
+		klen -= sizeof(oid->algo);
+	}
This relies on the order of the members hash and algo in struct
object_id to find a matching hash if we don't actually know algo.  It
also relies on the absence of padding after algo.  Would something like
this make sense?

   BUILD_ASSERT_OR_ZERO(offsetof(struct object_id, algo) + sizeof(k.algo) == sizeof(k));
Maybe... I think a static assertion that object_id.hash be the
first element of "struct object_id" is definitely needed, at
least.
And why set k.algo to some arbitrary value if we ignore it anyway?  I.e.
why not keep it GIT_HASH_UNKNOWN, as set by oidcpy_with_padding()?
Good point, shortening klen would've been all that was needed.
quoted
+void oidtree_each(struct oidtree *ot, const struct object_id *oid,
+			size_t oidhexlen, oidtree_iter fn, void *arg)
+{
+	size_t klen = oidhexlen / 2;
+	struct oidtree_iter_data x = { 0 };
+
+	x.fn = fn;
+	x.arg = arg;
+	x.algo = oid->algo;
+	if (oidhexlen & 1) {
+		x.last_byte = oid->hash[klen];
+		x.last_nibble_at = &klen;
+	}
+	cb_each(&ot->t, (const uint8_t *)oid, klen, iter, &x);
+}
Clamp oidhexlen at GIT_MAX_HEXSZ?  Or die?
I think an assertion would be enough, here.
init_object_disambiguation already clamps to the_hash_algo->hexsz
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help