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

Further sectioned results performance improvements #6646

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/realm/array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,6 @@ class Array : public Node, public ArrayParent {
{
}

~Array() noexcept override {}

/// Create a new integer array of the specified type and size, and filled
/// with the specified value, and attach this accessor to it. This does not
/// modify the parent reference information of this accessor.
Expand Down
2 changes: 0 additions & 2 deletions src/realm/cluster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,8 +531,6 @@ void Cluster::move(size_t ndx, ClusterNode* new_node, int64_t offset)
m_keys.truncate(ndx);
}

Cluster::~Cluster() {}

ColKey Cluster::get_col_key(size_t ndx_in_parent) const
{
ColKey::Idx col_ndx{unsigned(ndx_in_parent - 1)}; // <- leaf_index here. Opaque.
Expand Down
6 changes: 1 addition & 5 deletions src/realm/cluster.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,6 @@ class ClusterNode : public Array {
{
m_keys.set_parent(this, 0);
}
virtual ~ClusterNode()
{
}
void init_from_parent()
{
ref_type ref = get_ref_from_parent();
Expand Down Expand Up @@ -163,7 +160,7 @@ class ClusterNode : public Array {
/// Locate object identified by 'key' and update 'state' accordingly
void get(ObjKey key, State& state) const;
/// Locate object identified by 'key' and update 'state' accordingly
/// Returns `false` if the object doesn't not exist.
/// Returns `false` if the object doesn't exist.
virtual bool try_get(ObjKey key, State& state) const noexcept = 0;
/// Locate object identified by 'ndx' and update 'state' accordingly
virtual ObjKey get(size_t ndx, State& state) const = 0;
Expand Down Expand Up @@ -220,7 +217,6 @@ class Cluster : public ClusterNode {
: ClusterNode(offset, allocator, tree_top)
{
}
~Cluster() override;

static MemRef create_empty_cluster(Allocator& alloc);

Expand Down
22 changes: 19 additions & 3 deletions src/realm/cluster_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ namespace realm {
class ClusterNodeInner : public ClusterNode {
public:
ClusterNodeInner(Allocator& allocator, const ClusterTree& tree_top);
~ClusterNodeInner() override;

void create(int sub_tree_depth);
void init(MemRef mem) override;
Expand Down Expand Up @@ -196,8 +195,6 @@ ClusterNodeInner::ClusterNodeInner(Allocator& allocator, const ClusterTree& tree
{
}

ClusterNodeInner::~ClusterNodeInner() {}

void ClusterNodeInner::create(int sub_tree_depth)
{
Array::create(Array::type_InnerBptreeNode, false, s_first_node_index);
Expand Down Expand Up @@ -1455,4 +1452,23 @@ ClusterTree::Iterator::pointer ClusterTree::Iterator::operator->() const
return &m_obj;
}

ClusterTree::LeafCache::LeafCache(const Table& table)
: m_tree(table.m_clusters)
, m_leaf(0, m_tree.get_alloc(), m_tree)
{
}

Obj ClusterTree::LeafCache::get(ObjKey key)
{
ClusterNode::State state;
auto k2 = ObjKey(key.value - m_leaf.m_offset);
if (m_leaf.is_attached() && m_leaf.try_get(k2, state)) {
return Obj(m_tree.get_table_ref(), m_leaf.get_mem(), key, state.index);
}
ClusterNode::IteratorState state2(m_leaf);
bool found = m_tree.get_leaf(key, state2);
REALM_ASSERT(found);
return Obj(m_tree.get_table_ref(), m_leaf.get_mem(), key, state2.m_current_index);
}

} // namespace realm
11 changes: 11 additions & 0 deletions src/realm/cluster_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class Cluster;
class ClusterTree {
public:
class Iterator;
class LeafCache;
using TraverseFunction = util::FunctionRef<IteratorControl(const Cluster*)>;
using UpdateFunction = util::FunctionRef<void(Cluster*)>;
using ColIterateFunction = util::FunctionRef<IteratorControl(ColKey)>;
Expand Down Expand Up @@ -282,6 +283,16 @@ class ClusterTree::Iterator {
ObjKey load_leaf(ObjKey key) const;
size_t get_position();
};

class ClusterTree::LeafCache {
public:
LeafCache(const Table& table);
Obj get(ObjKey);

private:
const ClusterTree& m_tree;
Cluster m_leaf;
};
} // namespace realm

#endif /* REALM_CLUSTER_TREE_HPP */
2 changes: 1 addition & 1 deletion src/realm/obj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ Obj::Obj(TableRef table, MemRef mem, ObjKey key, size_t row_ndx)
, m_key(key)
, m_mem(mem)
, m_row_ndx(row_ndx)
, m_storage_version(_get_alloc().get_storage_version())
, m_valid(true)
{
m_storage_version = get_alloc().get_storage_version();
}

GlobalKey Obj::get_object_id() const
Expand Down
6 changes: 5 additions & 1 deletion src/realm/object-store/object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,11 @@ class Object {
{
return *m_object_schema;
}
Obj obj() const
Obj& obj()
{
return m_obj;
}
const Obj& obj() const
{
return m_obj;
}
Expand Down
3 changes: 1 addition & 2 deletions src/realm/object-store/results.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,7 @@ class Results {
*
* @return A SectionedResults object using a user defined sectioning algorithm.
*/
SectionedResults sectioned_results(
util::UniqueFunction<Mixed(Mixed value, const std::shared_ptr<Realm>& realm)>&& section_key_func);
SectionedResults sectioned_results(util::UniqueFunction<Mixed(Results&, size_t)>&& section_key_func);
enum class SectionedResultsOperator {
FirstLetter // Section by the first letter of each string element. Note that col must be a string.
};
Expand Down
11 changes: 5 additions & 6 deletions src/realm/object-store/sectioned_results.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,14 @@ static SectionedResults::SectionKeyFunc builtin_comparison(Results& results, Res
case Results::SectionedResultsOperator::FirstLetter:
if (results.get_type() == PropertyType::Object) {
auto col_key = results.get_table()->get_column_key(prop_name);
return [col_key](Mixed value, const SharedRealm& realm) {
auto link = value.get_link();
auto v = realm->read_group().get_object(link).get<StringData>(col_key);
return [col_key](Results& results, size_t i) {
auto v = results.get<Obj>(i).get<StringData>(col_key);
return v.size() > 0 ? v.prefix(1) : "";
};
}
else {
return [](Mixed value, const SharedRealm&) {
auto v = value.get_string();
return [](Results& results, size_t i) {
auto v = results.get<StringData>(i);
return v.size() > 0 ? v.prefix(1) : "";
};
}
Expand Down Expand Up @@ -423,7 +422,7 @@ void SectionedResults::calculate_sections()
m_row_to_index_path.resize(size);

for (size_t i = 0; i < size; ++i) {
Mixed key = m_callback(m_results.get_any(i), m_results.get_realm());
Mixed key = m_callback(m_results, i);
// Disallow links as section keys. It would be uncommon to use them to begin with
// and if the object acting as the key was deleted bad things would happen.
if (key.is_type(type_Link, type_TypedLink)) {
Expand Down
2 changes: 1 addition & 1 deletion src/realm/object-store/sectioned_results.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class ResultsSection {
class SectionedResults {
public:
SectionedResults() = default;
using SectionKeyFunc = util::UniqueFunction<Mixed(Mixed value, const std::shared_ptr<Realm>& realm)>;
using SectionKeyFunc = util::UniqueFunction<Mixed(Results& results, size_t i)>;

/**
* Returns a `ResultsSection` which will be bound to a section key present at the given index in
Expand Down
39 changes: 19 additions & 20 deletions src/realm/query.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1909,29 +1909,28 @@ Query Query::operator!()

void Query::get_outside_versions(TableVersions& versions) const
{
if (m_table) {
if (m_table_keys.empty()) {
// Store primary table info
m_table_keys.push_back(m_table.unchecked_ptr()->get_key());
if (!m_table) {
return;
}
auto table = m_table.unchecked_ptr();
if (m_table_keys.empty()) {
// Store primary table info
m_table_keys.push_back(table->get_key());

if (ParentNode* root = root_node())
root->get_link_dependencies(m_table_keys);
}
versions.emplace_back(m_table.unchecked_ptr()->get_key(), m_table.unchecked_ptr()->get_content_version());

if (Group* g = m_table.unchecked_ptr()->get_parent_group()) {
// update table versions for linked tables - first entry is primary table - skip it
auto end = m_table_keys.end();
auto it = m_table_keys.begin() + 1;
while (it != end) {
versions.emplace_back(*it, g->get_table(*it)->get_content_version());
++it;
}
}
if (m_view) {
m_view->get_dependencies(versions);
if (ParentNode* root = root_node())
root->get_link_dependencies(m_table_keys);
}
versions.emplace_back(table->get_key(), table->get_content_version());

if (Group* g = table->get_parent_group()) {
// update table versions for linked tables - first entry is primary table - skip it
for (auto it = m_table_keys.begin() + 1, end = m_table_keys.end(); it != end; ++it) {
versions.emplace_back(*it, g->get_table(*it).unchecked_ptr()->get_content_version());
}
}
if (m_view) {
m_view->get_dependencies(versions);
}
}

TableVersions Query::sync_view_if_needed() const
Expand Down
11 changes: 6 additions & 5 deletions src/realm/sort_descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ void ColumnsDescriptor::collect_dependencies(const Table* table, std::vector<Tab
const Table* t = table;
for (size_t i = 0; i < sz - 1; i++) {
ColKey col = columns[i];
ConstTableRef target_table;
const Table* target_table = nullptr;
if (t->get_column_type(col) == type_Link) {
target_table = t->get_link_target(col);
target_table = t->get_link_target(col).unchecked_ptr();
}
if (!target_table)
return;
table_keys.push_back(target_table->get_key());
t = target_table.unchecked_ptr();
t = target_table;
}
}
}
Expand Down Expand Up @@ -356,6 +356,7 @@ void BaseDescriptor::Sorter::cache_first_column(IndexPairs& v)

auto& col = m_columns[0];
ColKey ck = col.col_key;
ClusterTree::LeafCache cache(*col.table);
for (size_t i = 0; i < v.size(); i++) {
IndexPair& index = v[i];
ObjKey key = index.key_for_object;
Expand All @@ -368,7 +369,7 @@ void BaseDescriptor::Sorter::cache_first_column(IndexPairs& v)
}
}

index.cached_value = col.table->get_object(key).get_any(ck);
index.cached_value = cache.get(key).get_any(ck);
}
}

Expand Down Expand Up @@ -535,6 +536,6 @@ void DescriptorOrdering::get_versions(const Group* group, TableVersions& version
{
for (auto table_key : m_dependencies) {
REALM_ASSERT_DEBUG(group);
versions.emplace_back(table_key, group->get_table(table_key)->get_content_version());
versions.emplace_back(table_key, group->get_table(table_key).unchecked_ptr()->get_content_version());
}
}
69 changes: 9 additions & 60 deletions src/realm/table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2503,111 +2503,60 @@ ObjKey Table::find_first_uuid(ColKey col_key, UUID value) const
}

template <class T>
TableView Table::find_all(ColKey col_key, T value)
TableView Table::find_all(ColKey col_key, T value) const
{
return where().equal(col_key, value).find_all();
}

TableView Table::find_all_int(ColKey col_key, int64_t value)
{
return find_all<int64_t>(col_key, value);
}

TableView Table::find_all_int(ColKey col_key, int64_t value) const
{
return const_cast<Table*>(this)->find_all<int64_t>(col_key, value);
}

TableView Table::find_all_bool(ColKey col_key, bool value)
{
return find_all<bool>(col_key, value);
return find_all<int64_t>(col_key, value);
}

TableView Table::find_all_bool(ColKey col_key, bool value) const
{
return const_cast<Table*>(this)->find_all<int64_t>(col_key, value);
}


TableView Table::find_all_float(ColKey col_key, float value)
{
return find_all<float>(col_key, value);
return find_all<bool>(col_key, value);
}

TableView Table::find_all_float(ColKey col_key, float value) const
{
return const_cast<Table*>(this)->find_all<float>(col_key, value);
}

TableView Table::find_all_double(ColKey col_key, double value)
{
return find_all<double>(col_key, value);
return find_all<float>(col_key, value);
}

TableView Table::find_all_double(ColKey col_key, double value) const
{
return const_cast<Table*>(this)->find_all<double>(col_key, value);
}

TableView Table::find_all_string(ColKey col_key, StringData value)
{
return where().equal(col_key, value).find_all();
return find_all<double>(col_key, value);
}

TableView Table::find_all_string(ColKey col_key, StringData value) const
{
return const_cast<Table*>(this)->find_all_string(col_key, value);
}

TableView Table::find_all_binary(ColKey, BinaryData)
{
throw Exception(ErrorCodes::IllegalOperation, "Table::find_all_binary not supported");
}

TableView Table::find_all_binary(ColKey col_key, BinaryData value) const
{
return const_cast<Table*>(this)->find_all_binary(col_key, value);
}

TableView Table::find_all_null(ColKey col_key)
{
return where().equal(col_key, null{}).find_all();
return where().equal(col_key, value).find_all();
}

TableView Table::find_all_null(ColKey col_key) const
{
return const_cast<Table*>(this)->find_all_null(col_key);
return where().equal(col_key, null{}).find_all();
}

TableView Table::find_all_fulltext(ColKey col_key, StringData terms) const
{
return where().fulltext(col_key, terms).find_all();
}

TableView Table::get_sorted_view(ColKey col_key, bool ascending)
TableView Table::get_sorted_view(ColKey col_key, bool ascending) const
{
TableView tv = where().find_all();
tv.sort(col_key, ascending);
return tv;
}

TableView Table::get_sorted_view(ColKey col_key, bool ascending) const
{
return const_cast<Table*>(this)->get_sorted_view(col_key, ascending);
}

TableView Table::get_sorted_view(SortDescriptor order)
TableView Table::get_sorted_view(SortDescriptor order) const
{
TableView tv = where().find_all();
tv.sort(std::move(order));
return tv;
}

TableView Table::get_sorted_view(SortDescriptor order) const
{
return const_cast<Table*>(this)->get_sorted_view(std::move(order));
}

util::Logger* Table::get_logger() const noexcept
{
return *m_repl ? (*m_repl)->get_logger() : nullptr;
Expand Down
Loading