Merge pull request #6575 from jzhou77/version-vector

Use boost::flat_map and optimize getDelta/applyDelta
This commit is contained in:
Jingyu Zhou 2022-03-11 07:34:47 -08:00 committed by GitHub
commit 402b463a26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 22 deletions

View File

@ -23,15 +23,14 @@
#pragma once
#include <map>
#include <boost/container/flat_map.hpp>
#include <set>
#include <unordered_map>
#include "fdbclient/FDBTypes.h"
#include "fdbclient/Knobs.h"
struct VersionVector {
std::unordered_map<Tag, Version> versions;
boost::container::flat_map<Tag, Version> versions;
Version maxVersion; // Specifies the max version in this version vector. (Note:
// there may or may not be a corresponding entry for this
// version in the "versions" map.)
@ -39,6 +38,12 @@ struct VersionVector {
VersionVector() : maxVersion(invalidVersion) {}
VersionVector(Version version) : maxVersion(version) {}
private:
// Only invoked by getDelta() and applyDelta(), where tag has been validated
// and version is guaranteed to be larger than the existing value.
inline void setVersionNoCheck(const Tag& tag, Version version) { versions[tag] = version; }
public:
Version getMaxVersion() const { return maxVersion; }
int size() const { return versions.size(); }
@ -92,17 +97,11 @@ struct VersionVector {
if (CLIENT_KNOBS->SEND_ENTIRE_VERSION_VECTOR) {
delta = *this;
} else {
std::map<Version, std::set<Tag>> tmpVersionMap; // order versions
for (const auto& [tag, version] : versions) {
if (version > refVersion) {
tmpVersionMap[version].insert(tag);
delta.setVersionNoCheck(tag, version);
}
}
for (auto& [version, tags] : tmpVersionMap) {
delta.setVersion(tags, version);
}
delta.maxVersion = maxVersion;
}
}
@ -122,17 +121,11 @@ struct VersionVector {
if (CLIENT_KNOBS->SEND_ENTIRE_VERSION_VECTOR) {
*this = delta;
} else {
std::map<Version, std::set<Tag>> tmpVersionMap; // order versions
for (const auto& [tag, version] : delta.versions) {
if (version > maxVersion) {
tmpVersionMap[version].insert(tag);
setVersionNoCheck(tag, version);
}
}
for (auto& [version, tags] : tmpVersionMap) {
setVersion(tags, version);
}
maxVersion = delta.maxVersion;
}
}

View File

@ -21,6 +21,7 @@
#pragma once
#include <algorithm>
#include <boost/container/flat_map.hpp>
#include <iterator>
#include <cstring>
#include <functional>
@ -227,6 +228,30 @@ struct vector_like_traits<std::unordered_map<Key, T, Hash, Pred, Allocator>> : s
}
};
template <class Key, class T, class Compare, class Allocator>
struct vector_like_traits<boost::container::flat_map<Key, T, Compare, Allocator>> : std::true_type {
using Vec = boost::container::flat_map<Key, T, Compare, Allocator>;
using value_type = std::pair<Key, T>;
using iterator = typename Vec::const_iterator;
using insert_iterator = std::insert_iterator<Vec>;
template <class Context>
static size_t num_entries(const Vec& v, Context&) {
return v.size();
}
template <class Context>
static void reserve(Vec& v, size_t size, Context&) {}
template <class Context>
static insert_iterator insert(Vec& v, Context&) {
return std::inserter(v, v.end());
}
template <class Context>
static iterator begin(const Vec& v, Context&) {
return v.begin();
}
};
template <class Key, class Compare, class Allocator>
struct vector_like_traits<std::set<Key, Compare, Allocator>> : std::true_type {
using Vec = std::set<Key, Compare, Allocator>;

View File

@ -22,17 +22,19 @@
#define FLOW_SERIALIZE_H
#pragma once
#include <stdint.h>
#include <algorithm>
#include <array>
#include <boost/container/flat_map.hpp>
#include <deque>
#include <set>
#include "flow/ProtocolVersion.h"
#include "flow/Error.h"
#include <stdint.h>
#include "flow/Arena.h"
#include "flow/Error.h"
#include "flow/FileIdentifier.h"
#include "flow/ObjectSerializer.h"
#include "flow/ProtocolVersion.h"
#include "flow/network.h"
#include <algorithm>
#include <deque>
// Though similar, is_binary_serializable cannot be replaced by std::is_pod, as doing so would prefer
// memcpy over a defined serialize() method on a POD struct. As not all of our structs are packed,
@ -268,6 +270,27 @@ inline void load(Archive& ar, std::map<K, V>& value) {
ASSERT(ar.protocolVersion().isValid());
}
template <class Archive, class K, class V>
inline void save(Archive& ar, const boost::container::flat_map<K, V>& value) {
ar << (int)value.size();
for (const auto& it : value) {
ar << it.first << it.second;
}
ASSERT(ar.protocolVersion().isValid());
}
template <class Archive, class K, class V>
inline void load(Archive& ar, boost::container::flat_map<K, V>& value) {
int s;
ar >> s;
value.clear();
for (int i = 0; i < s; ++i) {
std::pair<K, V> p;
ar >> p.first >> p.second;
value.emplace(p);
}
ASSERT(ar.protocolVersion().isValid());
}
#ifdef _MSC_VER
#pragma intrinsic(memcpy)
#endif