Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: several improvements around sorted map #1699

Merged
merged 2 commits into from
Aug 15, 2023
Merged

chore: several improvements around sorted map #1699

merged 2 commits into from
Aug 15, 2023

Conversation

romange
Copy link
Collaborator

@romange romange commented Aug 15, 2023

  1. Pass memory_resource to sorted_map.
  2. Get rid of GetDict leaky accessor in SortedMap and introduce a proper Scan method.
  3. Introduce a proper BPTree type inside SortedMap::DFImpl.
  4. Added a test for bptree_test that covers sds comparison (apparently, sdscmp can return values outside of [-1, 1] range). Fixed bptree code to support a proper spec for three-way comparison.

@romange romange requested a review from dranikpg August 15, 2023 03:33

} // namespace

class BPTreeSetTest : public ::testing::Test {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this class existed before.

}

struct ZsetPolicy {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i just moved this policy up to be able to use it in tests

uint64_t ubound = stack.back().second;
stack.pop_back();

if (!Validate(node, ubound))
if (!ValidateNode<Node, BPTreePolicy<uint64_t>>(node, ubound))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made ValidateNode generic - to be able to use it for differrent types of trees

Clear();
}

pair<void*, bool> ScoreMap::AddOrUpdate(string_view field, double value) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expose internal objects managed by ScoreMap so we could
insert them into BPTree

return dictScan(this->dict, cursor, scanCb, NULL, &cb);
}

int SortedMap::DfImpl::ScoreSdsPolicy::KeyCompareTo::operator()(ScoreSds a, ScoreSds b) const {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

implement comparison for ScoreMap internal objects.

1. Pass memory_resource to sorted_map.
2. Get rid of GetDict leaky accessor in SortedMap and introduce a proper
   Scan method.
3. Introduce correct BPTree type inside SortedMap::DFImpl.
4. Added a test for bptree_test that covers sds comparison
   (apparently, sdscmp can return values outside of [-1, 1] range).
   Fixed bptree code to support a proper spec for three-way comparison.
5. Expose pointers to internal objects allocated by score_map so we could insert them
   into bptree.

Signed-off-by: Roman Gershman <roman@dragonflydb.io>
dranikpg
dranikpg previously approved these changes Aug 15, 2023
dict* GetDict() const {
return std::get<RdImpl>(impl_).dict;
uint64_t Scan(uint64_t cursor, absl::FunctionRef<void(std::string_view, double)> cb) const {
return std::visit(Overload{[&](const auto& impl) { return impl.Scan(cursor, cb); }}, impl_);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stop using the overload 🤣

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dranikpg Why? it's a nice utility ? :D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it works without in all those cases, its an auto lambda and visit([](auto& impl) { ... }) does the job. I pointed it out already in the last PR, but the code was already written 🙂

Comment on lines 376 to 382
auto scanCb = [](void* privdata, const dictEntry* de) {
auto* cb = (absl::FunctionRef<void(std::string_view, double)>*)privdata;

sds key = (sds)de->key;
double score = *(double*)dictGetVal(de);
(*cb)(std::string_view(key, sdslen(key)), score);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, it decays to a function pointer below only if it doesn't capture anything, nit reinterpret_cast is by the styleguide

Comment on lines 80 to 82
// Returns true if field was added
// otherwise updates its value and returns false.
bool AddOrUpdate(std::string_view field, double value);
std::pair<void*, bool> AddOrUpdate(std::string_view field, double value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. You forgot to update the comment
  2. Its strange you now have a nice external interface for both sorted set types, but return void* for the element

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As usual, you are welcomed to fix it up later :)

Comment on lines +481 to +483
SortedMap::SortedMap(PMR_NS::memory_resource* mr) : impl_(RdImpl()), mr_res_(mr) {
std::visit(Overload{[](RdImpl& impl) { impl.Init(); }, [mr](DfImpl& impl) { impl.Init(mr); }},
impl_);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can also be shortened at least twice 🙂

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, it has differrent implementations here.
btw, please remember that the end goal is to get rid of RdImpl so all this boilerplate is temporary.
Similarly, I am planning to get rid of the old set implementation some time this year.

Comment on lines 65 to 73
double GetObjScore(const void* obj) {
DoubleIntUnion u;
sds s = (sds)obj;
char* ptr = s + sdslen(s) + 1;
u.u64 = absl::little_endian::Load64(ptr);

return u.score;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return absl::bit_cast<double>(absl::little_endian::Load64(ptr)) 😅

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

Signed-off-by: Roman Gershman <roman@dragonflydb.io>
@romange romange merged commit ec22e73 into main Aug 15, 2023
10 checks passed
@romange romange deleted the Pr1 branch August 15, 2023 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants