Skip to content

Commit 5edb85d

Browse files
committed
Store less data for notification tracking on collections in Mixed
We only need the very next path element, not the entire remaining path.
1 parent 666bb25 commit 5edb85d

File tree

7 files changed

+24
-34
lines changed

7 files changed

+24
-34
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
### Enhancements
44
* Add support to synchronize collections embedded in Mixed properties and other collections (except sets) ([PR #7353](https://github.com/realm/realm-core/pull/7353)).
5+
* Improve performance of change notifications on nested collections somewhat ([PR #7402](https://github.com/realm/realm-core/pull/7402)).
56

67
### Fixed
78
* 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)).

src/realm/collection_parent.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,7 @@ bool StablePath::is_prefix_of(const StablePath& other) const noexcept
6666
{
6767
if (size() > other.size())
6868
return false;
69-
70-
auto it = other.begin();
71-
for (auto& p : *this) {
72-
if (!(p == *it))
73-
return false;
74-
++it;
75-
}
76-
return true;
69+
return std::equal(begin(), end(), other.begin());
7770
}
7871

7972
/***************************** CollectionParent ******************************/

src/realm/object-store/collection_notifications.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ struct CollectionChangeSet {
106106
// Per-column version of `modifications`
107107
std::unordered_map<int64_t, IndexSet> columns;
108108

109-
std::set<StablePath> paths;
109+
std::set<StableIndex> paths;
110110

111111
bool empty() const noexcept
112112
{

src/realm/object-store/impl/list_notifier.cpp

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,11 @@ void ListNotifier::attach(CollectionBase const& src)
6262
if (auto obj = tr.get_table(src.get_table()->get_key())->try_get_object(src.get_owner_key())) {
6363
auto path = src.get_stable_path();
6464
m_list = std::static_pointer_cast<CollectionBase>(obj.get_collection_by_stable_path(path));
65+
m_collection_parent = dynamic_cast<CollectionParent*>(m_list.get());
6566
}
6667
else {
6768
m_list = nullptr;
69+
m_collection_parent = nullptr;
6870
}
6971
}
7072

@@ -73,14 +75,9 @@ bool ListNotifier::do_add_required_change_info(TransactionChangeInfo& info)
7375
if (!m_list || !m_list->is_attached())
7476
return false; // origin row was deleted after the notification was added
7577

76-
// We need to have the collections with the shortest paths first
7778
StablePath this_path = m_list->get_stable_path();
78-
auto it = std::lower_bound(info.collections.begin(), info.collections.end(), this_path.size(),
79-
[](const CollectionChangeInfo& info, size_t sz) {
80-
return info.path.size() < sz;
81-
});
82-
info.collections.insert(
83-
it, {m_list->get_table()->get_key(), m_list->get_owner_key(), std::move(this_path), &m_change});
79+
info.collections.push_back(
80+
{m_list->get_table()->get_key(), m_list->get_owner_key(), std::move(this_path), &m_change});
8481

8582
m_info = &info;
8683

@@ -142,14 +139,14 @@ void ListNotifier::run()
142139
}
143140
}
144141

142+
// Modifications to nested values in Mixed are recorded in replication as
143+
// StableIndex and we have to look up the actual index afterwards
145144
if (m_change.paths.size()) {
146-
if (auto coll = dynamic_cast<CollectionParent*>(m_list.get())) {
147-
for (auto& p : m_change.paths) {
148-
// Report changes in substructure as modifications on this list
149-
auto ndx = coll->find_index(p[0]);
150-
if (ndx != realm::not_found)
151-
m_change.modifications.add(ndx); // OK to insert same index again
152-
}
145+
REALM_ASSERT(m_collection_parent);
146+
REALM_ASSERT(m_type == PropertyType::Mixed);
147+
for (auto& p : m_change.paths) {
148+
if (auto ndx = m_collection_parent->find_index(p); ndx != realm::not_found)
149+
m_change.modifications.add(ndx);
153150
}
154151
}
155152
}

src/realm/object-store/impl/list_notifier.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class ListNotifier : public CollectionNotifier {
3434
private:
3535
PropertyType m_type;
3636
CollectionBasePtr m_list;
37+
CollectionParent* m_collection_parent = nullptr;
3738

3839
// The last-seen size of the collection so that when the parent of the collection
3940
// is deleted we can report each row as being deleted

src/realm/object-store/impl/results_notifier.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -393,13 +393,13 @@ void ListResultsNotifier::run()
393393
std::iota(m_run_indices->begin(), m_run_indices->end(), 0);
394394
}
395395

396+
// Modifications to nested values in Mixed are recorded in replication as
397+
// StableIndex and we have to look up the actual index afterwards
396398
if (m_change.paths.size()) {
397399
if (auto coll = dynamic_cast<CollectionParent*>(m_list.get())) {
398400
for (auto& p : m_change.paths) {
399-
// Report changes in substructure as modifications on this list
400-
auto ndx = coll->find_index(p[0]);
401-
if (ndx != realm::not_found)
402-
m_change.modifications.add(ndx); // OK to insert same index again
401+
if (auto ndx = coll->find_index(p); ndx != realm::not_found)
402+
m_change.modifications.add(ndx);
403403
}
404404
}
405405
}

src/realm/object-store/impl/transact_log_handler.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -368,21 +368,19 @@ class TransactLogObserver : public TransactLogValidationMixin {
368368
{
369369
modify_object(col, obj);
370370
auto table = current_table();
371+
m_active_collection = nullptr;
371372
for (auto& c : m_info.collections) {
372-
373373
if (c.table_key == table && c.obj_key == obj && c.path.is_prefix_of(path)) {
374374
if (c.path.size() != path.size()) {
375-
StablePath sub_path;
376-
sub_path.insert(sub_path.begin(), path.begin() + c.path.size(), path.end());
377-
c.changes->paths.insert(std::move(sub_path));
375+
c.changes->paths.insert(path[c.path.size()]);
378376
}
379-
else {
377+
// If there are multiple exact matches for this collection we
378+
// use the first and then propagate the data to the others later
379+
else if (!m_active_collection) {
380380
m_active_collection = c.changes;
381-
return true;
382381
}
383382
}
384383
}
385-
m_active_collection = nullptr;
386384
return true;
387385
}
388386

0 commit comments

Comments
 (0)