1
0
Fork 0

speedup for object comparisons

This commit is contained in:
jsteemann 2017-02-21 17:21:25 +01:00
parent 43d797132a
commit eb293ba0d3
2 changed files with 67 additions and 24 deletions

View File

@ -113,11 +113,16 @@ class Collection {
ObjectIterator it(slice);
while (it.valid()) {
result.emplace(std::move(it.key(true).copyString()));
result.emplace(it.key(true).copyString());
it.next();
}
}
template<typename T>
static void keys(Slice const* slice, T& result) {
return keys(*slice, result);
}
static void keys(Slice const& slice, std::vector<std::string>& result) {
// pre-allocate result vector
result.reserve(checkOverflow(slice.length()));
@ -130,9 +135,19 @@ class Collection {
}
}
template<typename T>
static void unorderedKeys(Slice const& slice, T& result) {
ObjectIterator it(slice, true);
while (it.valid()) {
result.emplace(it.key(true).copyString());
it.next();
}
}
template<typename T>
static void keys(Slice const* slice, T& result) {
return keys(*slice, result);
static void unorderedKeys(Slice const* slice, T& result) {
return unorderedKeys(*slice, result);
}
static Builder extract(Slice const& slice, int64_t from, int64_t to = INT64_MAX);

View File

@ -731,10 +731,6 @@ int VelocyPackHelper::compare(VPackSlice lhs, VPackSlice rhs, bool useUTF8,
auto lhsType = lhs.type();
switch (lhsType) {
case VPackValueType::Illegal:
case VPackValueType::MinKey:
case VPackValueType::MaxKey:
case VPackValueType::None:
case VPackValueType::Null:
return 0;
case VPackValueType::Bool: {
@ -811,29 +807,61 @@ int VelocyPackHelper::compare(VPackSlice lhs, VPackSlice rhs, bool useUTF8,
return 0;
}
case VPackValueType::Object: {
std::set<std::string, AttributeSorterUTF8> keys;
VPackCollection::keys(lhs, keys);
VPackCollection::keys(rhs, keys);
for (auto const& key : keys) {
VPackSlice lhsValue = lhs.get(key).resolveExternal();
if (lhsValue.isNone()) {
// not present => null
lhsValue = VPackSlice::nullSlice();
}
VPackSlice rhsValue = rhs.get(key).resolveExternal();
if (rhsValue.isNone()) {
// not present => null
rhsValue = VPackSlice::nullSlice();
}
if (useUTF8) {
// must sort attributes by proper UTF8 values
// this is expensive
std::set<std::string, AttributeSorterUTF8> keys;
VPackCollection::keys(lhs, keys);
VPackCollection::keys(rhs, keys);
for (auto const& key : keys) {
VPackSlice lhsValue = lhs.get(key).resolveExternal();
if (lhsValue.isNone()) {
// not present => null
lhsValue = VPackSlice::nullSlice();
}
VPackSlice rhsValue = rhs.get(key).resolveExternal();
if (rhsValue.isNone()) {
// not present => null
rhsValue = VPackSlice::nullSlice();
}
int result = compare(lhsValue, rhsValue, useUTF8, options, &lhs, &rhs);
if (result != 0) {
return result;
int result = compare(lhsValue, rhsValue, useUTF8, options, &lhs, &rhs);
if (result != 0) {
return result;
}
}
} else {
// no UTF8-awareness is required here. do a quick and dirty comparison
std::set<std::string> keys;
VPackCollection::unorderedKeys(lhs, keys);
VPackCollection::unorderedKeys(rhs, keys);
for (auto const& key : keys) {
VPackSlice lhsValue = lhs.get(key).resolveExternal();
if (lhsValue.isNone()) {
// not present => null
lhsValue = VPackSlice::nullSlice();
}
VPackSlice rhsValue = rhs.get(key).resolveExternal();
if (rhsValue.isNone()) {
// not present => null
rhsValue = VPackSlice::nullSlice();
}
int result = compare(lhsValue, rhsValue, useUTF8, options, &lhs, &rhs);
if (result != 0) {
return result;
}
}
}
return 0;
}
case VPackValueType::Illegal:
case VPackValueType::MinKey:
case VPackValueType::MaxKey:
case VPackValueType::None:
// uncommon cases are compared at the end
return 0;
default:
// Contains all other ValueTypes of VelocyPack.
// They are not used in ArangoDB so this cannot occur