Speed up CV_Findvar & CV_FindNetVar with hashtable

This commit is contained in:
Alug 2026-04-27 17:32:17 -04:00 committed by NepDisk
parent d2c9a3e1b6
commit 9d2b6eda55
5 changed files with 79 additions and 7 deletions

View file

@ -1443,6 +1443,39 @@ void VS_Print(vsbuf_t *buf, const char *data)
//
// =========================================================================
#define NAME cvar_map_t
#define KEY_TY const char *
#define VAL_TY consvar_t *
#define HASH_FN vt_hash_string
#define CMPR_FN vt_cmpr_string
#include "verstable.h"
#define NAME netvar_map_t
#define KEY_TY UINT16
#define VAL_TY consvar_t *
#define HASH_FN vt_hash_integer
#define CMPR_FN vt_cmpr_integer
#include "verstable.h"
static cvar_map_t cvar_map;
static netvar_map_t netvar_map;
CONSTRUCTOR static void CV_InitMap(void)
{
// ensure the map is initialized
cvar_map_t_init(&cvar_map);
cvar_map_t_reserve(&cvar_map, 512);
netvar_map_t_init(&netvar_map);
netvar_map_t_reserve(&netvar_map, 256);
}
DESTRUCTOR static void CV_DestroyMap(void)
{
cvar_map_t_cleanup(&cvar_map);
netvar_map_t_cleanup(&netvar_map);
}
static const char *cv_null_string = "";
/** Searches if a variable has been registered.
@ -1453,11 +1486,17 @@ static const char *cv_null_string = "";
*/
consvar_t *CV_FindVar(const char *name)
{
consvar_t *cvar;
cvar_map_t_itr it = cvar_map_t_get(&cvar_map, name);
if (!cvar_map_t_is_end(it))
return it.data->val;
// fallback linear search
/*
consvar_t *cvar;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
if (fasticmp(name, cvar->name))
return cvar;
*/
return NULL;
}
@ -1484,6 +1523,10 @@ static inline UINT16 CV_ComputeLegacyNetid(const char *s)
*/
static consvar_t *CV_FindNetVar(UINT16 netid)
{
netvar_map_t_itr it = netvar_map_t_get(&netvar_map, netid);
if (!netvar_map_t_is_end(it))
return it.data->val;
/*
consvar_t *cvar;
if (netid > consvar_number_of_netids)
@ -1492,6 +1535,7 @@ static consvar_t *CV_FindNetVar(UINT16 netid)
for (cvar = consvar_vars; cvar; cvar = cvar->next)
if (cvar->netid == netid)
return cvar;
*/
if (netid == 44542) // ouch this hack
return &cv_karteliminatelast;
@ -1585,6 +1629,11 @@ void CV_RegisterVar(consvar_t *variable)
// the SetValue will set this bit
variable->flags &= ~CV_MODIFIED;
cvar_map_t_insert(&cvar_map, variable->name, variable);
if (variable->flags & CV_NETVAR)
netvar_map_t_insert(&netvar_map, variable->netid, variable);
}
/** Finds the string value of a console variable.
@ -1971,6 +2020,25 @@ static void CV_LoadVars(UINT8 **p,
// prevent "invalid command received"
serverloading = true;
// we can use our netvar map instead of going through all cvars each time
netvar_map_t_itr it;
for (it = netvar_map_t_first(&netvar_map);
!netvar_map_t_is_end(it);
it = netvar_map_t_next(it))
{
cvar = it.data->val;
if (store && cvar->revert.v.string == NULL)
{
cvar->revert.v.const_munge = cvar->string;
cvar->revert.allocated = ( cvar->zstring != NULL );
cvar->zstring = NULL; // don't free this
}
Setvalue(cvar, cvar->defaultvalue, true);
}
/*
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (cvar->flags & CV_NETVAR)
@ -1979,12 +2047,12 @@ static void CV_LoadVars(UINT8 **p,
{
cvar->revert.v.const_munge = cvar->string;
cvar->revert.allocated = ( cvar->zstring != NULL );
cvar->zstring = NULL;/* don't free this */
cvar->zstring = NULL; // don't free this
}
Setvalue(cvar, cvar->defaultvalue, true);
}
}
}*/
if (got == NULL)
G_LoadDemoCvars((void **)p, Setvalue);

View file

@ -440,6 +440,13 @@ INT32 I_GetKey(void);
// NOTE: you WILL have nasal troubles if the variable is not initialized
#define CLEANUP(f) __attribute__((__cleanup__(f)))
// the GNU constructor and destructor attributes
// The constructor attribute causes the function to be called automatically before execution enters main ().
// Similarly, the destructor attribute causes the function to be called automatically after main () has completed or exit () has been called.
// Functions with these attributes are useful for initializing data that will be used implicitly during the execution of the program.
#define CONSTRUCTOR __attribute__((constructor, used))
#define DESTRUCTOR __attribute__((destructor, used))
// An assert-type mechanism.
// NOTE: USE SRB2_ASSERT FOR C++ CODE INSTEAD
#ifdef PARANOIA

View file

@ -1364,7 +1364,6 @@ static void I_Fork(void)
INT32 I_StartupSystem(void)
{
int SDLlinked = SDL_GetVersion();
W_Startup();
I_StartupConsole();
#ifdef NEWSIGNALHANDLER
// This is useful when debugging. It lets GDB attach to

View file

@ -155,8 +155,7 @@ void W_Shutdown(void)
}
// the lumpnum cache needs to be initialized before use
// call this as early as possible!
void W_Startup(void)
CONSTRUCTOR static void W_Startup(void)
{
lumpnum_map_init(&lumpnumcache);
lumpnum_map_reserve(&lumpnumcache, LUMPNUMCACHESIZE);

View file

@ -152,7 +152,6 @@ extern wadfile_t *wadfiles[MAX_WADFILES];
// =========================================================================
void W_Startup(void);
void W_Shutdown(void);
// Opens a WAD file. Returns the FILE * handle for the file, or NULL if not found or could not be opened