From 96bafef3f3ef8061f67a4887f1d4c72d6d619530 Mon Sep 17 00:00:00 2001 From: James Turner Date: Thu, 29 Oct 2020 23:13:10 +0000 Subject: [PATCH] TerraSync: use an unordered_map for the hash cache Linear-scan is a bit slow in debug builds, for the large Airports/ tree; switch to an unordered_map. Will back-port to the LTS once tested a bit more. --- simgear/io/HTTPRepository.cxx | 37 +++++++++++---------------- simgear/io/HTTPRepository_private.hxx | 3 ++- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/simgear/io/HTTPRepository.cxx b/simgear/io/HTTPRepository.cxx index 0f771ce3..b3506615 100644 --- a/simgear/io/HTTPRepository.cxx +++ b/simgear/io/HTTPRepository.cxx @@ -986,25 +986,16 @@ HTTPRepository::failure() const return r; } - - class HashEntryWithPath - { - public: - HashEntryWithPath(const SGPath& p) : path(p.utf8Str()) {} - bool operator()(const HTTPRepoPrivate::HashCacheEntry& entry) const - { return entry.filePath == path; } - private: - std::string path; - }; - std::string HTTPRepoPrivate::hashForPath(const SGPath& p) { - HashCache::iterator it = std::find_if(hashes.begin(), hashes.end(), HashEntryWithPath(p)); + const auto ps = p.utf8Str(); + auto it = hashes.find(ps); if (it != hashes.end()) { + const auto& entry = it->second; // ensure data on disk hasn't changed. // we could also use the file type here if we were paranoid - if ((p.sizeInBytes() == it->lengthBytes) && (p.modTime() == it->modTime)) { - return it->hashHex; + if ((p.sizeInBytes() == entry.lengthBytes) && (p.modTime() == entry.modTime)) { + return entry.hashHex; } // entry in the cache, but it's stale so remove and fall through @@ -1049,7 +1040,8 @@ HTTPRepository::failure() const void HTTPRepoPrivate::updatedFileContents(const SGPath& p, const std::string& newHash) { // remove the existing entry - auto it = std::find_if(hashes.begin(), hashes.end(), HashEntryWithPath(p)); + const auto ps = p.utf8Str(); + auto it = hashes.find(ps); if (it != hashes.end()) { hashes.erase(it); ++hashCacheDirty; @@ -1065,11 +1057,11 @@ HTTPRepository::failure() const p2.set_cached(true); HashCacheEntry entry; - entry.filePath = p.utf8Str(); + entry.filePath = ps; entry.hashHex = newHash; entry.modTime = p2.modTime(); entry.lengthBytes = p2.sizeInBytes(); - hashes.push_back(entry); + hashes.insert(std::make_pair(ps, entry)); ++hashCacheDirty ; } @@ -1083,10 +1075,11 @@ HTTPRepository::failure() const SGPath cachePath = basePath; cachePath.append(".hashes"); sg_ofstream stream(cachePath, std::ios::out | std::ios::trunc | std::ios::binary); - HashCache::const_iterator it; - for (it = hashes.begin(); it != hashes.end(); ++it) { - stream << it->filePath << "*" << it->modTime << "*" - << it->lengthBytes << "*" << it->hashHex << "\n"; + for (const auto& e : hashes) { + const auto& entry = e.second; + + stream << entry.filePath << "*" << entry.modTime << "*" + << entry.lengthBytes << "*" << entry.hashHex << "\n"; } stream.close(); hashCacheDirty = 0; @@ -1130,7 +1123,7 @@ HTTPRepository::failure() const entry.hashHex = hashData; entry.modTime = strtol(timeData.c_str(), NULL, 10); entry.lengthBytes = strtol(sizeData.c_str(), NULL, 10); - hashes.push_back(entry); + hashes.insert(std::make_pair(entry.filePath, entry)); } } diff --git a/simgear/io/HTTPRepository_private.hxx b/simgear/io/HTTPRepository_private.hxx index 3f825896..68efac15 100644 --- a/simgear/io/HTTPRepository_private.hxx +++ b/simgear/io/HTTPRepository_private.hxx @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -59,7 +60,7 @@ public: std::string hashHex; }; - typedef std::vector HashCache; + using HashCache = std::unordered_map; HashCache hashes; int hashCacheDirty = 0;