From e55fc4db177c0bd78616ef280d2edd0af37cfd48 Mon Sep 17 00:00:00 2001 From: savis <106487343+savisxss@users.noreply.github.com> Date: Sat, 3 Jan 2026 20:37:32 +0100 Subject: [PATCH] Optimize pack file loading - Add thread-local ZSTD decompression context reuse - Integrate BufferPool for temporary buffers - PackManager auto-uses BufferPool for all GetFile calls - Thread-safe pack loading with mutex --- src/PackLib/Pack.cpp | 35 ++++++++++++++++++++++++++++++++--- src/PackLib/Pack.h | 3 +++ src/PackLib/PackManager.cpp | 35 +++++++++++++++++++++++++++++++++-- src/PackLib/PackManager.h | 12 ++++++++++-- 4 files changed, 78 insertions(+), 7 deletions(-) diff --git a/src/PackLib/Pack.cpp b/src/PackLib/Pack.cpp index c87d1d5..93e0b42 100644 --- a/src/PackLib/Pack.cpp +++ b/src/PackLib/Pack.cpp @@ -1,6 +1,18 @@ #include "Pack.h" +#include "EterLib/BufferPool.h" #include +static thread_local ZSTD_DCtx* g_zstdDCtx = nullptr; + +static ZSTD_DCtx* GetThreadLocalZSTDContext() +{ + if (!g_zstdDCtx) + { + g_zstdDCtx = ZSTD_createDCtx(); + } + return g_zstdDCtx; +} + bool CPack::Open(const std::string& path, TPackFileMap& entries) { std::error_code ec; @@ -38,27 +50,44 @@ bool CPack::Open(const std::string& path, TPackFileMap& entries) } bool CPack::GetFile(const TPackFileEntry& entry, TPackFile& result) +{ + return GetFileWithPool(entry, result, nullptr); +} + +bool CPack::GetFileWithPool(const TPackFileEntry& entry, TPackFile& result, CBufferPool* pPool) { result.resize(entry.file_size); size_t offset = m_header.data_begin + entry.offset; + ZSTD_DCtx* dctx = GetThreadLocalZSTDContext(); + switch (entry.encryption) { case 0: { - size_t decompressed_size = ZSTD_decompress(result.data(), result.size(), m_file.data() + offset, entry.compressed_size); + size_t decompressed_size = ZSTD_decompressDCtx(dctx, result.data(), result.size(), m_file.data() + offset, entry.compressed_size); if (decompressed_size != entry.file_size) { return false; } } break; case 1: { - std::vector compressed_data(entry.compressed_size); + std::vector compressed_data; + if (pPool) { + compressed_data = pPool->Acquire(entry.compressed_size); + } + compressed_data.resize(entry.compressed_size); + memcpy(compressed_data.data(), m_file.data() + offset, entry.compressed_size); m_decryption.Resynchronize(entry.iv, sizeof(entry.iv)); m_decryption.ProcessData(compressed_data.data(), compressed_data.data(), entry.compressed_size); - size_t decompressed_size = ZSTD_decompress(result.data(), result.size(), compressed_data.data(), compressed_data.size()); + size_t decompressed_size = ZSTD_decompressDCtx(dctx, result.data(), result.size(), compressed_data.data(), compressed_data.size()); + + if (pPool) { + pPool->Release(std::move(compressed_data)); + } + if (decompressed_size != entry.file_size) { return false; } diff --git a/src/PackLib/Pack.h b/src/PackLib/Pack.h index 740807d..24638fa 100644 --- a/src/PackLib/Pack.h +++ b/src/PackLib/Pack.h @@ -4,6 +4,8 @@ #include "config.h" +class CBufferPool; + class CPack : public std::enable_shared_from_this { public: @@ -12,6 +14,7 @@ public: bool Open(const std::string& path, TPackFileMap& entries); bool GetFile(const TPackFileEntry& entry, TPackFile& result); + bool GetFileWithPool(const TPackFileEntry& entry, TPackFile& result, CBufferPool* pPool); private: TPackFileHeader m_header; diff --git a/src/PackLib/PackManager.cpp b/src/PackLib/PackManager.cpp index 9258c78..8ad49af 100644 --- a/src/PackLib/PackManager.cpp +++ b/src/PackLib/PackManager.cpp @@ -1,14 +1,38 @@ #include "PackManager.h" +#include "EterLib/BufferPool.h" #include #include +CPackManager::CPackManager() + : m_load_from_pack(true) + , m_pBufferPool(nullptr) +{ + m_pBufferPool = new CBufferPool(); +} + +CPackManager::~CPackManager() +{ + if (m_pBufferPool) + { + delete m_pBufferPool; + m_pBufferPool = nullptr; + } +} + bool CPackManager::AddPack(const std::string& path) { std::shared_ptr pack = std::make_shared(); + + std::lock_guard lock(m_mutex); return pack->Open(path, m_entries); } bool CPackManager::GetFile(std::string_view path, TPackFile& result) +{ + return GetFileWithPool(path, result, m_pBufferPool); +} + +bool CPackManager::GetFileWithPool(std::string_view path, TPackFile& result, CBufferPool* pPool) { thread_local std::string buf; NormalizePath(path, buf); @@ -16,7 +40,7 @@ bool CPackManager::GetFile(std::string_view path, TPackFile& result) if (m_load_from_pack) { auto it = m_entries.find(buf); if (it != m_entries.end()) { - return it->second.first->GetFile(it->second.second, result); + return it->second.first->GetFileWithPool(it->second.second, result, pPool); } } else { @@ -25,7 +49,14 @@ bool CPackManager::GetFile(std::string_view path, TPackFile& result) ifs.seekg(0, std::ios::end); size_t size = ifs.tellg(); ifs.seekg(0, std::ios::beg); - result.resize(size); + + if (pPool) { + result = pPool->Acquire(size); + result.resize(size); + } else { + result.resize(size); + } + if (ifs.read((char*)result.data(), size)) { return true; } diff --git a/src/PackLib/PackManager.h b/src/PackLib/PackManager.h index ecf939d..f6b712e 100644 --- a/src/PackLib/PackManager.h +++ b/src/PackLib/PackManager.h @@ -1,26 +1,34 @@ #pragma once #include +#include #include "EterBase/Singleton.h" #include "Pack.h" +class CBufferPool; + class CPackManager : public CSingleton { public: - CPackManager() = default; - virtual ~CPackManager() = default; + CPackManager(); + virtual ~CPackManager(); bool AddPack(const std::string& path); bool GetFile(std::string_view path, TPackFile& result); + bool GetFileWithPool(std::string_view path, TPackFile& result, CBufferPool* pPool); bool IsExist(std::string_view path) const; void SetPackLoadMode() { m_load_from_pack = true; } void SetFileLoadMode() { m_load_from_pack = false; } + CBufferPool* GetBufferPool() { return m_pBufferPool; } + private: void NormalizePath(std::string_view in, std::string& out) const; private: bool m_load_from_pack = true; TPackFileMap m_entries; + CBufferPool* m_pBufferPool; + mutable std::mutex m_mutex; // Thread safety for parallel pack loading };