mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Speed up archive caching
This is particularly significant for large Data directories.
This commit is contained in:
+10
-8
@@ -153,7 +153,6 @@ void Game::LoadPlugins(const std::vector<std::string>& plugins,
|
||||
|
||||
// Clear the existing plugin and archive caches.
|
||||
cache_->ClearCachedPlugins();
|
||||
cache_->ClearCachedArchivePaths();
|
||||
|
||||
// Search for and cache archives.
|
||||
CacheArchives();
|
||||
@@ -243,17 +242,20 @@ void Game::SetLoadOrder(const std::vector<std::string>& loadOrder) {
|
||||
void Game::CacheArchives() {
|
||||
const auto archiveFileExtension = GetArchiveFileExtension(Type());
|
||||
|
||||
std::set<std::filesystem::path> archivePaths;
|
||||
for (std::filesystem::directory_iterator it(DataPath());
|
||||
it != std::filesystem::directory_iterator();
|
||||
++it) {
|
||||
// Check if the path is an archive by checking if replacing its
|
||||
// file extension with the archive extension resolves to the same file.
|
||||
// Could use boost::iends_with, but it's less obvious here that the
|
||||
// test string is ASCII-only.
|
||||
if (loot::equivalent(it->path(),
|
||||
replaceExtension(it->path(), archiveFileExtension))) {
|
||||
cache_->CacheArchivePath(it->path());
|
||||
// This is only correct for ASCII strings, but that's all that
|
||||
// GetArchiveFileExtension() can return. It's a lot faster than the more
|
||||
// generally-correct approach of testing file path equivalence when
|
||||
// there are a lot of entries in DataPath().
|
||||
if (it->is_regular_file() &&
|
||||
boost::iends_with(it->path().u8string(), archiveFileExtension)) {
|
||||
archivePaths.insert(it->path());
|
||||
}
|
||||
}
|
||||
|
||||
cache_->CacheArchivePaths(std::move(archivePaths));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@ using std::string;
|
||||
namespace loot {
|
||||
GameCache::GameCache() {}
|
||||
|
||||
GameCache::GameCache(const GameCache& cache) :
|
||||
plugins_(cache.plugins_) {}
|
||||
GameCache::GameCache(const GameCache& cache) : plugins_(cache.plugins_) {}
|
||||
|
||||
GameCache& GameCache::operator=(const GameCache& cache) {
|
||||
if (&cache != this) {
|
||||
@@ -78,20 +77,17 @@ void GameCache::AddPlugin(const Plugin&& plugin) {
|
||||
if (it != end(plugins_))
|
||||
plugins_.erase(it);
|
||||
|
||||
plugins_.emplace(normalizedName,
|
||||
std::make_shared<Plugin>(std::move(plugin)));
|
||||
plugins_.emplace(normalizedName, std::make_shared<Plugin>(std::move(plugin)));
|
||||
}
|
||||
|
||||
std::set<std::filesystem::path> GameCache::GetArchivePaths() const
|
||||
{
|
||||
std::set<std::filesystem::path> GameCache::GetArchivePaths() const {
|
||||
return archivePaths_;
|
||||
}
|
||||
|
||||
void GameCache::CacheArchivePath(const std::filesystem::path& path)
|
||||
{
|
||||
void GameCache::CacheArchivePaths(std::set<std::filesystem::path>&& paths) {
|
||||
lock_guard<mutex> lock(mutex_);
|
||||
|
||||
archivePaths_.insert(path);
|
||||
archivePaths_ = paths;
|
||||
}
|
||||
|
||||
void GameCache::ClearCachedPlugins() {
|
||||
@@ -99,10 +95,4 @@ void GameCache::ClearCachedPlugins() {
|
||||
|
||||
plugins_.clear();
|
||||
}
|
||||
|
||||
void GameCache::ClearCachedArchivePaths() {
|
||||
lock_guard<mutex> guard(mutex_);
|
||||
|
||||
archivePaths_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,10 +44,9 @@ public:
|
||||
void AddPlugin(const Plugin&& plugin);
|
||||
|
||||
std::set<std::filesystem::path> GetArchivePaths() const;
|
||||
void CacheArchivePath(const std::filesystem::path& path);
|
||||
void CacheArchivePaths(std::set<std::filesystem::path>&& paths);
|
||||
|
||||
void ClearCachedPlugins();
|
||||
void ClearCachedArchivePaths();
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, std::shared_ptr<const Plugin>> plugins_;
|
||||
|
||||
@@ -113,8 +113,8 @@ TEST_P(GameCacheTest,
|
||||
|
||||
TEST_P(GameCacheTest,
|
||||
gettingArchivePathsShouldReturnASetOfPathsIfPathsHaveBeenCached) {
|
||||
cache_.CacheArchivePath(game_.DataPath() / blankEsm);
|
||||
cache_.CacheArchivePath(game_.DataPath() / blankMasterDependentEsm);
|
||||
cache_.CacheArchivePaths({game_.DataPath() / blankEsm,
|
||||
game_.DataPath() / blankMasterDependentEsm});
|
||||
|
||||
auto expected = std::set<std::filesystem::path>({
|
||||
game_.DataPath() / blankEsm,
|
||||
@@ -137,18 +137,6 @@ TEST_P(GameCacheTest, clearingCachedPluginsShouldClearAnyCachedPlugins) {
|
||||
|
||||
EXPECT_TRUE(cache_.GetPlugins().empty());
|
||||
}
|
||||
|
||||
TEST_P(GameCacheTest,
|
||||
clearingCachedArchivePathsShouldNotThrowIfNoPathsAreCached) {
|
||||
EXPECT_NO_THROW(cache_.GetArchivePaths());
|
||||
}
|
||||
|
||||
TEST_P(GameCacheTest, clearingCachedArchivePathsShouldClearAnyCachedPaths) {
|
||||
cache_.CacheArchivePath(game_.DataPath() / blankEsm);
|
||||
cache_.ClearCachedArchivePaths();
|
||||
|
||||
EXPECT_TRUE(cache_.GetArchivePaths().empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,10 +91,10 @@ protected:
|
||||
out.open(nonAsciiPrefixArchivePath);
|
||||
out.close();
|
||||
|
||||
game_.GetCache()->CacheArchivePath(dataPath / blankArchive);
|
||||
game_.GetCache()->CacheArchivePath(dataPath / blankSuffixArchive);
|
||||
game_.GetCache()->CacheArchivePath(dataPath / nonAsciiArchivePath);
|
||||
game_.GetCache()->CacheArchivePath(dataPath / nonAsciiPrefixArchivePath);
|
||||
game_.GetCache()->CacheArchivePaths({dataPath / blankArchive,
|
||||
dataPath / blankSuffixArchive,
|
||||
dataPath / nonAsciiArchivePath,
|
||||
dataPath / nonAsciiPrefixArchivePath});
|
||||
}
|
||||
|
||||
uintmax_t getGhostedPluginFileSize() {
|
||||
|
||||
Reference in New Issue
Block a user