Skip to content

Commit

Permalink
Improve performance of aggregate operations on empty dictionaries
Browse files Browse the repository at this point in the history
  • Loading branch information
tgoyne committed Mar 13, 2024
1 parent 687bb98 commit 2b43cf8
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### Enhancements
* Add support to synchronize collections embedded in Mixed properties and other collections (except sets) ([PR #7353](https://github.com/realm/realm-core/pull/7353)).
* Improve performance of change notifications on nested collections somewhat ([PR #7402](https://github.com/realm/realm-core/pull/7402)).
* Improve performance of aggregate operations on Dictionaries of objects, particularly when the dictionaries are empty ([PR #7418](https://github.com/realm/realm-core/pull/7418))

### Fixed
* Fixed conflict resolution bug which may result in an crash when the AddInteger instruction on Mixed properties is merged against updates to a non-integer type ([PR #7353](https://github.com/realm/realm-core/pull/7353)).
Expand Down
36 changes: 17 additions & 19 deletions src/realm/collection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,12 @@ class CollectionBase : public Collection {
return PathElement(ndx);
}

// Clone this collection if it contains objects, and return nullptr otherwise
virtual LinkCollectionPtr clone_as_obj_list() const
{
return nullptr;
}

/// Return true if the collection has changed since the last call to
/// `has_changed()`. Note that this function is not idempotent and updates
/// the internal state of the accessor if it has changed.
Expand Down Expand Up @@ -202,7 +208,7 @@ class CollectionBase : public Collection {
}

/// If this is a collection of links, get the target table.
virtual TableRef get_target_table() const final
TableRef get_target_table() const
{
return get_obj().get_target_table(get_col_key());
}
Expand Down Expand Up @@ -815,24 +821,12 @@ void update_unresolved(std::vector<size_t>& vec, const BPlusTree<ObjKey>* tree);

/// Clear the context flag on the tree if there are no more unresolved links.
void check_for_last_unresolved(BPlusTree<ObjKey>* tree);

/// Proxy class needed because the ObjList interface clobbers method names from
/// CollectionBase.
struct ObjListProxy : ObjList {
virtual TableRef proxy_get_target_table() const = 0;

TableRef get_target_table() const final
{
return proxy_get_target_table();
}
};

} // namespace _impl

/// Base class for collections of objects, where unresolved links (tombstones)
/// can occur.
template <class Interface>
class ObjCollectionBase : public Interface, public _impl::ObjListProxy {
class ObjCollectionBase : public Interface, public ObjList {
public:
static_assert(std::is_base_of_v<CollectionBase, Interface>);

Expand Down Expand Up @@ -868,7 +862,15 @@ class ObjCollectionBase : public Interface, public _impl::ObjListProxy {
return m_unresolved.size() != 0;
}

using Interface::get_target_table;
LinkCollectionPtr clone_as_obj_list() const final
{
return clone_obj_list();
}

TableRef get_target_table() const final
{
return Interface::get_target_table();
}

protected:
ObjCollectionBase() = default;
Expand Down Expand Up @@ -956,10 +958,6 @@ class ObjCollectionBase : public Interface, public _impl::ObjListProxy {
// Sorted set of indices containing unresolved links.
mutable std::vector<size_t> m_unresolved;

TableRef proxy_get_target_table() const final
{
return Interface::get_target_table();
}
bool matches(const ObjList& other) const final
{
return get_owning_obj().get_key() == other.get_owning_obj().get_key() &&
Expand Down
8 changes: 8 additions & 0 deletions src/realm/dictionary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,14 @@ void Dictionary::set_collection_ref(Index index, ref_type ref, CollectionType ty
m_values->set(ndx, Mixed(ref, type));
}

LinkCollectionPtr Dictionary::clone_as_obj_list() const
{
if (get_value_data_type() == type_Link) {
return std::make_unique<DictionaryLinkValues>(*this);
}
return nullptr;
}

/************************* DictionaryLinkValues *************************/

DictionaryLinkValues::DictionaryLinkValues(const Obj& obj, ColKey col_key)
Expand Down
2 changes: 2 additions & 0 deletions src/realm/dictionary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ class Dictionary final : public CollectionBaseImpl<DictionaryBase>, public Colle

void to_json(std::ostream&, JSONOutputMode, util::FunctionRef<void(const Mixed&)>) const override;

LinkCollectionPtr clone_as_obj_list() const final;

private:
using Base::set_collection;

Expand Down
9 changes: 2 additions & 7 deletions src/realm/object-store/results.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -810,13 +810,8 @@ Query Results::do_get_query() const
return Query(m_table, std::make_unique<TableView>(m_table_view));
}
case Mode::Collection:
if (auto list = dynamic_cast<ObjList*>(m_collection.get())) {
return m_table->where(*list);
}
if (auto dict = dynamic_cast<Dictionary*>(m_collection.get())) {
if (dict->get_value_data_type() == type_Link) {
return m_table->where(*dict);
}
if (auto objlist = m_collection->clone_as_obj_list()) {
return m_table->where(std::move(objlist));
}
return m_query;
case Mode::Table:
Expand Down
4 changes: 2 additions & 2 deletions src/realm/table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1082,9 +1082,9 @@ void Table::do_erase_root_column(ColKey col_key)
bump_storage_version();
}

Query Table::where(const DictionaryLinkValues& dictionary_of_links) const
Query Table::where(const Dictionary& dict) const
{
return Query(m_own_ref, dictionary_of_links);
return Query(m_own_ref, dict.clone_as_obj_list());
}

void Table::set_table_type(Type table_type, bool handle_backlinks)
Expand Down
6 changes: 5 additions & 1 deletion src/realm/table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,11 @@ class Table {
{
return Query(m_own_ref, list);
}
Query where(const DictionaryLinkValues& dictionary_of_links) const;
Query where(const Dictionary& dict) const;
Query where(LinkCollectionPtr&& list) const
{
return Query(m_own_ref, std::move(list));
}

Query query(const std::string& query_string,
const std::vector<mpark::variant<Mixed, std::vector<Mixed>>>& arguments = {}) const;
Expand Down

0 comments on commit 2b43cf8

Please sign in to comment.