mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 09:33:51 +00:00
perf: eliminate ~70 unnecessary sqrt ops per frame, optimize caches and threading
Squared distance optimizations across 30 files: - Convert glm::length() comparisons to glm::dot() (no sqrt) - Use glm::inversesqrt() for check-then-normalize patterns (1 rsqrt vs 2 sqrt) - Defer sqrt to after early-out checks in collision/movement code - Hottest paths: camera_controller (21), weather particles, WMO collision, transport movement, creature interpolation, nameplate culling Container and algorithm improvements: - std::map<string> → std::unordered_map for asset/DBC/MPQ/warden caches - std::mutex → std::shared_mutex for asset_manager and mpq_manager caches - std::sort → std::partial_sort in lighting_manager (top-2 of N volumes) - Double-lookup find()+operator[] → insert_or_assign in game_handler - Add reserve() for per-frame vectors: weather, swim_effects, WMO/M2 collision Threading and synchronization: - Replace 1ms busy-wait polling with condition_variable in character_renderer - Move timestamp capture before mutex in logger - Use memory_order_acquire/release for normal map completion signaling API additions: - DBC getStringView()/getStringViewByOffset() for zero-copy string access - Parse creature display IDs from SMSG_CREATURE_QUERY_SINGLE_RESPONSE
This commit is contained in:
parent
cf0e2aa240
commit
b0466e9029
29 changed files with 328 additions and 196 deletions
|
|
@ -396,14 +396,15 @@ std::vector<uint8_t> AssetManager::readFile(const std::string& path) const {
|
|||
|
||||
std::string normalized = normalizePath(path);
|
||||
|
||||
// Check cache first
|
||||
// Check cache first (shared lock allows concurrent reads)
|
||||
{
|
||||
std::lock_guard<std::mutex> cacheLock(cacheMutex);
|
||||
std::shared_lock<std::shared_mutex> cacheLock(cacheMutex);
|
||||
auto it = fileCache.find(normalized);
|
||||
if (it != fileCache.end()) {
|
||||
it->second.lastAccessTime = ++fileCacheAccessCounter;
|
||||
auto data = it->second.data;
|
||||
cacheLock.unlock();
|
||||
fileCacheHits++;
|
||||
return it->second.data;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -422,7 +423,7 @@ std::vector<uint8_t> AssetManager::readFile(const std::string& path) const {
|
|||
// Add to cache if within budget
|
||||
size_t fileSize = data.size();
|
||||
if (fileSize > 0 && fileSize < fileCacheBudget / 2) {
|
||||
std::lock_guard<std::mutex> cacheLock(cacheMutex);
|
||||
std::lock_guard<std::shared_mutex> cacheLock(cacheMutex);
|
||||
// Evict old entries if needed (LRU)
|
||||
while (fileCacheTotalBytes + fileSize > fileCacheBudget && !fileCache.empty()) {
|
||||
auto lru = fileCache.begin();
|
||||
|
|
@ -456,13 +457,13 @@ std::vector<uint8_t> AssetManager::readFileOptional(const std::string& path) con
|
|||
}
|
||||
|
||||
void AssetManager::clearDBCCache() {
|
||||
std::lock_guard<std::mutex> lock(cacheMutex);
|
||||
std::lock_guard<std::shared_mutex> lock(cacheMutex);
|
||||
dbcCache.clear();
|
||||
LOG_INFO("Cleared DBC cache");
|
||||
}
|
||||
|
||||
void AssetManager::clearCache() {
|
||||
std::lock_guard<std::mutex> lock(cacheMutex);
|
||||
std::lock_guard<std::shared_mutex> lock(cacheMutex);
|
||||
dbcCache.clear();
|
||||
fileCache.clear();
|
||||
fileCacheTotalBytes = 0;
|
||||
|
|
|
|||
|
|
@ -137,26 +137,32 @@ float DBCFile::getFloat(uint32_t recordIndex, uint32_t fieldIndex) const {
|
|||
}
|
||||
|
||||
std::string DBCFile::getString(uint32_t recordIndex, uint32_t fieldIndex) const {
|
||||
return std::string(getStringView(recordIndex, fieldIndex));
|
||||
}
|
||||
|
||||
std::string_view DBCFile::getStringView(uint32_t recordIndex, uint32_t fieldIndex) const {
|
||||
uint32_t offset = getUInt32(recordIndex, fieldIndex);
|
||||
return getStringByOffset(offset);
|
||||
return getStringViewByOffset(offset);
|
||||
}
|
||||
|
||||
std::string DBCFile::getStringByOffset(uint32_t offset) const {
|
||||
return std::string(getStringViewByOffset(offset));
|
||||
}
|
||||
|
||||
std::string_view DBCFile::getStringViewByOffset(uint32_t offset) const {
|
||||
if (!loaded || offset >= stringBlockSize) {
|
||||
return "";
|
||||
return {};
|
||||
}
|
||||
|
||||
// Find null terminator
|
||||
const char* str = reinterpret_cast<const char*>(stringBlock.data() + offset);
|
||||
const char* end = reinterpret_cast<const char*>(stringBlock.data() + stringBlockSize);
|
||||
|
||||
// Find string length (up to null terminator or end of block)
|
||||
size_t length = 0;
|
||||
while (str + length < end && str[length] != '\0') {
|
||||
length++;
|
||||
}
|
||||
|
||||
return std::string(str, length);
|
||||
return std::string_view(str, length);
|
||||
}
|
||||
|
||||
int32_t DBCFile::findRecordById(uint32_t id) const {
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ void MPQManager::shutdown() {
|
|||
archives.clear();
|
||||
archiveNames.clear();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fileArchiveCacheMutex_);
|
||||
std::lock_guard<std::shared_mutex> lock(fileArchiveCacheMutex_);
|
||||
fileArchiveCache_.clear();
|
||||
}
|
||||
{
|
||||
|
|
@ -214,7 +214,7 @@ bool MPQManager::loadArchive(const std::string& path, int priority) {
|
|||
|
||||
// Archive set/priority changed, so cached filename -> archive mappings may be stale.
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fileArchiveCacheMutex_);
|
||||
std::lock_guard<std::shared_mutex> lock(fileArchiveCacheMutex_);
|
||||
fileArchiveCache_.clear();
|
||||
}
|
||||
|
||||
|
|
@ -383,7 +383,7 @@ HANDLE MPQManager::findFileArchive(const std::string& filename) const {
|
|||
#ifdef HAVE_STORMLIB
|
||||
std::string cacheKey = normalizeVirtualFilenameForLookup(filename);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fileArchiveCacheMutex_);
|
||||
std::shared_lock<std::shared_mutex> lock(fileArchiveCacheMutex_);
|
||||
auto it = fileArchiveCache_.find(cacheKey);
|
||||
if (it != fileArchiveCache_.end()) {
|
||||
return it->second;
|
||||
|
|
@ -416,7 +416,7 @@ HANDLE MPQManager::findFileArchive(const std::string& filename) const {
|
|||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(fileArchiveCacheMutex_);
|
||||
std::lock_guard<std::shared_mutex> lock(fileArchiveCacheMutex_);
|
||||
if (fileArchiveCache_.size() >= fileArchiveCacheMaxEntries_) {
|
||||
// Simple safety valve: clear the cache rather than allowing an unbounded growth.
|
||||
LOG_WARNING("MPQ archive lookup cache cleared (size=", fileArchiveCache_.size(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue