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.
This commit is contained in:
James Turner 2020-10-29 23:13:10 +00:00 committed by James Turner
parent 3ff3bd0a6c
commit 96bafef3f3
2 changed files with 17 additions and 23 deletions

View File

@ -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));
}
}

View File

@ -21,6 +21,7 @@
#include <memory>
#include <string>
#include <unordered_map>
#include <simgear/io/HTTPClient.hxx>
#include <simgear/misc/sg_path.hxx>
@ -59,7 +60,7 @@ public:
std::string hashHex;
};
typedef std::vector<HashCacheEntry> HashCache;
using HashCache = std::unordered_map<std::string, HashCacheEntry>;
HashCache hashes;
int hashCacheDirty = 0;