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.
This commit is contained in:
parent
c0f464b98f
commit
ff16079e49
5 changed files with 50 additions and 63 deletions
|
@ -319,14 +319,17 @@ found:
|
||||||
void
|
void
|
||||||
digestmessage(Mailbox *mb, Message *m)
|
digestmessage(Mailbox *mb, Message *m)
|
||||||
{
|
{
|
||||||
|
Message *old;
|
||||||
|
|
||||||
assert(m->digest == nil);
|
assert(m->digest == nil);
|
||||||
m->digest = emalloc(SHA1dlen);
|
m->digest = emalloc(SHA1dlen);
|
||||||
sha1((uchar*)m->start, m->end - m->start, m->digest, nil);
|
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");
|
logmsg(m, "dup detected");
|
||||||
m->deleted = Dup; /* no dups allowed */
|
m->deleted = Dup; /* no dups allowed */
|
||||||
}else
|
}
|
||||||
mtreeadd(mb, m);
|
|
||||||
dprint("%lud %#A\n", m->id, m->digest);
|
dprint("%lud %#A\n", m->id, m->digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,10 +42,16 @@ enum {
|
||||||
Nref = 10,
|
Nref = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Avl;
|
||||||
|
uchar *digest;
|
||||||
|
} Mtree;
|
||||||
|
|
||||||
typedef struct Idx Idx;
|
typedef struct Idx Idx;
|
||||||
struct Idx {
|
struct Idx {
|
||||||
|
Mtree;
|
||||||
|
|
||||||
char *str; /* as read from idx file */
|
char *str; /* as read from idx file */
|
||||||
uchar *digest;
|
|
||||||
uchar flags;
|
uchar flags;
|
||||||
uvlong fileid;
|
uvlong fileid;
|
||||||
ulong lines;
|
ulong lines;
|
||||||
|
@ -136,11 +142,6 @@ struct Message {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Avl;
|
|
||||||
Message *m;
|
|
||||||
} Mtree;
|
|
||||||
|
|
||||||
typedef struct Mcache Mcache;
|
typedef struct Mcache Mcache;
|
||||||
struct Mcache {
|
struct Mcache {
|
||||||
uvlong cached;
|
uvlong cached;
|
||||||
|
@ -256,10 +257,10 @@ void rmidx(char*, int);
|
||||||
int vremove(char*);
|
int vremove(char*);
|
||||||
int rename(char *, char*, int);
|
int rename(char *, char*, int);
|
||||||
|
|
||||||
int mtreecmp(Avl*, Avl*);
|
void mtreeinit(Mailbox *);
|
||||||
int mtreeisdup(Mailbox *, Message *);
|
void mtreefree(Mailbox *);
|
||||||
Message* mtreefind(Mailbox*, uchar*);
|
Message* mtreefind(Mailbox*, uchar*);
|
||||||
void mtreeadd(Mailbox*, Message*);
|
Message* mtreeadd(Mailbox*, Message*);
|
||||||
void mtreedelete(Mailbox*, Message*);
|
void mtreedelete(Mailbox*, Message*);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
|
@ -122,7 +122,7 @@ static char hbuf[32*1024];
|
||||||
static uchar mbuf[16*1024 + IOHDRSZ];
|
static uchar mbuf[16*1024 + IOHDRSZ];
|
||||||
static uchar mdata[16*1024 + IOHDRSZ];
|
static uchar mdata[16*1024 + IOHDRSZ];
|
||||||
static ulong path; /* incremented for each new file */
|
static ulong path; /* incremented for each new file */
|
||||||
static Hash *htab[1024];
|
static Hash *htab[2053];
|
||||||
static Fcall rhdr;
|
static Fcall rhdr;
|
||||||
static Fcall thdr;
|
static Fcall thdr;
|
||||||
static Fid *fids;
|
static Fid *fids;
|
||||||
|
|
|
@ -267,7 +267,7 @@ newmbox(char *path, char *name, int flags, Mailbox **r)
|
||||||
mb->next = nil;
|
mb->next = nil;
|
||||||
mb->id = newid();
|
mb->id = newid();
|
||||||
mb->root = newmessage(nil);
|
mb->root = newmessage(nil);
|
||||||
mb->mtree = avlcreate(mtreecmp);
|
mtreeinit(mb);
|
||||||
|
|
||||||
*l = mb;
|
*l = mb;
|
||||||
|
|
||||||
|
@ -1187,7 +1187,7 @@ mboxdecref(Mailbox *mb)
|
||||||
if(mb->flags & ORCLOSE && mb->remove)
|
if(mb->flags & ORCLOSE && mb->remove)
|
||||||
if(mb->remove(mb, mb->rmflags))
|
if(mb->remove(mb, mb->rmflags))
|
||||||
rmidx(mb->path, mb->rmflags);
|
rmidx(mb->path, mb->rmflags);
|
||||||
free(mb->mtree);
|
mtreefree(mb);
|
||||||
free(mb->d);
|
free(mb->d);
|
||||||
free(mb);
|
free(mb);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,79 +2,62 @@
|
||||||
#include <libsec.h>
|
#include <libsec.h>
|
||||||
#include "dat.h"
|
#include "dat.h"
|
||||||
|
|
||||||
int
|
#define messageof(p) ((Message*)(((uchar*)&(p)->digest) - offsetof(Message, digest)))
|
||||||
|
|
||||||
|
static int
|
||||||
mtreecmp(Avl *va, Avl *vb)
|
mtreecmp(Avl *va, Avl *vb)
|
||||||
{
|
{
|
||||||
Mtree *a, *b;
|
return memcmp(((Mtree*)va)->digest, ((Mtree*)vb)->digest, SHA1dlen);
|
||||||
|
|
||||||
a = (Mtree*)va;
|
|
||||||
b = (Mtree*)vb;
|
|
||||||
return memcmp(a->m->digest, b->m->digest, SHA1dlen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
mtreeisdup(Mailbox *mb, Message *m)
|
mtreeinit(Mailbox *mb)
|
||||||
{
|
{
|
||||||
Mtree t;
|
mb->mtree = avlcreate(mtreecmp);
|
||||||
|
}
|
||||||
|
|
||||||
assert(Topmsg(mb, m) && m->digest);
|
void
|
||||||
if(m->digest == nil)
|
mtreefree(Mailbox *mb)
|
||||||
return 0;
|
{
|
||||||
memset(&t, 0, sizeof t);
|
free(mb->mtree);
|
||||||
t.m = m;
|
mb->mtree = nil;
|
||||||
if(avllookup(mb->mtree, &t, 0))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Message*
|
Message*
|
||||||
mtreefind(Mailbox *mb, uchar *digest)
|
mtreefind(Mailbox *mb, uchar *digest)
|
||||||
{
|
{
|
||||||
Message m0;
|
|
||||||
Mtree t, *p;
|
Mtree t, *p;
|
||||||
|
|
||||||
m0.digest = digest;
|
t.digest = digest;
|
||||||
memset(&t, 0, sizeof t);
|
if((p = (Mtree*)avllookup(mb->mtree, &t, 0)) == nil)
|
||||||
t.m = &m0;
|
return nil;
|
||||||
if(p = (Mtree*)avllookup(mb->mtree, &t, 0))
|
return messageof(p);
|
||||||
return p->m;
|
|
||||||
return nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
Message*
|
||||||
mtreeadd(Mailbox *mb, Message *m)
|
mtreeadd(Mailbox *mb, Message *m)
|
||||||
{
|
{
|
||||||
Avl *old;
|
Mtree *old;
|
||||||
Mtree *p;
|
|
||||||
|
|
||||||
assert(Topmsg(mb, m) && m->digest);
|
assert(Topmsg(mb, m) && m->digest != nil);
|
||||||
p = emalloc(sizeof *p);
|
if((old = (Mtree*)avlinsert(mb->mtree, m)) == nil)
|
||||||
p->m = m;
|
return nil;
|
||||||
old = avlinsert(mb->mtree, p);
|
return messageof(old);
|
||||||
assert(old == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mtreedelete(Mailbox *mb, Message *m)
|
mtreedelete(Mailbox *mb, Message *m)
|
||||||
{
|
{
|
||||||
Mtree t, *p;
|
Mtree *old;
|
||||||
|
|
||||||
assert(Topmsg(mb, m));
|
assert(Topmsg(mb, m));
|
||||||
memset(&t, 0, sizeof t);
|
if(m->digest == nil)
|
||||||
t.m = m;
|
|
||||||
if(m->deleted & ~Deleted){
|
|
||||||
if(m->digest == nil)
|
|
||||||
return;
|
|
||||||
p = (Mtree*)avllookup(mb->mtree, &t, 0);
|
|
||||||
if(p == nil || p->m != m)
|
|
||||||
return;
|
|
||||||
p = (Mtree*)avldelete(mb->mtree, &t);
|
|
||||||
free(p);
|
|
||||||
return;
|
return;
|
||||||
|
if(m->deleted & ~Deleted){
|
||||||
|
old = (Mtree*)avllookup(mb->mtree, m, 0);
|
||||||
|
if(old == nil || messageof(old) != m)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
assert(m->digest);
|
old = (Mtree*)avldelete(mb->mtree, m);
|
||||||
p = (Mtree*)avldelete(mb->mtree, &t);
|
assert(messageof(old) == m);
|
||||||
if(p == nil)
|
|
||||||
_assert("mtree delete fails");
|
|
||||||
free(p);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue