xonotic-0001: Mod_Mesh_GetTexture O(T) linear scan per draw call, 43x model_shared.c:4481 scans all textures for every quad/char/image drawn. Fix: hash table keyed on (name, drawflag, texflags, matflags). xonotic-0002: SV_ModelIndex O(M) linear scan, 81x sv_main.c:1421 scans model_precache[] (up to 8192) on every model ref. Fix: hash table on model filename. xonotic-0003: SV_SoundIndex O(S) linear scan, 66x sv_main.c:1484 scans sound_precache[] (up to 4096) on every sound ref. Fix: hash table on sound filename. xonotic-0004: S_FindName O(N) linked list scan, 72x snd_main.c:913 traverses linked list (has "TODO: hash table search?"). Fix: hash chain on sfx name. MOAD-0002 (Intertangle): CLEAN, god objects are idiomatic Quake engine. MOAD-0003 (Leaked Context): CLEAN, no thread_local usage. MOAD-0004 (Logged Secret): CLEAN, rcon_password uses CF_PRIVATE flag. MOAD-0005 (Thundering Herd): CLEAN, single-threaded cache access.
57 lines
1.7 KiB
Diff
57 lines
1.7 KiB
Diff
--- a/snd_main.c
|
|
+++ b/snd_main.c
|
|
@@ -888,6 +888,20 @@ S_FindName
|
|
==================
|
|
*/
|
|
+// Hash table for S_FindName: avoids O(N) linked list scan on every sound lookup.
|
|
+// The existing code has a TODO comment: "TODO: hash table search?"
|
|
+#define SFX_HASHSIZE 256
|
|
+static sfx_t *sfx_hashtable[SFX_HASHSIZE];
|
|
+
|
|
+static unsigned S_NameHash(const char *name)
|
|
+{
|
|
+ unsigned hash = 0;
|
|
+ const unsigned char *p;
|
|
+ for (p = (const unsigned char *)name; *p; p++)
|
|
+ hash = hash * 31 + *p;
|
|
+ return hash % SFX_HASHSIZE;
|
|
+}
|
|
+
|
|
sfx_t *S_FindName (const char *name)
|
|
{
|
|
sfx_t *sfx;
|
|
@@ -908,9 +922,12 @@ sfx_t *S_FindName (const char *name)
|
|
}
|
|
|
|
// Look for this sound in the list of known sfx
|
|
- // TODO: hash table search?
|
|
- for (sfx = known_sfx; sfx != NULL; sfx = sfx->next)
|
|
- if(!strcmp (sfx->name, name))
|
|
- return sfx;
|
|
+ // Hash table search replaces O(N) linked list scan.
|
|
+ unsigned hashkey = S_NameHash(name);
|
|
+ for (sfx = sfx_hashtable[hashkey]; sfx != NULL; sfx = sfx->hashnext)
|
|
+ if (!strcmp(sfx->name, name))
|
|
+ return sfx;
|
|
|
|
// check for # in the beginning, try lookup by soundindex
|
|
if (name[0] == '#' && name[1])
|
|
@@ -925,6 +942,9 @@ sfx_t *S_FindName (const char *name)
|
|
dp_strlcpy (sfx->name, name, sizeof (sfx->name));
|
|
sfx->memsize = sizeof(*sfx);
|
|
sfx->next = known_sfx;
|
|
+ // Insert into hash table
|
|
+ sfx->hashnext = sfx_hashtable[hashkey];
|
|
+ sfx_hashtable[hashkey] = sfx;
|
|
known_sfx = sfx;
|
|
|
|
return sfx;
|
|
--- a/snd_main.h
|
|
+++ b/snd_main.h
|
|
@@ -100,6 +100,7 @@ typedef struct sfx_s
|
|
unsigned int flags; // cf SFXFLAG_* defines
|
|
|
|
struct sfx_s *next;
|
|
+ struct sfx_s *hashnext; // hash chain for S_FindName O(1) lookup
|
|
unsigned int memsize; // total memory used (including sfx_t and fetcher data)
|
|
} sfx_t;
|