shithub: riscv

Download patch

ref: ff16079e49ae585281e4ff0f2aed9620a7273644
parent: c0f464b98fde437a1c6556006e87662827d77096
author: cinap_lenrek <[email protected]>
date: Thu Oct 3 11:49:53 EDT 2019

upas/fs: speedup mtree and henter()

move digest pointer into Mtree structrue and embed it into Idx struct
(which is embedded in Message) to avoid one level of indirection
during mtreecmp().

get rid of mtreeisdup(). instead we have mtreeadd() return the old
message in case of a collision. this avoids double lookup.

increase the hash table size for henter() and make it a prime.

--- a/sys/src/cmd/upas/fs/cache.c
+++ b/sys/src/cmd/upas/fs/cache.c
@@ -319,14 +319,17 @@
 void
 digestmessage(Mailbox *mb, Message *m)
 {
+	Message *old;
+
 	assert(m->digest == nil);
 	m->digest = emalloc(SHA1dlen);
 	sha1((uchar*)m->start, m->end - m->start, m->digest, nil);
-	if(mtreeisdup(mb, m)){
+	old = mtreeadd(mb, m);
+	if(old != nil && old != m){
+		m = mtreeadd(mb, old);
 		logmsg(m, "dup detected");
 		m->deleted = Dup;	/* no dups allowed */
-	}else
-		mtreeadd(mb, m);
+	}
 	dprint("%lud %#A\n", m->id, m->digest);
 }
 
--- a/sys/src/cmd/upas/fs/dat.h
+++ b/sys/src/cmd/upas/fs/dat.h
@@ -42,10 +42,16 @@
 	Nref		= 10,
 };
 
+typedef struct {
+	Avl;
+	uchar	*digest;
+} Mtree;
+
 typedef struct Idx Idx;
 struct Idx {
+	Mtree;
+
 	char	*str;			/* as read from idx file */
-	uchar	*digest;
 	uchar	flags;
 	uvlong	fileid;
 	ulong	lines;
@@ -136,11 +142,6 @@
 	};
 };
 
-typedef struct {
-	Avl;
-	Message *m;
-} Mtree;
-
 typedef struct Mcache Mcache;
 struct Mcache {
 	uvlong	cached;
@@ -256,10 +257,10 @@
 int		vremove(char*);
 int		rename(char *, char*, int);
 
-int		mtreecmp(Avl*, Avl*);
-int		mtreeisdup(Mailbox *, Message *);
+void		mtreeinit(Mailbox *);
+void		mtreefree(Mailbox *);
 Message*	mtreefind(Mailbox*, uchar*);
-void		mtreeadd(Mailbox*, Message*);
+Message*	mtreeadd(Mailbox*, Message*);
 void		mtreedelete(Mailbox*, Message*);
 
 enum {
--- a/sys/src/cmd/upas/fs/fs.c
+++ b/sys/src/cmd/upas/fs/fs.c
@@ -122,7 +122,7 @@
 static	uchar	mbuf[16*1024 + IOHDRSZ];
 static	uchar	mdata[16*1024 + IOHDRSZ];
 static	ulong	path;		/* incremented for each new file */
-static	Hash	*htab[1024];
+static	Hash	*htab[2053];
 static	Fcall	rhdr;
 static	Fcall	thdr;
 static	Fid	*fids;
--- a/sys/src/cmd/upas/fs/mbox.c
+++ b/sys/src/cmd/upas/fs/mbox.c
@@ -267,7 +267,7 @@
 	mb->next = nil;
 	mb->id = newid();
 	mb->root = newmessage(nil);
-	mb->mtree = avlcreate(mtreecmp);
+	mtreeinit(mb);
 
 	*l = mb;
 
@@ -1187,7 +1187,7 @@
 	if(mb->flags & ORCLOSE && mb->remove)
 	if(mb->remove(mb, mb->rmflags))
 		rmidx(mb->path, mb->rmflags);
-	free(mb->mtree);
+	mtreefree(mb);
 	free(mb->d);
 	free(mb);
 }
--- a/sys/src/cmd/upas/fs/mtree.c
+++ b/sys/src/cmd/upas/fs/mtree.c
@@ -2,79 +2,62 @@
 #include <libsec.h>
 #include "dat.h"
 
-int
+#define messageof(p)	((Message*)(((uchar*)&(p)->digest) - offsetof(Message, digest)))
+
+static int
 mtreecmp(Avl *va, Avl *vb)
 {
-	Mtree *a, *b;
-
-	a = (Mtree*)va;
-	b = (Mtree*)vb;
-	return memcmp(a->m->digest, b->m->digest, SHA1dlen);
+	return memcmp(((Mtree*)va)->digest, ((Mtree*)vb)->digest, SHA1dlen);
 }
 
-int
-mtreeisdup(Mailbox *mb, Message *m)
+void
+mtreeinit(Mailbox *mb)
 {
-	Mtree t;
+	mb->mtree = avlcreate(mtreecmp);
+}
 
-	assert(Topmsg(mb, m) && m->digest);
-	if(m->digest == nil)
-		return 0;
-	memset(&t, 0, sizeof t);
-	t.m = m;
-	if(avllookup(mb->mtree, &t, 0))
-		return 1;
-	return 0;
+void
+mtreefree(Mailbox *mb)
+{
+	free(mb->mtree);
+	mb->mtree = nil;
 }
 
 Message*
 mtreefind(Mailbox *mb, uchar *digest)
 {
-	Message m0;
 	Mtree t, *p;
 
-	m0.digest = digest;
-	memset(&t, 0, sizeof t);
-	t.m = &m0;
-	if(p = (Mtree*)avllookup(mb->mtree, &t, 0))
-		return p->m;
-	return nil;
+	t.digest = digest;
+	if((p = (Mtree*)avllookup(mb->mtree, &t, 0)) == nil)
+		return nil;
+	return messageof(p);
 }
 
-void
+Message*
 mtreeadd(Mailbox *mb, Message *m)
 {
-	Avl *old;
-	Mtree *p;
+	Mtree *old;
 
-	assert(Topmsg(mb, m) && m->digest);
-	p = emalloc(sizeof *p);
-	p->m = m;
-	old = avlinsert(mb->mtree, p);
-	assert(old == 0);
+	assert(Topmsg(mb, m) && m->digest != nil);
+	if((old = (Mtree*)avlinsert(mb->mtree, m)) == nil)
+		return nil;
+	return messageof(old);
 }
 
 void
 mtreedelete(Mailbox *mb, Message *m)
 {
-	Mtree t, *p;
+	Mtree *old;
 
 	assert(Topmsg(mb, m));
-	memset(&t, 0, sizeof t);
-	t.m = m;
+	if(m->digest == nil)
+		return;
 	if(m->deleted & ~Deleted){
-		if(m->digest == nil)
+		old = (Mtree*)avllookup(mb->mtree, m, 0);
+		if(old == nil || messageof(old) != m)
 			return;
-		p = (Mtree*)avllookup(mb->mtree, &t, 0);
-		if(p == nil || p->m != m)
-			return;
-		p = (Mtree*)avldelete(mb->mtree, &t);
-		free(p);
-		return;
 	}
-	assert(m->digest);
-	p = (Mtree*)avldelete(mb->mtree, &t);
-	if(p == nil)
-		_assert("mtree delete fails");
-	free(p);
+	old = (Mtree*)avldelete(mb->mtree, m);
+	assert(messageof(old) == m);
 }