mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
Improvements to SimDictionary for when you have a large number of objects in the game. Under light load (i.e. under 5000 objects) this code actually runs slower that the stock simdictionary. When you exceed 5000 objects, the template class actually runs faster and more consistently.
This commit is contained in:
parent
378a933894
commit
a91e5a2590
|
|
@ -23,19 +23,24 @@
|
|||
#include "console/simDictionary.h"
|
||||
#include "console/simBase.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
extern U32 HashPointer(StringTableEntry e);
|
||||
|
||||
SimNameDictionary::SimNameDictionary()
|
||||
{
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
hashTable = NULL;
|
||||
#endif
|
||||
mutex = Mutex::createMutex();
|
||||
}
|
||||
|
||||
SimNameDictionary::~SimNameDictionary()
|
||||
{
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
delete[] hashTable;
|
||||
#endif
|
||||
Mutex::destroyMutex(mutex);
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +55,7 @@ void SimNameDictionary::insert(SimObject* obj)
|
|||
Con::warnf("Warning! You have a duplicate datablock name of %s. This can cause problems. You should rename one of them.", obj->objectName);
|
||||
|
||||
Mutex::lockMutex(mutex);
|
||||
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
if(!hashTable)
|
||||
{
|
||||
hashTable = new SimObject *[DefaultTableSize];
|
||||
|
|
@ -95,12 +100,15 @@ void SimNameDictionary::insert(SimObject* obj)
|
|||
hashTable = newHashTable;
|
||||
hashTableSize = newHashTableSize;
|
||||
}
|
||||
|
||||
#else
|
||||
root[StringTable->insert(obj->objectName)] = obj;
|
||||
#endif
|
||||
Mutex::unlockMutex(mutex);
|
||||
}
|
||||
|
||||
SimObject* SimNameDictionary::find(StringTableEntry name)
|
||||
{
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
// NULL is a valid lookup - it will always return NULL
|
||||
if(!hashTable)
|
||||
return NULL;
|
||||
|
|
@ -121,6 +129,12 @@ SimObject* SimNameDictionary::find(StringTableEntry name)
|
|||
|
||||
Mutex::unlockMutex(mutex);
|
||||
return NULL;
|
||||
#else
|
||||
Mutex::lockMutex(mutex);
|
||||
SimObject* f = root[StringTable->insert(name)];
|
||||
Mutex::unlockMutex(mutex);
|
||||
return f;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SimNameDictionary::remove(SimObject* obj)
|
||||
|
|
@ -129,7 +143,7 @@ void SimNameDictionary::remove(SimObject* obj)
|
|||
return;
|
||||
|
||||
Mutex::lockMutex(mutex);
|
||||
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
SimObject **walk = &hashTable[HashPointer(obj->objectName) % hashTableSize];
|
||||
while(*walk)
|
||||
{
|
||||
|
|
@ -144,7 +158,11 @@ void SimNameDictionary::remove(SimObject* obj)
|
|||
}
|
||||
walk = &((*walk)->nextNameObject);
|
||||
}
|
||||
|
||||
#else
|
||||
const char* name = StringTable->insert(obj->objectName);
|
||||
if (root[name])
|
||||
root.erase(name);
|
||||
#endif
|
||||
Mutex::unlockMutex(mutex);
|
||||
}
|
||||
|
||||
|
|
@ -152,18 +170,21 @@ void SimNameDictionary::remove(SimObject* obj)
|
|||
|
||||
SimManagerNameDictionary::SimManagerNameDictionary()
|
||||
{
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
hashTable = new SimObject *[DefaultTableSize];
|
||||
hashTableSize = DefaultTableSize;
|
||||
hashEntryCount = 0;
|
||||
|
||||
dMemset( hashTable, 0, sizeof( hashTable[ 0 ] ) * hashTableSize );
|
||||
|
||||
#endif
|
||||
mutex = Mutex::createMutex();
|
||||
}
|
||||
|
||||
SimManagerNameDictionary::~SimManagerNameDictionary()
|
||||
{
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
delete[] hashTable;
|
||||
#endif
|
||||
Mutex::destroyMutex(mutex);
|
||||
}
|
||||
|
||||
|
|
@ -173,7 +194,7 @@ void SimManagerNameDictionary::insert(SimObject* obj)
|
|||
return;
|
||||
|
||||
Mutex::lockMutex(mutex);
|
||||
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
S32 idx = HashPointer(obj->objectName) % hashTableSize;
|
||||
obj->nextManagerNameObject = hashTable[idx];
|
||||
hashTable[idx] = obj;
|
||||
|
|
@ -209,7 +230,9 @@ void SimManagerNameDictionary::insert(SimObject* obj)
|
|||
hashTable = newHashTable;
|
||||
hashTableSize = newHashTableSize;
|
||||
}
|
||||
|
||||
#else
|
||||
root[StringTable->insert(obj->objectName)] = obj;
|
||||
#endif
|
||||
Mutex::unlockMutex(mutex);
|
||||
}
|
||||
|
||||
|
|
@ -219,6 +242,7 @@ SimObject* SimManagerNameDictionary::find(StringTableEntry name)
|
|||
|
||||
Mutex::lockMutex(mutex);
|
||||
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
S32 idx = HashPointer(name) % hashTableSize;
|
||||
SimObject *walk = hashTable[idx];
|
||||
while(walk)
|
||||
|
|
@ -230,9 +254,14 @@ SimObject* SimManagerNameDictionary::find(StringTableEntry name)
|
|||
}
|
||||
walk = walk->nextManagerNameObject;
|
||||
}
|
||||
|
||||
Mutex::unlockMutex(mutex);
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
SimObject* f = root[StringTable->insert(name)];
|
||||
Mutex::unlockMutex(mutex);
|
||||
return f;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SimManagerNameDictionary::remove(SimObject* obj)
|
||||
|
|
@ -240,6 +269,7 @@ void SimManagerNameDictionary::remove(SimObject* obj)
|
|||
if(!obj->objectName)
|
||||
return;
|
||||
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
Mutex::lockMutex(mutex);
|
||||
|
||||
SimObject **walk = &hashTable[HashPointer(obj->objectName) % hashTableSize];
|
||||
|
|
@ -256,7 +286,12 @@ void SimManagerNameDictionary::remove(SimObject* obj)
|
|||
}
|
||||
walk = &((*walk)->nextManagerNameObject);
|
||||
}
|
||||
#else
|
||||
|
||||
const char* name = StringTable->insert(obj->objectName);
|
||||
if (root[name])
|
||||
root.erase(name);
|
||||
#endif
|
||||
Mutex::unlockMutex(mutex);
|
||||
}
|
||||
|
||||
|
|
@ -265,7 +300,9 @@ void SimManagerNameDictionary::remove(SimObject* obj)
|
|||
|
||||
SimIdDictionary::SimIdDictionary()
|
||||
{
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
dMemset( table, 0, sizeof( table[ 0 ] ) * DefaultTableSize );
|
||||
#endif
|
||||
mutex = Mutex::createMutex();
|
||||
}
|
||||
|
||||
|
|
@ -274,22 +311,26 @@ SimIdDictionary::~SimIdDictionary()
|
|||
Mutex::destroyMutex(mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SimIdDictionary::insert(SimObject* obj)
|
||||
{
|
||||
Mutex::lockMutex(mutex);
|
||||
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
S32 idx = obj->getId() & TableBitMask;
|
||||
obj->nextIdObject = table[idx];
|
||||
AssertFatal( obj->nextIdObject != obj, "SimIdDictionary::insert - Creating Infinite Loop linking to self!" );
|
||||
table[idx] = obj;
|
||||
|
||||
#else
|
||||
root[obj->getId()] = obj;
|
||||
#endif
|
||||
Mutex::unlockMutex(mutex);
|
||||
}
|
||||
|
||||
SimObject* SimIdDictionary::find(S32 id)
|
||||
{
|
||||
Mutex::lockMutex(mutex);
|
||||
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
S32 idx = id & TableBitMask;
|
||||
SimObject *walk = table[idx];
|
||||
while(walk)
|
||||
|
|
@ -301,22 +342,28 @@ SimObject* SimIdDictionary::find(S32 id)
|
|||
}
|
||||
walk = walk->nextIdObject;
|
||||
}
|
||||
|
||||
Mutex::unlockMutex(mutex);
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
SimObject* f = root[id];
|
||||
Mutex::unlockMutex(mutex);
|
||||
return f;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SimIdDictionary::remove(SimObject* obj)
|
||||
{
|
||||
Mutex::lockMutex(mutex);
|
||||
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
SimObject **walk = &table[obj->getId() & TableBitMask];
|
||||
while(*walk && *walk != obj)
|
||||
walk = &((*walk)->nextIdObject);
|
||||
if(*walk)
|
||||
*walk = obj->nextIdObject;
|
||||
|
||||
#else
|
||||
root.erase(obj->getId());
|
||||
#endif
|
||||
Mutex::unlockMutex(mutex);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,8 +33,37 @@
|
|||
#include "platform/threads/mutex.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "TorqueConfig.h"
|
||||
|
||||
|
||||
class SimObject;
|
||||
|
||||
#include "core/strings/stringFunctions.h"
|
||||
|
||||
struct my_hash {
|
||||
inline size_t operator()(const char* val) const
|
||||
{
|
||||
return (long)val;
|
||||
}
|
||||
};
|
||||
|
||||
struct eqstr {
|
||||
inline bool operator()(const char *s1, const char *s2) const {
|
||||
return dStrcmp(s1, s2) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef USE_CLASSIC_SIMDICTIONARY
|
||||
typedef std::unordered_map<const char * , SimObject*, my_hash, eqstr> StringDictDef;
|
||||
typedef std::unordered_map<U32 ,SimObject*> U32DictDef;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// Map of names to SimObjects
|
||||
///
|
||||
|
|
@ -42,6 +71,7 @@ class SimObject;
|
|||
/// for fast removal of an object given object*
|
||||
class SimNameDictionary
|
||||
{
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
enum
|
||||
{
|
||||
DefaultTableSize = 29
|
||||
|
|
@ -50,9 +80,13 @@ class SimNameDictionary
|
|||
SimObject **hashTable; // hash the pointers of the names...
|
||||
S32 hashTableSize;
|
||||
S32 hashEntryCount;
|
||||
|
||||
#else
|
||||
StringDictDef root;
|
||||
#endif
|
||||
void *mutex;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
void insert(SimObject* obj);
|
||||
void remove(SimObject* obj);
|
||||
|
|
@ -64,6 +98,7 @@ public:
|
|||
|
||||
class SimManagerNameDictionary
|
||||
{
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
enum
|
||||
{
|
||||
DefaultTableSize = 29
|
||||
|
|
@ -73,8 +108,14 @@ class SimManagerNameDictionary
|
|||
S32 hashTableSize;
|
||||
S32 hashEntryCount;
|
||||
|
||||
void *mutex;
|
||||
|
||||
#else
|
||||
|
||||
|
||||
StringDictDef root;
|
||||
|
||||
#endif
|
||||
void *mutex;
|
||||
public:
|
||||
void insert(SimObject* obj);
|
||||
void remove(SimObject* obj);
|
||||
|
|
@ -91,13 +132,16 @@ public:
|
|||
/// for fast removal of an object given object*
|
||||
class SimIdDictionary
|
||||
{
|
||||
#ifdef USE_CLASSIC_SIMDICTIONARY
|
||||
enum
|
||||
{
|
||||
DefaultTableSize = 4096,
|
||||
TableBitMask = 4095
|
||||
};
|
||||
SimObject *table[DefaultTableSize];
|
||||
|
||||
#else
|
||||
U32DictDef root;
|
||||
#endif
|
||||
void *mutex;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@
|
|||
//general, the information here is global for your entire codebase, applying
|
||||
//not only to your game proper, but also to all of your tools.
|
||||
|
||||
//If you plan to have less than 5000 objects use the Classic SimDictionary, if you plan to have more than
|
||||
//5000 objects use the new SimDictionary.
|
||||
|
||||
#define USE_CLASSIC_SIMDICTIONARY
|
||||
/// What's the name of your application? Used in a variety of places.
|
||||
#define TORQUE_APP_NAME "Empty"
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@
|
|||
//general, the information here is global for your entire codebase, applying
|
||||
//not only to your game proper, but also to all of your tools.
|
||||
|
||||
//If you plan to have less than 5000 objects use the Classic SimDictionary, if you plan to have more than
|
||||
//5000 objects use the new SimDictionary.
|
||||
|
||||
#define USE_CLASSIC_SIMDICTIONARY
|
||||
/// What's the name of your application? Used in a variety of places.
|
||||
#define TORQUE_APP_NAME "Full"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue