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

Initialize sub-query only once #6328

Merged
merged 2 commits into from
Feb 23, 2023
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
### Fixed
* <How do the end-user experience this issue? what was the impact?> ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?)
* Converting local realm to sync'd realm crashes if an embedded object is null ([#6294](https://github.com/realm/realm-core/issues/6294), since v11.9.0)
* Fixed performance degradation on SubQueries ([#6327](https://github.com/realm/realm-core/issues/6327), since v6.0.0)

### Breaking changes
* None.
Expand Down
13 changes: 12 additions & 1 deletion src/realm/query_expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3866,7 +3866,10 @@ class SubQueryCount : public Subexpr2<Int> {
{
std::vector<ObjKey> links = m_link_map.get_links(index);
// std::sort(links.begin(), links.end());
m_query.init();
if (!m_initialized) {
m_query.init();
m_initialized = true;
}

size_t count = std::accumulate(links.begin(), links.end(), size_t(0), [this](size_t running_count, ObjKey k) {
const Obj obj = m_link_map.get_target_table()->get_object(k);
Expand All @@ -3893,9 +3896,17 @@ class SubQueryCount : public Subexpr2<Int> {
return make_subexpr<SubQueryCount>(*this);
}

SubQueryCount(const SubQueryCount& other)
: m_query(other.m_query)
, m_link_map(other.m_link_map)
, m_initialized(false)
{
}

private:
Query m_query;
LinkMap m_link_map;
bool m_initialized = false;
};

// The unused template parameter is a hack to avoid a circular dependency between table.hpp and query_expression.hpp.
Expand Down
39 changes: 18 additions & 21 deletions test/benchmark-common-tasks/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,31 +338,23 @@ struct BenchmarkFindFirstStringFewDupes : BenchmarkWithStringsFewDup {
};

struct BenchmarkQueryStringOverLinks : BenchmarkWithStringsFewDup {
ColKey link_col_ndx;
ColKey id_col_ndx;
ColKey link_col;
ColKey id_col;
void before_all(DBRef group)
{
BenchmarkWithStringsFewDup::before_all(group);
WrtTrans tr(group);
TableRef t = tr.add_table("Links");
id_col_ndx = t->add_column(type_Int, "id");
id_col = t->add_column(type_Int, "id");
TableRef strings = tr.get_table(name());
link_col_ndx = t->add_column(*strings, "myLink");
link_col = t->add_column(*strings, "myLink");
const size_t num_links = strings->size();

#ifdef REALM_CLUSTER_IF
auto target = strings->begin();
for (size_t i = 0; i < num_links; ++i) {
t->create_object().set_all(int64_t(i), target->get_key());
++target;
}
#else
for (size_t i = 0; i < num_links; ++i) {
auto ndx = t->add_empty_row();
t->set_int(id_col_ndx, ndx, i);
t->set_link(link_col_ndx, ndx, i);
}
#endif
tr.commit();
}
const char* name() const
Expand All @@ -371,20 +363,12 @@ struct BenchmarkQueryStringOverLinks : BenchmarkWithStringsFewDup {
}
virtual void before_each(DBRef group)
{
#ifdef REALM_CLUSTER_IF
m_tr.reset(new WrtTrans(group));
#else
m_tr.reset(new WrtTrans(group));
#endif
m_table = m_tr->get_table("Links");
}
virtual void after_each(DBRef)
{
#ifdef REALM_CLUSTER_IF
m_table = nullptr;
#else
m_table.reset();
#endif
m_tr = nullptr;
}
void operator()(DBRef)
Expand All @@ -395,7 +379,7 @@ struct BenchmarkQueryStringOverLinks : BenchmarkWithStringsFewDup {
};

for (auto s : strs) {
Query query = table->link(link_col_ndx).column<String>(m_col) == StringData(s);
Query query = table->link(link_col).column<String>(m_col) == StringData(s);
TableView results = query.find_all();
}
}
Expand All @@ -409,6 +393,18 @@ struct BenchmarkQueryStringOverLinks : BenchmarkWithStringsFewDup {
}
};

struct BenchmarkSubQuery : BenchmarkQueryStringOverLinks {
const char* name() const
{
return "SubqueryStrings";
}
void operator()(DBRef)
{
Query subquery = m_table->get_link_target(link_col)->column<String>(m_col) == "20";
Query query = m_table->column<Link>(link_col, subquery).count() >= 1;
TableView results = query.find_all();
}
};

struct BenchmarkFindFirstStringManyDupes : BenchmarkWithStringsManyDup {
const char* name() const
Expand Down Expand Up @@ -2143,6 +2139,7 @@ int benchmark_common_tasks_main()
BENCH(BenchmarkQueryIntEqualityIndexed);
BENCH(BenchmarkIntVsDoubleColumns);
BENCH(BenchmarkQueryStringOverLinks);
BENCH(BenchmarkSubQuery);
BENCH(BenchmarkQueryTimestampGreaterOverLinks);
BENCH(BenchmarkQueryTimestampGreater);
BENCH(BenchmarkQueryTimestampGreaterEqual);
Expand Down