forked from github/server
Slightly more cache-friendly hashing (WIP)
This commit is contained in:
parent
34edc042bc
commit
23505d2b84
4 changed files with 130 additions and 73 deletions
|
@ -633,40 +633,6 @@ shipspeed (const ship * sh, const unit * u)
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* erwartete Anzahl Einheiten x 2 */
|
|
||||||
#define UMAXHASH 199999
|
|
||||||
unit *unithash[UMAXHASH];
|
|
||||||
|
|
||||||
void
|
|
||||||
uhash (unit * u)
|
|
||||||
{
|
|
||||||
assert(!u->nexthash || !"unit ist bereits gehasht");
|
|
||||||
u->nexthash = unithash[u->no % UMAXHASH];
|
|
||||||
unithash[u->no % UMAXHASH] = u;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uunhash (unit * u)
|
|
||||||
{
|
|
||||||
unit ** x = &(unithash[u->no % UMAXHASH]);
|
|
||||||
while (*x && *x!=u) x = &(*x)->nexthash;
|
|
||||||
assert(*x || !"unit nicht gefunden");
|
|
||||||
*x = u->nexthash;
|
|
||||||
u->nexthash=NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
unit *
|
|
||||||
ufindhash (int i)
|
|
||||||
{
|
|
||||||
assert(i>=0);
|
|
||||||
if (i>=0) {
|
|
||||||
unit * u = unithash[i % UMAXHASH];
|
|
||||||
while (u && u->no!=i) u = u->nexthash;
|
|
||||||
return u;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FMAXHASH 2039
|
#define FMAXHASH 2039
|
||||||
faction * factionhash[FMAXHASH];
|
faction * factionhash[FMAXHASH];
|
||||||
|
|
||||||
|
@ -1438,7 +1404,10 @@ findunitr (const region * r, int n)
|
||||||
|
|
||||||
unit *findunit(int n)
|
unit *findunit(int n)
|
||||||
{
|
{
|
||||||
return findunitg(n, NULL);
|
if (n <= 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ufindhash(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
unit *
|
unit *
|
||||||
|
|
|
@ -39,8 +39,12 @@ extern "C" {
|
||||||
|
|
||||||
#define ALLIED(f1, f2) (f1==f2 || (f1->alliance && f1->alliance==f2->alliance))
|
#define ALLIED(f1, f2) (f1==f2 || (f1->alliance && f1->alliance==f2->alliance))
|
||||||
|
|
||||||
|
/* for some good prime numbers, check http://www.math.niu.edu/~rusin/known-math/98/pi_x */
|
||||||
#ifndef MAXREGIONS
|
#ifndef MAXREGIONS
|
||||||
# define MAXREGIONS 262139 /* must be prime for hashing. 262139=last<2^18 */
|
# define MAXREGIONS 262139 /* must be prime for hashing. */
|
||||||
|
#endif
|
||||||
|
#ifndef MAXUNITS
|
||||||
|
# define MAXUNITS 524287 /* must be prime for hashing. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MONSTER_FACTION 0 /* Die Partei, in der die Monster sind. */
|
#define MONSTER_FACTION 0 /* Die Partei, in der die Monster sind. */
|
||||||
|
@ -274,11 +278,6 @@ void changeblockchaos(void);
|
||||||
extern struct region *firstregion(struct faction * f);
|
extern struct region *firstregion(struct faction * f);
|
||||||
extern struct region *lastregion(struct faction * f);
|
extern struct region *lastregion(struct faction * f);
|
||||||
|
|
||||||
void inituhash(void);
|
|
||||||
void uhash(struct unit * u);
|
|
||||||
void uunhash(struct unit * u);
|
|
||||||
struct unit *ufindhash(int i);
|
|
||||||
|
|
||||||
void fhash(struct faction * f);
|
void fhash(struct faction * f);
|
||||||
void funhash(struct faction * f);
|
void funhash(struct faction * f);
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,92 @@ attrib_type at_creator = {
|
||||||
/* Rest ist NULL; temporäres, nicht alterndes Attribut */
|
/* Rest ist NULL; temporäres, nicht alterndes Attribut */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define UMAXHASH MAXUNITS
|
||||||
|
static unit * unithash[UMAXHASH];
|
||||||
|
static unit * delmarker = (unit*)unithash; /* a funny hack */
|
||||||
|
|
||||||
|
#define HASH_STATISTICS 1
|
||||||
|
#if HASH_STATISTICS
|
||||||
|
static int hash_requests;
|
||||||
|
static int hash_misses;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* benchmark:
|
||||||
|
* jenkins_hash: 5.25 misses/hit
|
||||||
|
* wang_hash: 5.33 misses/hit
|
||||||
|
*/
|
||||||
|
|
||||||
|
INLINE_FUNCTION unsigned int jenkins_hash(unsigned int a)
|
||||||
|
{
|
||||||
|
a = (a+0x7ed55d16) + (a<<12);
|
||||||
|
a = (a^0xc761c23c) ^ (a>>19);
|
||||||
|
a = (a+0x165667b1) + (a<<5);
|
||||||
|
a = (a+0xd3a2646c) ^ (a<<9);
|
||||||
|
a = (a+0xfd7046c5) + (a<<3);
|
||||||
|
a = (a^0xb55a4f09) ^ (a>>16);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE_FUNCTION unsigned int wang_hash(unsigned int a)
|
||||||
|
{
|
||||||
|
a = ~a + (a << 15); // a = (a << 15) - a - 1;
|
||||||
|
a = a ^ (a >> 12);
|
||||||
|
a = a + (a << 2);
|
||||||
|
a = a ^ (a >> 4);
|
||||||
|
a = a * 2057; // a = (a + (a << 3)) + (a << 11);
|
||||||
|
a = a ^ (a >> 16);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HASH1(a, m) (jenkins_hash(a) % m)
|
||||||
|
#define HASH2(a, m) 1
|
||||||
|
/*
|
||||||
|
#define HASH1(a, m) ((a) % m)
|
||||||
|
#define HASH2(a, m) (m - 2 - a % (m-2))
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
uhash(unit * u)
|
||||||
|
{
|
||||||
|
int key = HASH1(u->no, UMAXHASH), gk = HASH2(u->no, UMAXHASH);
|
||||||
|
while (unithash[key]!=NULL && unithash[key]!=delmarker && unithash[key]!=u) {
|
||||||
|
key = (key + gk) % UMAXHASH;
|
||||||
|
}
|
||||||
|
assert(unithash[key]!=u || !"trying to add the same unit twice");
|
||||||
|
unithash[key] = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uunhash(unit * u)
|
||||||
|
{
|
||||||
|
int key = HASH1(u->no, UMAXHASH), gk = HASH2(u->no, UMAXHASH);
|
||||||
|
while (unithash[key]!=NULL && unithash[key]!=u) {
|
||||||
|
key = (key + gk) % UMAXHASH;
|
||||||
|
}
|
||||||
|
assert(unithash[key]==u || !"trying to remove a unit that is not hashed");
|
||||||
|
unithash[key] = delmarker;
|
||||||
|
}
|
||||||
|
|
||||||
|
unit *
|
||||||
|
ufindhash(int uid)
|
||||||
|
{
|
||||||
|
assert(uid>=0);
|
||||||
|
#if HASH_STATISTICS
|
||||||
|
++hash_requests;
|
||||||
|
#endif
|
||||||
|
if (uid>=0) {
|
||||||
|
int key = HASH1(uid, UMAXHASH), gk = HASH2(uid, UMAXHASH);
|
||||||
|
while (unithash[key]!=NULL && (unithash[key]==delmarker || unithash[key]->no!=uid)) {
|
||||||
|
key = (key + gk) % UMAXHASH;
|
||||||
|
#if HASH_STATISTICS
|
||||||
|
++hash_misses;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return unithash[key];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#define DMAXHASH 7919
|
#define DMAXHASH 7919
|
||||||
typedef struct dead {
|
typedef struct dead {
|
||||||
struct dead * nexthash;
|
struct dead * nexthash;
|
||||||
|
|
|
@ -77,7 +77,6 @@ extern int countheroes(const struct faction * f);
|
||||||
|
|
||||||
typedef struct unit {
|
typedef struct unit {
|
||||||
struct unit *next; /* needs to be first entry, for region's unitlist */
|
struct unit *next; /* needs to be first entry, for region's unitlist */
|
||||||
struct unit *nexthash;
|
|
||||||
struct unit *nextF; /* nächste Einheit der Partei */
|
struct unit *nextF; /* nächste Einheit der Partei */
|
||||||
struct region *region;
|
struct region *region;
|
||||||
int no;
|
int no;
|
||||||
|
@ -217,6 +216,10 @@ extern void stripunit(struct unit * u);
|
||||||
extern void name_unit(struct unit *u);
|
extern void name_unit(struct unit *u);
|
||||||
extern struct unit * create_unit(struct region * r1, struct faction * f, int number, const struct race * rc, int id, const char * dname, struct unit *creator);
|
extern struct unit * create_unit(struct region * r1, struct faction * f, int number, const struct race * rc, int id, const char * dname, struct unit *creator);
|
||||||
|
|
||||||
|
extern void uhash(struct unit * u);
|
||||||
|
extern void uunhash(struct unit * u);
|
||||||
|
extern struct unit *ufindhash(int i);
|
||||||
|
|
||||||
extern struct attrib_type at_creator;
|
extern struct attrib_type at_creator;
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue