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:
parent
3ff3bd0a6c
commit
96bafef3f3
@ -986,25 +986,16 @@ HTTPRepository::failure() const
|
|||||||
return r;
|
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)
|
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()) {
|
if (it != hashes.end()) {
|
||||||
|
const auto& entry = it->second;
|
||||||
// ensure data on disk hasn't changed.
|
// ensure data on disk hasn't changed.
|
||||||
// we could also use the file type here if we were paranoid
|
// we could also use the file type here if we were paranoid
|
||||||
if ((p.sizeInBytes() == it->lengthBytes) && (p.modTime() == it->modTime)) {
|
if ((p.sizeInBytes() == entry.lengthBytes) && (p.modTime() == entry.modTime)) {
|
||||||
return it->hashHex;
|
return entry.hashHex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// entry in the cache, but it's stale so remove and fall through
|
// 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)
|
void HTTPRepoPrivate::updatedFileContents(const SGPath& p, const std::string& newHash)
|
||||||
{
|
{
|
||||||
// remove the existing entry
|
// 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()) {
|
if (it != hashes.end()) {
|
||||||
hashes.erase(it);
|
hashes.erase(it);
|
||||||
++hashCacheDirty;
|
++hashCacheDirty;
|
||||||
@ -1065,11 +1057,11 @@ HTTPRepository::failure() const
|
|||||||
p2.set_cached(true);
|
p2.set_cached(true);
|
||||||
|
|
||||||
HashCacheEntry entry;
|
HashCacheEntry entry;
|
||||||
entry.filePath = p.utf8Str();
|
entry.filePath = ps;
|
||||||
entry.hashHex = newHash;
|
entry.hashHex = newHash;
|
||||||
entry.modTime = p2.modTime();
|
entry.modTime = p2.modTime();
|
||||||
entry.lengthBytes = p2.sizeInBytes();
|
entry.lengthBytes = p2.sizeInBytes();
|
||||||
hashes.push_back(entry);
|
hashes.insert(std::make_pair(ps, entry));
|
||||||
|
|
||||||
++hashCacheDirty ;
|
++hashCacheDirty ;
|
||||||
}
|
}
|
||||||
@ -1083,10 +1075,11 @@ HTTPRepository::failure() const
|
|||||||
SGPath cachePath = basePath;
|
SGPath cachePath = basePath;
|
||||||
cachePath.append(".hashes");
|
cachePath.append(".hashes");
|
||||||
sg_ofstream stream(cachePath, std::ios::out | std::ios::trunc | std::ios::binary);
|
sg_ofstream stream(cachePath, std::ios::out | std::ios::trunc | std::ios::binary);
|
||||||
HashCache::const_iterator it;
|
for (const auto& e : hashes) {
|
||||||
for (it = hashes.begin(); it != hashes.end(); ++it) {
|
const auto& entry = e.second;
|
||||||
stream << it->filePath << "*" << it->modTime << "*"
|
|
||||||
<< it->lengthBytes << "*" << it->hashHex << "\n";
|
stream << entry.filePath << "*" << entry.modTime << "*"
|
||||||
|
<< entry.lengthBytes << "*" << entry.hashHex << "\n";
|
||||||
}
|
}
|
||||||
stream.close();
|
stream.close();
|
||||||
hashCacheDirty = 0;
|
hashCacheDirty = 0;
|
||||||
@ -1130,7 +1123,7 @@ HTTPRepository::failure() const
|
|||||||
entry.hashHex = hashData;
|
entry.hashHex = hashData;
|
||||||
entry.modTime = strtol(timeData.c_str(), NULL, 10);
|
entry.modTime = strtol(timeData.c_str(), NULL, 10);
|
||||||
entry.lengthBytes = strtol(sizeData.c_str(), NULL, 10);
|
entry.lengthBytes = strtol(sizeData.c_str(), NULL, 10);
|
||||||
hashes.push_back(entry);
|
hashes.insert(std::make_pair(entry.filePath, entry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <simgear/io/HTTPClient.hxx>
|
#include <simgear/io/HTTPClient.hxx>
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
@ -59,7 +60,7 @@ public:
|
|||||||
std::string hashHex;
|
std::string hashHex;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<HashCacheEntry> HashCache;
|
using HashCache = std::unordered_map<std::string, HashCacheEntry>;
|
||||||
HashCache hashes;
|
HashCache hashes;
|
||||||
int hashCacheDirty = 0;
|
int hashCacheDirty = 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user