Added a cHeiGenCache object for caching generated heightmaps. World generation is now about twice as fast as before Rev 535 :)
git-svn-id: http://mc-server.googlecode.com/svn/trunk@538 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
5e831256ef
commit
39a59d6806
@ -25,6 +25,96 @@ void cHeiGenFlat::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cHeiGenCache:
|
||||||
|
|
||||||
|
cHeiGenCache::cHeiGenCache(cTerrainHeightGen * a_HeiGenToCache, int a_CacheSize) :
|
||||||
|
m_HeiGenToCache(a_HeiGenToCache),
|
||||||
|
m_CacheSize(a_CacheSize),
|
||||||
|
m_CacheOrder(new int[a_CacheSize]),
|
||||||
|
m_CacheData(new sCacheData[a_CacheSize]),
|
||||||
|
m_NumHits(0),
|
||||||
|
m_NumMisses(0),
|
||||||
|
m_TotalChain(0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_CacheSize; i++)
|
||||||
|
{
|
||||||
|
m_CacheOrder[i] = i;
|
||||||
|
m_CacheData[i].m_ChunkX = 0x7fffffff;
|
||||||
|
m_CacheData[i].m_ChunkZ = 0x7fffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cHeiGenCache::~cHeiGenCache()
|
||||||
|
{
|
||||||
|
delete m_CacheData;
|
||||||
|
delete m_CacheOrder;
|
||||||
|
delete m_HeiGenToCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cHeiGenCache::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap)
|
||||||
|
{
|
||||||
|
if (((m_NumHits + m_NumMisses) % 1024) == 10)
|
||||||
|
{
|
||||||
|
LOGD("HeiGenCache: %d hits, %d misses, saved %.2f %%", m_NumHits, m_NumMisses, 100.0 * m_NumHits / (m_NumHits + m_NumMisses));
|
||||||
|
LOGD("HeiGenCache: Avg cache chain length: %.2f", (float)m_TotalChain / m_NumHits);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < m_CacheSize; i++)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(m_CacheData[m_CacheOrder[i]].m_ChunkX != a_ChunkX) ||
|
||||||
|
(m_CacheData[m_CacheOrder[i]].m_ChunkZ != a_ChunkZ)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Found it in the cache
|
||||||
|
int Idx = m_CacheOrder[i];
|
||||||
|
|
||||||
|
// Move to front:
|
||||||
|
for (int j = i; j > 0; j--)
|
||||||
|
{
|
||||||
|
m_CacheOrder[j] = m_CacheOrder[j - 1];
|
||||||
|
}
|
||||||
|
m_CacheOrder[0] = Idx;
|
||||||
|
|
||||||
|
// Use the cached data:
|
||||||
|
memcpy(a_HeightMap, m_CacheData[Idx].m_HeightMap, sizeof(a_HeightMap));
|
||||||
|
|
||||||
|
m_NumHits++;
|
||||||
|
m_TotalChain += i;
|
||||||
|
return;
|
||||||
|
} // for i - cache
|
||||||
|
|
||||||
|
// Not in the cache:
|
||||||
|
m_NumMisses++;
|
||||||
|
m_HeiGenToCache->GenHeightMap(a_ChunkX, a_ChunkZ, a_HeightMap);
|
||||||
|
|
||||||
|
// Insert it as the first item in the MRU order:
|
||||||
|
int Idx = m_CacheOrder[m_CacheSize - 1];
|
||||||
|
for (int i = m_CacheSize - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
m_CacheOrder[i] = m_CacheOrder[i - 1];
|
||||||
|
} // for i - m_CacheOrder[]
|
||||||
|
m_CacheOrder[0] = Idx;
|
||||||
|
memcpy(m_CacheData[Idx].m_HeightMap, a_HeightMap, sizeof(a_HeightMap));
|
||||||
|
m_CacheData[Idx].m_ChunkX = a_ChunkX;
|
||||||
|
m_CacheData[Idx].m_ChunkZ = a_ChunkZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cHeiGenClassic:
|
// cHeiGenClassic:
|
||||||
|
|
||||||
|
@ -39,6 +39,42 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// A simple cache that stores N most recently generated chunks' heightmaps; N being settable upon creation
|
||||||
|
class cHeiGenCache :
|
||||||
|
public cTerrainHeightGen
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cHeiGenCache(cTerrainHeightGen * a_HeiGenToCache, int a_CacheSize); // Takes ownership of a_HeiGenToCache
|
||||||
|
~cHeiGenCache();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
cTerrainHeightGen * m_HeiGenToCache;
|
||||||
|
|
||||||
|
struct sCacheData
|
||||||
|
{
|
||||||
|
int m_ChunkX;
|
||||||
|
int m_ChunkZ;
|
||||||
|
cChunkDef::HeightMap m_HeightMap;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
// To avoid moving large amounts of data for the MRU behavior, we MRU-ize indices to an array of the actual data
|
||||||
|
int m_CacheSize;
|
||||||
|
int * m_CacheOrder; // MRU-ized order, indices into m_CacheData array
|
||||||
|
sCacheData * m_CacheData; // m_CacheData[m_CacheOrder[0]] is the most recently used
|
||||||
|
|
||||||
|
// Cache statistics
|
||||||
|
int m_NumHits;
|
||||||
|
int m_NumMisses;
|
||||||
|
int m_TotalChain; // Number of cache items walked to get to a hit (only added for hits)
|
||||||
|
|
||||||
|
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cHeiGenClassic :
|
class cHeiGenClassic :
|
||||||
public cTerrainHeightGen
|
public cTerrainHeightGen
|
||||||
{
|
{
|
||||||
|
@ -177,10 +177,12 @@ void cChunkGenerator::InitHeightGen(cIniFile & a_IniFile)
|
|||||||
HeightGenName = "classic";
|
HeightGenName = "classic";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CacheOffByDefault = false;
|
||||||
if (NoCaseCompare(HeightGenName, "flat") == 0)
|
if (NoCaseCompare(HeightGenName, "flat") == 0)
|
||||||
{
|
{
|
||||||
int Height = a_IniFile.GetValueI("Generator", "FlatHeight", 5);
|
int Height = a_IniFile.GetValueI("Generator", "FlatHeight", 5);
|
||||||
m_HeightGen = new cHeiGenFlat(Height);
|
m_HeightGen = new cHeiGenFlat(Height);
|
||||||
|
CacheOffByDefault = true; // We're generating faster than a cache would retrieve data
|
||||||
}
|
}
|
||||||
else if (NoCaseCompare(HeightGenName, "classic") == 0)
|
else if (NoCaseCompare(HeightGenName, "classic") == 0)
|
||||||
{
|
{
|
||||||
@ -201,6 +203,21 @@ void cChunkGenerator::InitHeightGen(cIniFile & a_IniFile)
|
|||||||
}
|
}
|
||||||
m_HeightGen = new cHeiGenBiomal(m_Seed, *m_BiomeGen);
|
m_HeightGen = new cHeiGenBiomal(m_Seed, *m_BiomeGen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a cache, if requested:
|
||||||
|
int CacheSize = a_IniFile.GetValueI("Generator", "HeightGenCacheSize", CacheOffByDefault ? 0 : 64);
|
||||||
|
if (CacheSize > 0)
|
||||||
|
{
|
||||||
|
if (CacheSize < 4)
|
||||||
|
{
|
||||||
|
LOGWARNING("Heightgen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d",
|
||||||
|
CacheSize, 4
|
||||||
|
);
|
||||||
|
CacheSize = 4;
|
||||||
|
}
|
||||||
|
LOGINFO("Using a cache for Heightgen of size %d.", CacheSize);
|
||||||
|
m_HeightGen = new cHeiGenCache(m_HeightGen, CacheSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user