Merge pull request #1020 from eightyeight/simdictionary-improvement

SimDictionary improvement
This commit is contained in:
Daniel Buckmaster 2014-12-24 09:54:54 +11:00
commit c85ac03c16
4 changed files with 125 additions and 19 deletions

View file

@ -29,19 +29,23 @@ extern U32 HashPointer(StringTableEntry e);
SimNameDictionary::SimNameDictionary() SimNameDictionary::SimNameDictionary()
{ {
#ifndef USE_NEW_SIMDICTIONARY
hashTable = NULL; hashTable = NULL;
#endif
mutex = Mutex::createMutex(); mutex = Mutex::createMutex();
} }
SimNameDictionary::~SimNameDictionary() SimNameDictionary::~SimNameDictionary()
{ {
#ifndef USE_NEW_SIMDICTIONARY
delete[] hashTable; delete[] hashTable;
#endif
Mutex::destroyMutex(mutex); Mutex::destroyMutex(mutex);
} }
void SimNameDictionary::insert(SimObject* obj) void SimNameDictionary::insert(SimObject* obj)
{ {
if(!obj->objectName) if(!obj || !obj->objectName)
return; return;
SimObject* checkForDup = find(obj->objectName); SimObject* checkForDup = find(obj->objectName);
@ -50,7 +54,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); 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); Mutex::lockMutex(mutex);
#ifndef USE_NEW_SIMDICTIONARY
if(!hashTable) if(!hashTable)
{ {
hashTable = new SimObject *[DefaultTableSize]; hashTable = new SimObject *[DefaultTableSize];
@ -95,12 +99,15 @@ void SimNameDictionary::insert(SimObject* obj)
hashTable = newHashTable; hashTable = newHashTable;
hashTableSize = newHashTableSize; hashTableSize = newHashTableSize;
} }
#else
root[obj->objectName] = obj;
#endif
Mutex::unlockMutex(mutex); Mutex::unlockMutex(mutex);
} }
SimObject* SimNameDictionary::find(StringTableEntry name) SimObject* SimNameDictionary::find(StringTableEntry name)
{ {
#ifndef USE_NEW_SIMDICTIONARY
// NULL is a valid lookup - it will always return NULL // NULL is a valid lookup - it will always return NULL
if(!hashTable) if(!hashTable)
return NULL; return NULL;
@ -121,15 +128,22 @@ SimObject* SimNameDictionary::find(StringTableEntry name)
Mutex::unlockMutex(mutex); Mutex::unlockMutex(mutex);
return NULL; return NULL;
#else
Mutex::lockMutex(mutex);
StringDictDef::iterator it = root.find(name);
SimObject* f = (it == root.end() ? NULL : it->second);
Mutex::unlockMutex(mutex);
return f;
#endif
} }
void SimNameDictionary::remove(SimObject* obj) void SimNameDictionary::remove(SimObject* obj)
{ {
if(!obj->objectName) if(!obj || !obj->objectName)
return; return;
Mutex::lockMutex(mutex); Mutex::lockMutex(mutex);
#ifndef USE_NEW_SIMDICTIONARY
SimObject **walk = &hashTable[HashPointer(obj->objectName) % hashTableSize]; SimObject **walk = &hashTable[HashPointer(obj->objectName) % hashTableSize];
while(*walk) while(*walk)
{ {
@ -144,7 +158,11 @@ void SimNameDictionary::remove(SimObject* obj)
} }
walk = &((*walk)->nextNameObject); walk = &((*walk)->nextNameObject);
} }
#else
const char* name = obj->objectName;
if (root.find(name) != root.end())
root.erase(name);
#endif
Mutex::unlockMutex(mutex); Mutex::unlockMutex(mutex);
} }
@ -152,28 +170,31 @@ void SimNameDictionary::remove(SimObject* obj)
SimManagerNameDictionary::SimManagerNameDictionary() SimManagerNameDictionary::SimManagerNameDictionary()
{ {
#ifndef USE_NEW_SIMDICTIONARY
hashTable = new SimObject *[DefaultTableSize]; hashTable = new SimObject *[DefaultTableSize];
hashTableSize = DefaultTableSize; hashTableSize = DefaultTableSize;
hashEntryCount = 0; hashEntryCount = 0;
dMemset( hashTable, 0, sizeof( hashTable[ 0 ] ) * hashTableSize ); dMemset( hashTable, 0, sizeof( hashTable[ 0 ] ) * hashTableSize );
#endif
mutex = Mutex::createMutex(); mutex = Mutex::createMutex();
} }
SimManagerNameDictionary::~SimManagerNameDictionary() SimManagerNameDictionary::~SimManagerNameDictionary()
{ {
#ifndef USE_NEW_SIMDICTIONARY
delete[] hashTable; delete[] hashTable;
#endif
Mutex::destroyMutex(mutex); Mutex::destroyMutex(mutex);
} }
void SimManagerNameDictionary::insert(SimObject* obj) void SimManagerNameDictionary::insert(SimObject* obj)
{ {
if(!obj->objectName) if(!obj || !obj->objectName)
return; return;
Mutex::lockMutex(mutex); Mutex::lockMutex(mutex);
#ifndef USE_NEW_SIMDICTIONARY
S32 idx = HashPointer(obj->objectName) % hashTableSize; S32 idx = HashPointer(obj->objectName) % hashTableSize;
obj->nextManagerNameObject = hashTable[idx]; obj->nextManagerNameObject = hashTable[idx];
hashTable[idx] = obj; hashTable[idx] = obj;
@ -209,7 +230,9 @@ void SimManagerNameDictionary::insert(SimObject* obj)
hashTable = newHashTable; hashTable = newHashTable;
hashTableSize = newHashTableSize; hashTableSize = newHashTableSize;
} }
#else
root[obj->objectName] = obj;
#endif
Mutex::unlockMutex(mutex); Mutex::unlockMutex(mutex);
} }
@ -219,6 +242,7 @@ SimObject* SimManagerNameDictionary::find(StringTableEntry name)
Mutex::lockMutex(mutex); Mutex::lockMutex(mutex);
#ifndef USE_NEW_SIMDICTIONARY
S32 idx = HashPointer(name) % hashTableSize; S32 idx = HashPointer(name) % hashTableSize;
SimObject *walk = hashTable[idx]; SimObject *walk = hashTable[idx];
while(walk) while(walk)
@ -230,16 +254,23 @@ SimObject* SimManagerNameDictionary::find(StringTableEntry name)
} }
walk = walk->nextManagerNameObject; walk = walk->nextManagerNameObject;
} }
Mutex::unlockMutex(mutex); Mutex::unlockMutex(mutex);
return NULL; return NULL;
#else
StringDictDef::iterator it = root.find(name);
SimObject* f = (it == root.end() ? NULL : it->second);
Mutex::unlockMutex(mutex);
return f;
#endif
} }
void SimManagerNameDictionary::remove(SimObject* obj) void SimManagerNameDictionary::remove(SimObject* obj)
{ {
if(!obj->objectName) if(!obj || !obj->objectName)
return; return;
#ifndef USE_NEW_SIMDICTIONARY
Mutex::lockMutex(mutex); Mutex::lockMutex(mutex);
SimObject **walk = &hashTable[HashPointer(obj->objectName) % hashTableSize]; SimObject **walk = &hashTable[HashPointer(obj->objectName) % hashTableSize];
@ -256,7 +287,11 @@ void SimManagerNameDictionary::remove(SimObject* obj)
} }
walk = &((*walk)->nextManagerNameObject); walk = &((*walk)->nextManagerNameObject);
} }
#else
StringTableEntry name = obj->objectName;
if (root.find(name) != root.end())
root.erase(name);
#endif
Mutex::unlockMutex(mutex); Mutex::unlockMutex(mutex);
} }
@ -265,7 +300,9 @@ void SimManagerNameDictionary::remove(SimObject* obj)
SimIdDictionary::SimIdDictionary() SimIdDictionary::SimIdDictionary()
{ {
#ifndef USE_NEW_SIMDICTIONARY
dMemset( table, 0, sizeof( table[ 0 ] ) * DefaultTableSize ); dMemset( table, 0, sizeof( table[ 0 ] ) * DefaultTableSize );
#endif
mutex = Mutex::createMutex(); mutex = Mutex::createMutex();
} }
@ -274,22 +311,29 @@ SimIdDictionary::~SimIdDictionary()
Mutex::destroyMutex(mutex); Mutex::destroyMutex(mutex);
} }
void SimIdDictionary::insert(SimObject* obj) void SimIdDictionary::insert(SimObject* obj)
{ {
Mutex::lockMutex(mutex); if (!obj)
return;
Mutex::lockMutex(mutex);
#ifndef USE_NEW_SIMDICTIONARY
S32 idx = obj->getId() & TableBitMask; S32 idx = obj->getId() & TableBitMask;
obj->nextIdObject = table[idx]; obj->nextIdObject = table[idx];
AssertFatal( obj->nextIdObject != obj, "SimIdDictionary::insert - Creating Infinite Loop linking to self!" ); AssertFatal( obj->nextIdObject != obj, "SimIdDictionary::insert - Creating Infinite Loop linking to self!" );
table[idx] = obj; table[idx] = obj;
#else
root[obj->getId()] = obj;
#endif
Mutex::unlockMutex(mutex); Mutex::unlockMutex(mutex);
} }
SimObject* SimIdDictionary::find(S32 id) SimObject* SimIdDictionary::find(S32 id)
{ {
Mutex::lockMutex(mutex); Mutex::lockMutex(mutex);
#ifndef USE_NEW_SIMDICTIONARY
S32 idx = id & TableBitMask; S32 idx = id & TableBitMask;
SimObject *walk = table[idx]; SimObject *walk = table[idx];
while(walk) while(walk)
@ -301,22 +345,32 @@ SimObject* SimIdDictionary::find(S32 id)
} }
walk = walk->nextIdObject; walk = walk->nextIdObject;
} }
Mutex::unlockMutex(mutex); Mutex::unlockMutex(mutex);
return NULL; return NULL;
#else
SimObjectIdDictDef::iterator it = root.find(id);
SimObject* f = (it == root.end() ? NULL : it->second);
Mutex::unlockMutex(mutex);
return f;
#endif
} }
void SimIdDictionary::remove(SimObject* obj) void SimIdDictionary::remove(SimObject* obj)
{ {
Mutex::lockMutex(mutex); if (!obj)
return;
Mutex::lockMutex(mutex);
#ifndef USE_NEW_SIMDICTIONARY
SimObject **walk = &table[obj->getId() & TableBitMask]; SimObject **walk = &table[obj->getId() & TableBitMask];
while(*walk && *walk != obj) while(*walk && *walk != obj)
walk = &((*walk)->nextIdObject); walk = &((*walk)->nextIdObject);
if(*walk) if(*walk)
*walk = obj->nextIdObject; *walk = obj->nextIdObject;
#else
root.erase(obj->getId());
#endif
Mutex::unlockMutex(mutex); Mutex::unlockMutex(mutex);
} }

View file

@ -33,8 +33,38 @@
#include "platform/threads/mutex.h" #include "platform/threads/mutex.h"
#endif #endif
#include "torqueConfig.h"
class SimObject; class SimObject;
#ifdef USE_NEW_SIMDICTIONARY
#include <string>
#include <unordered_map>
#ifndef _SIM_H_
#include "console/sim.h"
#endif
struct StringTableEntryHash
{
inline size_t operator()(StringTableEntry val) const
{
return (size_t)val;
}
};
struct StringTableEntryEq
{
inline bool operator()(StringTableEntry s1, StringTableEntry s2) const
{
return s1 == s2;
}
};
typedef std::unordered_map<StringTableEntry, SimObject*, StringTableEntryHash, StringTableEntryEq> StringDictDef;
typedef std::unordered_map<SimObjectId, SimObject*> SimObjectIdDictDef;
#endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/// Map of names to SimObjects /// Map of names to SimObjects
/// ///
@ -42,6 +72,7 @@ class SimObject;
/// for fast removal of an object given object* /// for fast removal of an object given object*
class SimNameDictionary class SimNameDictionary
{ {
#ifndef USE_NEW_SIMDICTIONARY
enum enum
{ {
DefaultTableSize = 29 DefaultTableSize = 29
@ -50,6 +81,9 @@ class SimNameDictionary
SimObject **hashTable; // hash the pointers of the names... SimObject **hashTable; // hash the pointers of the names...
S32 hashTableSize; S32 hashTableSize;
S32 hashEntryCount; S32 hashEntryCount;
#else
StringDictDef root;
#endif
void *mutex; void *mutex;
@ -64,6 +98,7 @@ public:
class SimManagerNameDictionary class SimManagerNameDictionary
{ {
#ifndef USE_NEW_SIMDICTIONARY
enum enum
{ {
DefaultTableSize = 29 DefaultTableSize = 29
@ -72,6 +107,9 @@ class SimManagerNameDictionary
SimObject **hashTable; // hash the pointers of the names... SimObject **hashTable; // hash the pointers of the names...
S32 hashTableSize; S32 hashTableSize;
S32 hashEntryCount; S32 hashEntryCount;
#else
StringDictDef root;
#endif
void *mutex; void *mutex;
@ -91,12 +129,16 @@ public:
/// for fast removal of an object given object* /// for fast removal of an object given object*
class SimIdDictionary class SimIdDictionary
{ {
#ifndef USE_NEW_SIMDICTIONARY
enum enum
{ {
DefaultTableSize = 4096, DefaultTableSize = 4096,
TableBitMask = 4095 TableBitMask = 4095
}; };
SimObject *table[DefaultTableSize]; SimObject *table[DefaultTableSize];
#else
SimObjectIdDictDef root;
#endif
void *mutex; void *mutex;

View file

@ -52,6 +52,11 @@
#define TORQUE_DISABLE_MEMORY_MANAGER #define TORQUE_DISABLE_MEMORY_MANAGER
#endif #endif
/// The improved SimDictionary uses C++11 and is designed for games where
/// there are over 10000 simobjects active normally. To enable the new
/// SimDictionary just uncomment the line below.
//#define USE_NEW_SIMDICTIONARY
/// Define me if you want to disable the virtual mount system. /// Define me if you want to disable the virtual mount system.
//#define TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM //#define TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM

View file

@ -52,6 +52,11 @@
#define TORQUE_DISABLE_MEMORY_MANAGER #define TORQUE_DISABLE_MEMORY_MANAGER
#endif #endif
/// The improved SimDictionary uses C++11 and is designed for games where
/// there are over 10000 simobjects active normally. To enable the new
/// SimDictionary just uncomment the line below.
//#define USE_NEW_SIMDICTIONARY
/// Define me if you want to disable the virtual mount system. /// Define me if you want to disable the virtual mount system.
//#define TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM //#define TORQUE_DISABLE_VIRTUAL_MOUNT_SYSTEM