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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
faction * factionhash[FMAXHASH];
|
||||
|
||||
|
@ -1438,7 +1404,10 @@ findunitr (const region * r, int n)
|
|||
|
||||
unit *findunit(int n)
|
||||
{
|
||||
return findunitg(n, NULL);
|
||||
if (n <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
return ufindhash(n);
|
||||
}
|
||||
|
||||
unit *
|
||||
|
@ -1446,12 +1415,12 @@ findunitg (int n, const region * hint)
|
|||
{
|
||||
|
||||
/* Abfangen von Syntaxfehlern. */
|
||||
if(n <= 0)
|
||||
if (n <= 0)
|
||||
return NULL;
|
||||
|
||||
/* findunit global! */
|
||||
hint = 0;
|
||||
return ufindhash (n);
|
||||
return ufindhash(n);
|
||||
}
|
||||
|
||||
unit *
|
||||
|
|
|
@ -39,8 +39,12 @@ extern "C" {
|
|||
|
||||
#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
|
||||
# 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
|
||||
|
||||
#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 *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 funhash(struct faction * f);
|
||||
|
||||
|
|
|
@ -67,6 +67,92 @@ attrib_type at_creator = {
|
|||
/* 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
|
||||
typedef struct dead {
|
||||
struct dead * nexthash;
|
||||
|
|
|
@ -76,48 +76,47 @@ extern int countheroes(const struct faction * f);
|
|||
#endif
|
||||
|
||||
typedef struct unit {
|
||||
struct unit *next; /* needs to be first entry, for region's unitlist */
|
||||
struct unit *nexthash;
|
||||
struct unit *nextF; /* nächste Einheit der Partei */
|
||||
struct region *region;
|
||||
struct unit *next; /* needs to be first entry, for region's unitlist */
|
||||
struct unit *nextF; /* nächste Einheit der Partei */
|
||||
struct region *region;
|
||||
int no;
|
||||
int hp;
|
||||
char *name;
|
||||
char *display;
|
||||
struct faction *faction;
|
||||
struct building *building;
|
||||
struct ship *ship;
|
||||
char *name;
|
||||
char *display;
|
||||
struct faction *faction;
|
||||
struct building *building;
|
||||
struct ship *ship;
|
||||
unsigned short number;
|
||||
short age;
|
||||
|
||||
/* skill data */
|
||||
short skill_size;
|
||||
struct skill *skills;
|
||||
struct item * items;
|
||||
struct reservation {
|
||||
struct reservation * next;
|
||||
const struct resource_type * type;
|
||||
int value;
|
||||
} * reservations;
|
||||
/* skill data */
|
||||
short skill_size;
|
||||
struct skill *skills;
|
||||
struct item * items;
|
||||
struct reservation {
|
||||
struct reservation * next;
|
||||
const struct resource_type * type;
|
||||
int value;
|
||||
} * reservations;
|
||||
|
||||
/* orders */
|
||||
struct order * orders;
|
||||
struct order * thisorder;
|
||||
/* orders */
|
||||
struct order * orders;
|
||||
struct order * thisorder;
|
||||
#ifdef LASTORDER
|
||||
struct order * lastorder;
|
||||
struct order * lastorder;
|
||||
#else
|
||||
struct order * old_orders;
|
||||
#endif
|
||||
|
||||
/* race and illusionary race */
|
||||
const struct race * race;
|
||||
const struct race * irace;
|
||||
/* race and illusionary race */
|
||||
const struct race * race;
|
||||
const struct race * irace;
|
||||
|
||||
unsigned int flags;
|
||||
struct attrib * attribs;
|
||||
status_t status;
|
||||
int n; /* enno: attribut? */
|
||||
int wants; /* enno: attribut? */
|
||||
unsigned int flags;
|
||||
struct attrib * attribs;
|
||||
status_t status;
|
||||
int n; /* enno: attribut? */
|
||||
int wants; /* enno: attribut? */
|
||||
} unit;
|
||||
|
||||
typedef struct unit_list {
|
||||
|
@ -217,6 +216,10 @@ extern void stripunit(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 void uhash(struct unit * u);
|
||||
extern void uunhash(struct unit * u);
|
||||
extern struct unit *ufindhash(int i);
|
||||
|
||||
extern struct attrib_type at_creator;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue