From 06bee153e363c120bb88e6ea2f5873433bd51b9a Mon Sep 17 00:00:00 2001 From: James Stone Date: Wed, 20 Sep 2023 12:43:08 -0700 Subject: [PATCH 1/2] remove core metrics --- CHANGELOG.md | 1 + CMakeLists.txt | 1 - src/realm/CMakeLists.txt | 11 - src/realm/db.cpp | 14 - src/realm/db.hpp | 6 - src/realm/db_options.hpp | 8 - src/realm/group.cpp | 23 - src/realm/group.hpp | 18 - src/realm/group_writer.cpp | 10 - src/realm/metrics/metric_timer.cpp | 144 --- src/realm/metrics/metric_timer.hpp | 100 -- src/realm/metrics/metrics.cpp | 133 --- src/realm/metrics/metrics.hpp | 76 -- src/realm/metrics/query_info.cpp | 127 --- src/realm/metrics/query_info.hpp | 69 -- src/realm/metrics/transaction_info.cpp | 108 --- src/realm/metrics/transaction_info.hpp | 73 -- src/realm/query.cpp | 30 - src/realm/query.hpp | 5 - src/realm/query_engine.hpp | 1 - src/realm/query_expression.hpp | 1 - src/realm/table.hpp | 4 - src/realm/transaction.cpp | 36 - src/realm/util/config.h.in | 1 - test/CMakeLists.txt | 1 - test/test_metrics.cpp | 1207 ------------------------ test/test_parser.cpp | 1 - test/testsettings.hpp | 1 - 28 files changed, 1 insertion(+), 2209 deletions(-) delete mode 100644 src/realm/metrics/metric_timer.cpp delete mode 100644 src/realm/metrics/metric_timer.hpp delete mode 100644 src/realm/metrics/metrics.cpp delete mode 100644 src/realm/metrics/metrics.hpp delete mode 100644 src/realm/metrics/query_info.cpp delete mode 100644 src/realm/metrics/query_info.hpp delete mode 100644 src/realm/metrics/transaction_info.cpp delete mode 100644 src/realm/metrics/transaction_info.hpp delete mode 100644 test/test_metrics.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d80254703d..4bcd5d45c84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ ### Internals * Update History Command tool to work with realms with fileformat v23 ([PR #6970](https://github.com/realm/realm-core/pull/6970)) * Don't edit the ObjectStore target to enable the libuv scheduler in tests, just register the factory instead. ([PR #6699](https://github.com/realm/realm-core/pull/6699)) +* Removed the core metrics which were unused. ([PR 6990](https://github.com/realm/realm-core/pull/6990)) ---------------------------------------------- diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e94e6a0317..131db994b8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -254,7 +254,6 @@ if(NOT EMSCRIPTEN) endif() option(REALM_ENABLE_MEMDEBUG "Add additional memory checks" OFF) option(REALM_VALGRIND "Tell the test suite we are running with valgrind" OFF) -option(REALM_METRICS "Enable various metric tracking" ON) option(REALM_SYNC_MULTIPLEXING "Enables/disables sync session multiplexing by default" ON) set(REALM_MAX_BPNODE_SIZE "1000" CACHE STRING "Max B+ tree node size.") option(REALM_ENABLE_GEOSPATIAL "Enable geospatial types and queries." ON) diff --git a/src/realm/CMakeLists.txt b/src/realm/CMakeLists.txt index f4751827f94..03ae01356d1 100644 --- a/src/realm/CMakeLists.txt +++ b/src/realm/CMakeLists.txt @@ -249,11 +249,6 @@ set(REALM_INSTALL_HEADERS util/to_string.hpp util/type_traits.hpp util/uri.hpp - - metrics/metrics.hpp - metrics/metric_timer.hpp - metrics/query_info.hpp - metrics/transaction_info.hpp ) # REALM_INSTALL_HEADERS set(REALM_NOINST_HEADERS @@ -279,12 +274,6 @@ set(REALM_NOINST_HEADERS util/value_reset_guard.hpp ) # REALM_NOINST_HEADERS -list(APPEND REALM_SOURCES - metrics/metrics.cpp - metrics/metric_timer.cpp - metrics/query_info.cpp - metrics/transaction_info.cpp) - if(NOT MSVC) list(APPEND REALM_SOURCES util/interprocess_mutex.cpp) endif() diff --git a/src/realm/db.cpp b/src/realm/db.cpp index 3952efc097e..b0178081808 100644 --- a/src/realm/db.cpp +++ b/src/realm/db.cpp @@ -57,7 +57,6 @@ using namespace realm; -using namespace realm::metrics; using namespace realm::util; using Durability = DBOptions::Durability; @@ -1443,11 +1442,6 @@ void DB::open(const std::string& path, bool no_create_file, const DBOptions& opt close(); throw; } -#if REALM_METRICS - if (options.enable_metrics) { - m_metrics = std::make_shared(options.metrics_buffer_size); - } -#endif // REALM_METRICS m_alloc.set_read_only(true); } @@ -1534,11 +1528,6 @@ void DB::open(Replication& repl, const DBOptions options) m_file_format_version = target_file_format_version; -#if REALM_METRICS - if (options.enable_metrics) { - m_metrics = std::make_shared(options.metrics_buffer_size); - } -#endif // REALM_METRICS m_info = info; m_alloc.set_read_only(true); } @@ -2483,9 +2472,6 @@ void DB::low_level_commit(uint_fast64_t new_version, Transaction& transaction, b auto live_versions = top_refs.size(); // Do the actual commit REALM_ASSERT(oldest_version <= new_version); -#if REALM_METRICS - transaction.update_num_objects(); -#endif // REALM_METRICS GroupWriter out(transaction, Durability(info->durability), m_marker_observer.get()); // Throws out.set_versions(new_version, top_refs, any_new_unreachables); diff --git a/src/realm/db.hpp b/src/realm/db.hpp index bf8d419b725..c87f293a14c 100644 --- a/src/realm/db.hpp +++ b/src/realm/db.hpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -391,10 +390,6 @@ class DB : public std::enable_shared_from_this { /// On the importing side, the top-level accessor being created during /// import takes ownership of all other accessors (if any) being created as /// part of the import. - std::shared_ptr get_metrics() - { - return m_metrics; - } // Try to grab an exclusive lock of the given realm path's lock file. If the lock // can be acquired, the callback will be executed with the lock and then return true. @@ -507,7 +502,6 @@ class DB : public std::enable_shared_from_this { util::InterprocessCondVar m_new_commit_available; util::InterprocessCondVar m_pick_next_writer; std::function m_upgrade_callback; - std::shared_ptr m_metrics; std::unique_ptr m_commit_helper; std::shared_ptr m_logger; bool m_is_sync_agent = false; diff --git a/src/realm/db_options.hpp b/src/realm/db_options.hpp index 327507a3d20..781e561a96a 100644 --- a/src/realm/db_options.hpp +++ b/src/realm/db_options.hpp @@ -80,14 +80,6 @@ struct DBOptions { /// This string should include a trailing slash '/'. std::string temp_dir = sys_tmp_dir; - /// Controls the feature of collecting various metrics to the DB. - /// A prerequisite is compiling with REALM_METRICS=ON. - bool enable_metrics = false; - - /// The maximum number of entries stored by the metrics (if enabled). If this number - /// is exceeded without being consumed, only the most recent entries will be stored. - size_t metrics_buffer_size = 10000; - /// is_immutable should be set to true if run from a read-only file system. /// this will prevent the DB from making any writes, also disabling the creation /// of write transactions. diff --git a/src/realm/group.cpp b/src/realm/group.cpp index 5b27ab9c291..c792021430f 100644 --- a/src/realm/group.cpp +++ b/src/realm/group.cpp @@ -76,7 +76,6 @@ Group::Group(const std::string& file_path, const char* encryption_key) , m_top(m_alloc) , m_tables(m_alloc) , m_table_names(m_alloc) - , m_total_rows(0) { init_array_parents(); @@ -99,7 +98,6 @@ Group::Group(BinaryData buffer, bool take_ownership) , m_top(m_alloc) , m_tables(m_alloc) , m_table_names(m_alloc) - , m_total_rows(0) { REALM_ASSERT(buffer.data()); @@ -118,7 +116,6 @@ Group::Group(SlabAlloc* alloc) noexcept m_top(m_alloc) , m_tables(m_alloc) , m_table_names(m_alloc) - , m_total_rows(0) { init_array_parents(); } @@ -560,9 +557,6 @@ void Group::attach(ref_type top_ref, bool writable, bool create_group_when_missi while (m_table_accessors.size() < sz) { m_table_accessors.emplace_back(); } -#if REALM_METRICS - update_num_objects(); -#endif // REALM_METRICS } @@ -578,23 +572,6 @@ void Group::detach() noexcept m_attached = false; } -void Group::update_num_objects() -{ -#if REALM_METRICS - if (m_metrics) { - // This is quite invasive and completely defeats the lazy loading mechanism - // where table accessors are only instantiated on demand, because they are all created here. - - m_total_rows = 0; - auto keys = get_table_keys(); - for (auto key : keys) { - ConstTableRef t = get_table(key); - m_total_rows += t->size(); - } - } -#endif // REALM_METRICS -} - void Group::attach_shared(ref_type new_top_ref, size_t new_file_size, bool writable, VersionID version) { REALM_ASSERT_3(new_top_ref, <, new_file_size); diff --git a/src/realm/group.hpp b/src/realm/group.hpp index ae43bfca187..b61bfe06782 100644 --- a/src/realm/group.hpp +++ b/src/realm/group.hpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -615,9 +614,7 @@ class Group : public ArrayParent { util::UniqueFunction m_notify_handler; util::UniqueFunction m_schema_change_handler; - std::shared_ptr m_metrics; std::vector m_objects_to_delete; - size_t m_total_rows; Group(SlabAlloc* alloc) noexcept; void init_array_parents() noexcept; @@ -690,9 +687,6 @@ class Group : public ArrayParent { void write(util::File& file, const char* encryption_key, uint_fast64_t version_number, TableWriter& writer) const; void write(std::ostream&, bool pad, uint_fast64_t version_numer, TableWriter& writer) const; - std::shared_ptr get_metrics() const noexcept; - void set_metrics(std::shared_ptr other) noexcept; - void update_num_objects(); /// Memory mappings must have been updated to reflect any growth in filesize before /// calling advance_transact() void advance_transact(ref_type new_top_ref, util::InputStream*, bool writable); @@ -837,8 +831,6 @@ class Group : public ArrayParent { friend class GroupCommitter; friend class DB; friend class _impl::GroupFriend; - friend class metrics::QueryInfo; - friend class metrics::Metrics; friend class Transaction; friend class TableKeyIterator; friend class CascadeState; @@ -1175,16 +1167,6 @@ inline void Group::reset_free_space_tracking() m_alloc.reset_free_space_tracking(); // Throws } -inline std::shared_ptr Group::get_metrics() const noexcept -{ - return m_metrics; -} - -inline void Group::set_metrics(std::shared_ptr shared) noexcept -{ - m_metrics = shared; -} - // The purpose of this class is to give internal access to some, but // not all of the non-public parts of the Group class. class _impl::GroupFriend { diff --git a/src/realm/group_writer.cpp b/src/realm/group_writer.cpp index 9f7834ab20f..41225a60753 100644 --- a/src/realm/group_writer.cpp +++ b/src/realm/group_writer.cpp @@ -28,13 +28,11 @@ #include #include #include -#include #include #include using namespace realm; using namespace realm::util; -using namespace realm::metrics; namespace realm { class InMemoryWriter : public _impl::ArrayWriterBase { @@ -647,10 +645,6 @@ void GroupWriter::prepare_evacuation() ref_type GroupWriter::write_group() { -#if REALM_METRICS - std::unique_ptr fsync_timer = Metrics::report_write_time(m_group); -#endif // REALM_METRICS - ALLOC_DBG_COUT("Commit nr " << m_current_version << " ( from " << m_oldest_reachable_version << " )" << std::endl); @@ -1409,10 +1403,6 @@ void GroupCommitter::commit(ref_type new_top_ref) bool disable_sync = get_disable_sync_to_disk() || m_durability == Durability::Unsafe; file_header.m_top_ref[slot_selector] = new_top_ref; -#if REALM_METRICS - std::unique_ptr fsync_timer = Metrics::report_fsync_time(m_group); -#endif // REALM_METRICS - // Make sure that that all data relating to the new snapshot is written to // stable storage before flipping the slot selector window->encryption_write_barrier(&file_header, sizeof file_header); diff --git a/src/realm/metrics/metric_timer.cpp b/src/realm/metrics/metric_timer.cpp deleted file mode 100644 index c8ff2d237b8..00000000000 --- a/src/realm/metrics/metric_timer.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - **************************************************************************/ - -#include - -#include -#include -#include -#include - -using namespace realm; -using namespace realm::metrics; - - -MetricTimerResult::MetricTimerResult() - : m_elapsed_nanoseconds(0) -{ -} - -MetricTimerResult::~MetricTimerResult() -{ -} - -nanosecond_storage_t MetricTimerResult::get_elapsed_nanoseconds() const -{ - return m_elapsed_nanoseconds; -} - -void MetricTimerResult::report_nanoseconds(nanosecond_storage_t time) -{ - m_elapsed_nanoseconds = time; -} - - -MetricTimer::MetricTimer(std::shared_ptr destination) - : m_dest(destination) -{ - reset(); -} - -MetricTimer::~MetricTimer() -{ - if (m_dest) { - m_dest->report_nanoseconds(get_elapsed_nanoseconds()); - } -} - -MetricTimer::time_point MetricTimer::get_timer_ticks() const -{ - return clock_type::now(); -} - -nanosecond_storage_t MetricTimer::calc_elapsed_nanoseconds(MetricTimer::time_point begin, - MetricTimer::time_point end) const -{ - std::chrono::duration elapsed = end - begin; - return elapsed.count(); -} - -std::string MetricTimer::format(nanosecond_storage_t nanoseconds) -{ - std::ostringstream out; - format(nanoseconds, out); - return out.str(); -} - -namespace { - -int64_t round_to_int64(double x) -{ - // Note: this is std::llround() from as of c++11, - // but this will actually use a native implementation on android. - return llround(x); -} - -} // end anonymous namespace - -// see also test/util/Timer.cpp -void MetricTimer::format(nanosecond_storage_t nanoseconds, std::ostream& out) -{ - constexpr int64_t ns_per_second = 1'000'000'000; - int64_t rounded_minutes = round_to_int64(nanoseconds / (60.0 * ns_per_second)); - if (rounded_minutes > 60) { - // 1h0m -> inf - int64_t hours = rounded_minutes / 60; - int64_t minutes = rounded_minutes % 60; - out << hours << "h" << minutes << "m"; - } - else { - int64_t rounded_seconds = round_to_int64(nanoseconds / double(ns_per_second)); - if (rounded_seconds > 60) { - // 1m0s -> 59m59s - int64_t minutes = rounded_seconds / 60; - int64_t seconds = rounded_seconds % 60; - out << minutes << "m" << seconds << "s"; - } - else { - int64_t rounded_centies = round_to_int64(nanoseconds / double(10'000'000)); - if (rounded_centies > 100) { - // 1s -> 59.99s - int64_t seconds = rounded_centies / 100; - int64_t centies = rounded_centies % 100; - out << seconds; - if (centies > 0) { - out << '.' << std::setw(2) << std::setfill('0') << centies; - } - out << 's'; - } - else { - int64_t rounded_centi_ms = round_to_int64(nanoseconds / double(10'000)); - if (rounded_centi_ms > 100) { - // 0.1ms -> 999.99ms - int64_t ms = rounded_centi_ms / 100; - int64_t centi_ms = rounded_centi_ms % 100; - out << ms; - if (centi_ms > 0) { - out << '.' << std::setw(2) << std::setfill('0') << centi_ms; - } - out << "ms"; - } - else { - // 0 -> 999µs - int64_t us = round_to_int64(nanoseconds / double(1'000)); - out << us << "us"; - } - } - } - } -} diff --git a/src/realm/metrics/metric_timer.hpp b/src/realm/metrics/metric_timer.hpp deleted file mode 100644 index b80c6f549e6..00000000000 --- a/src/realm/metrics/metric_timer.hpp +++ /dev/null @@ -1,100 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - **************************************************************************/ - -#ifndef REALM_METRIC_TIMER_HPP -#define REALM_METRIC_TIMER_HPP - -#include - -#include -#include -#include - -namespace realm { -namespace metrics { - -using nanosecond_storage_t = int64_t; - -class MetricTimerResult { -public: - MetricTimerResult(); - ~MetricTimerResult(); - nanosecond_storage_t get_elapsed_nanoseconds() const; - void report_nanoseconds(nanosecond_storage_t time); - -protected: - nanosecond_storage_t m_elapsed_nanoseconds; -}; - - -class MetricTimer { -public: - MetricTimer(std::shared_ptr destination = nullptr); - ~MetricTimer(); - - void reset(); - - /// Returns elapsed time in nanoseconds since last call to reset(). - nanosecond_storage_t get_elapsed_nanoseconds() const; - /// Same as get_elapsed_time(). - operator nanosecond_storage_t() const; - - /// Format the elapsed time on the form 0h00m, 00m00s, 00.00s, or - /// 000.0ms depending on magnitude. - static void format(nanosecond_storage_t nanoseconds, std::ostream&); - - static std::string format(nanosecond_storage_t nanoseconds); - -private: - using clock_type = std::chrono::high_resolution_clock; - using time_point = std::chrono::time_point; - time_point m_start; - time_point m_paused_at; - std::shared_ptr m_dest; - - time_point get_timer_ticks() const; - nanosecond_storage_t calc_elapsed_nanoseconds(time_point begin, time_point end) const; -}; - - -inline void MetricTimer::reset() -{ - m_start = get_timer_ticks(); -} - -inline nanosecond_storage_t MetricTimer::get_elapsed_nanoseconds() const -{ - return calc_elapsed_nanoseconds(m_start, get_timer_ticks()); -} - -inline MetricTimer::operator nanosecond_storage_t() const -{ - return get_elapsed_nanoseconds(); -} - -inline std::ostream& operator<<(std::ostream& out, const MetricTimer& timer) -{ - MetricTimer::format(timer, out); - return out; -} - - -} // namespace metrics -} // namespace realm - -#endif // REALM_METRIC_TIMER_HPP diff --git a/src/realm/metrics/metrics.cpp b/src/realm/metrics/metrics.cpp deleted file mode 100644 index b33de0af520..00000000000 --- a/src/realm/metrics/metrics.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - **************************************************************************/ - -#include -#include - -using namespace realm; -using namespace realm::metrics; - -Metrics::Metrics(size_t max_history_size) - : m_max_num_queries(max_history_size) - , m_max_num_transactions(max_history_size) -{ - m_query_info = std::make_unique(max_history_size); - m_transaction_info = std::make_unique(max_history_size); -} - -Metrics::~Metrics() noexcept -{ -} - -size_t Metrics::num_query_metrics() const -{ - return m_query_info ? m_query_info->size() : 0; -} - -size_t Metrics::num_transaction_metrics() const -{ - return m_transaction_info ? m_transaction_info->size() : 0; -} - -void Metrics::add_query(QueryInfo info) -{ - REALM_ASSERT_DEBUG(m_query_info); - m_query_info->insert(info); -} - -void Metrics::add_transaction(TransactionInfo info) -{ - REALM_ASSERT_DEBUG(m_transaction_info); - m_transaction_info->insert(info); -} - -void Metrics::start_read_transaction() -{ - REALM_ASSERT_DEBUG(!m_pending_read); - m_pending_read = std::make_unique(TransactionInfo::read_transaction); -} - -void Metrics::start_write_transaction() -{ - REALM_ASSERT_DEBUG(!m_pending_write); - m_pending_write = std::make_unique(TransactionInfo::write_transaction); -} - -void Metrics::end_read_transaction(size_t total_size, size_t free_space, size_t num_objects, size_t num_versions, - size_t num_decrypted_pages) -{ - REALM_ASSERT_DEBUG(m_transaction_info); - if (m_pending_read) { - m_pending_read->update_stats(total_size, free_space, num_objects, num_versions, num_decrypted_pages); - m_pending_read->finish_timer(); - add_transaction(*m_pending_read); - m_pending_read.reset(nullptr); - } -} - -void Metrics::end_write_transaction(size_t total_size, size_t free_space, size_t num_objects, size_t num_versions, - size_t num_decrypted_pages) -{ - REALM_ASSERT_DEBUG(m_transaction_info); - if (m_pending_write) { - m_pending_write->update_stats(total_size, free_space, num_objects, num_versions, num_decrypted_pages); - m_pending_write->finish_timer(); - add_transaction(*m_pending_write); - m_pending_write.reset(nullptr); - } -} - -std::unique_ptr Metrics::report_fsync_time(const Group& g) -{ - std::shared_ptr instance = g.get_metrics(); - if (instance) { - REALM_ASSERT_DEBUG(instance->m_transaction_info); - if (instance->m_pending_write) { - return std::make_unique(instance->m_pending_write->m_fsync_time); - } - } - return nullptr; -} - -std::unique_ptr Metrics::report_write_time(const Group& g) -{ - std::shared_ptr instance = g.get_metrics(); - if (instance) { - REALM_ASSERT_DEBUG(instance->m_transaction_info); - if (instance->m_pending_write) { - return std::make_unique(instance->m_pending_write->m_write_time); - } - } - return nullptr; -} - - -std::unique_ptr Metrics::take_queries() -{ - - std::unique_ptr values = std::make_unique(m_max_num_queries); - values.swap(m_query_info); - return values; -} - -std::unique_ptr Metrics::take_transactions() -{ - std::unique_ptr values = std::make_unique(m_max_num_transactions); - values.swap(m_transaction_info); - return values; -} diff --git a/src/realm/metrics/metrics.hpp b/src/realm/metrics/metrics.hpp deleted file mode 100644 index 3e9ff00a957..00000000000 --- a/src/realm/metrics/metrics.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - **************************************************************************/ - -#ifndef REALM_METRICS_HPP -#define REALM_METRICS_HPP - -#include - -#include -#include -#include -#include "realm/util/fixed_size_buffer.hpp" - -namespace realm { - -class Group; - -namespace metrics { - -class Metrics { -public: - Metrics(size_t max_history_size); - ~Metrics() noexcept; - size_t num_query_metrics() const; - size_t num_transaction_metrics() const; - - void add_query(QueryInfo info); - void add_transaction(TransactionInfo info); - - void start_read_transaction(); - void start_write_transaction(); - void end_read_transaction(size_t total_size, size_t free_space, size_t num_objects, size_t num_versions, - size_t num_decrypted_pages); - void end_write_transaction(size_t total_size, size_t free_space, size_t num_objects, size_t num_versions, - size_t num_decrypted_pages); - static std::unique_ptr report_fsync_time(const Group& g); - static std::unique_ptr report_write_time(const Group& g); - - using QueryInfoList = util::FixedSizeBuffer; - using TransactionInfoList = util::FixedSizeBuffer; - - // Get the list of metric objects tracked since the last take - std::unique_ptr take_queries(); - std::unique_ptr take_transactions(); - -private: - std::unique_ptr m_query_info; - std::unique_ptr m_transaction_info; - - std::unique_ptr m_pending_read; - std::unique_ptr m_pending_write; - - size_t m_max_num_queries; - size_t m_max_num_transactions; -}; - -} // namespace metrics -} // namespace realm - - -#endif // REALM_METRICS_HPP diff --git a/src/realm/metrics/query_info.cpp b/src/realm/metrics/query_info.cpp deleted file mode 100644 index 4ff00370ead..00000000000 --- a/src/realm/metrics/query_info.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - **************************************************************************/ - -#include -#include -#include -#include - -using namespace realm; -using namespace realm::metrics; - -QueryInfo::QueryInfo(const Query* query, QueryType type) - : m_type(type) -{ -#if REALM_METRICS - REALM_ASSERT(query); - - const Group* group = query->m_table->get_parent_group(); - REALM_ASSERT(group); - - try { - m_description = query->get_description(); - } - catch (const SerializationError& e) { - m_description = e.what(); - } - m_table_name = query->m_table->get_name(); -#else - static_cast(query); -#endif -} - -QueryInfo::~QueryInfo() noexcept -{ -} - -std::string QueryInfo::get_description() const -{ - return m_description; -} - -std::string QueryInfo::get_table_name() const -{ - return m_table_name; -} - -QueryInfo::QueryType QueryInfo::get_type() const -{ - return m_type; -} - -nanosecond_storage_t QueryInfo::get_query_time_nanoseconds() const -{ - if (m_query_time) { - return m_query_time->get_elapsed_nanoseconds(); - } - return 0; -} - -std::unique_ptr QueryInfo::track(const Query* query, QueryType type) -{ -#if REALM_METRICS - REALM_ASSERT_DEBUG(query); - - if (!bool(query->m_table)) { - return nullptr; - } - - const Group* group = query->m_table->get_parent_group(); - - // If the table is not attached to a group we cannot track it's metrics. - if (!group) - return nullptr; - - std::shared_ptr metrics = group->get_metrics(); - if (!metrics) - return nullptr; - - QueryInfo info(query, type); - info.m_query_time = std::make_shared(); - metrics->add_query(info); - - return std::make_unique(info.m_query_time); -#else - static_cast(query); - static_cast(type); - return nullptr; -#endif -} - -QueryInfo::QueryType QueryInfo::type_from_action(Action action) -{ - switch (action) { - case act_ReturnFirst: - return type_Find; - case act_Sum: - return type_Sum; - case act_Max: - return type_Maximum; - case act_Min: - return type_Minimum; - case act_Average: - return type_Average; - case act_Count: - return type_Count; - case act_FindAll: - return type_FindAll; - case act_CallbackIdx: - return type_Invalid; - }; - REALM_UNREACHABLE(); -} diff --git a/src/realm/metrics/query_info.hpp b/src/realm/metrics/query_info.hpp deleted file mode 100644 index 1334a076880..00000000000 --- a/src/realm/metrics/query_info.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - **************************************************************************/ - -#ifndef REALM_QUERY_INFO_HPP -#define REALM_QUERY_INFO_HPP - -#include -#include - -#include -#include -#include - -namespace realm { - -class Query; // forward declare in namespace realm - -namespace metrics { - -class QueryInfo { -public: - enum QueryType { - type_Find, - type_FindAll, - type_Count, - type_Sum, - type_Average, - type_Maximum, - type_Minimum, - type_Invalid - }; - - QueryInfo(const Query* query, QueryType type); - ~QueryInfo() noexcept; - - std::string get_description() const; - std::string get_table_name() const; - QueryType get_type() const; - nanosecond_storage_t get_query_time_nanoseconds() const; - - static std::unique_ptr track(const Query* query, QueryType type); - static QueryType type_from_action(Action action); - -private: - std::string m_description; - std::string m_table_name; - QueryType m_type; - std::shared_ptr m_query_time; -}; - -} // namespace metrics -} // namespace realm - -#endif // REALM_QUERY_INFO_HPP diff --git a/src/realm/metrics/transaction_info.cpp b/src/realm/metrics/transaction_info.cpp deleted file mode 100644 index 6221a583eb0..00000000000 --- a/src/realm/metrics/transaction_info.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - **************************************************************************/ - -#include - -using namespace realm; -using namespace metrics; - -TransactionInfo::TransactionInfo(TransactionInfo::TransactionType type) - : m_realm_disk_size(0) - , m_realm_free_space(0) - , m_total_objects(0) - , m_type(type) - , m_num_versions(0) - , m_num_decrypted_pages(0) -{ -#if REALM_METRICS - if (m_type == write_transaction) { - m_fsync_time = std::make_shared(); - m_write_time = std::make_shared(); - } -#endif -} - -TransactionInfo::~TransactionInfo() noexcept -{ -} - -TransactionInfo::TransactionType TransactionInfo::get_transaction_type() const -{ - return m_type; -} - -nanosecond_storage_t TransactionInfo::get_transaction_time_nanoseconds() const -{ - return m_transaction_time.get_elapsed_nanoseconds(); -} - -nanosecond_storage_t TransactionInfo::get_fsync_time_nanoseconds() const -{ - if (m_fsync_time) { - return m_fsync_time->get_elapsed_nanoseconds(); - } - return 0; -} - -nanosecond_storage_t TransactionInfo::get_write_time_nanoseconds() const -{ - if (m_write_time) { - return m_write_time->get_elapsed_nanoseconds(); - } - return 0; -} - -size_t TransactionInfo::get_disk_size() const -{ - return m_realm_disk_size; -} - -size_t TransactionInfo::get_free_space() const -{ - return m_realm_free_space; -} - -size_t TransactionInfo::get_total_objects() const -{ - return m_total_objects; -} - -size_t TransactionInfo::get_num_available_versions() const -{ - return m_num_versions; -} - -size_t TransactionInfo::get_num_decrypted_pages() const -{ - return m_num_decrypted_pages; -} - -void TransactionInfo::update_stats(size_t disk_size, size_t free_space, size_t total_objects, - size_t available_versions, size_t num_decrypted_pages) -{ - m_realm_disk_size = disk_size; - m_realm_free_space = free_space; - m_total_objects = total_objects; - m_num_versions = available_versions; - m_num_decrypted_pages = num_decrypted_pages; -} - -void TransactionInfo::finish_timer() -{ - m_transaction_time.report_nanoseconds(m_transact_timer.get_elapsed_nanoseconds()); -} diff --git a/src/realm/metrics/transaction_info.hpp b/src/realm/metrics/transaction_info.hpp deleted file mode 100644 index 2706024a192..00000000000 --- a/src/realm/metrics/transaction_info.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - **************************************************************************/ - -#ifndef REALM_TRANSACTION_INFO_HPP -#define REALM_TRANSACTION_INFO_HPP - -#include -#include - -#include -#include - -namespace realm { -namespace metrics { - -class Metrics; - -class TransactionInfo { -public: - enum TransactionType { read_transaction, write_transaction }; - TransactionInfo(TransactionType type); - TransactionInfo(const TransactionInfo&) = default; - ~TransactionInfo() noexcept; - - TransactionType get_transaction_type() const; - // the transaction time is a total amount which includes fsync_time + write_time + user_time - nanosecond_storage_t get_transaction_time_nanoseconds() const; - nanosecond_storage_t get_fsync_time_nanoseconds() const; - nanosecond_storage_t get_write_time_nanoseconds() const; - size_t get_disk_size() const; - size_t get_free_space() const; - size_t get_total_objects() const; - size_t get_num_available_versions() const; - size_t get_num_decrypted_pages() const; - -private: - MetricTimerResult m_transaction_time; - std::shared_ptr m_fsync_time; - std::shared_ptr m_write_time; - MetricTimer m_transact_timer; - - size_t m_realm_disk_size; - size_t m_realm_free_space; - size_t m_total_objects; - TransactionType m_type; - size_t m_num_versions; - size_t m_num_decrypted_pages; - - friend class Metrics; - void update_stats(size_t disk_size, size_t free_space, size_t total_objects, size_t available_versions, - size_t num_decrypted_pages); - void finish_timer(); -}; - -} // namespace metrics -} // namespace realm - -#endif // REALM_TRANSACTION_INFO_HPP diff --git a/src/realm/query.cpp b/src/realm/query.cpp index 029010f3290..84a43189919 100644 --- a/src/realm/query.cpp +++ b/src/realm/query.cpp @@ -31,7 +31,6 @@ #include using namespace realm; -using namespace realm::metrics; Query::Query() { @@ -1105,33 +1104,21 @@ void Query::aggregate_internal(ParentNode* pn, QueryStateBase* st, size_t start, std::optional Query::sum(ColKey col_key) const { -#if REALM_METRICS - auto metric_timer = QueryInfo::track(this, QueryInfo::type_Sum); -#endif return AggregateHelper::sum(*m_table, *this, col_key); } std::optional Query::avg(ColKey col_key, size_t* value_count) const { -#if REALM_METRICS - auto metric_timer = QueryInfo::track(this, QueryInfo::type_Average); -#endif return AggregateHelper::avg(*m_table, *this, col_key, value_count); } std::optional Query::min(ColKey col_key, ObjKey* return_ndx) const { -#if REALM_METRICS - auto metric_timer = QueryInfo::track(this, QueryInfo::type_Minimum); -#endif return AggregateHelper::min(*m_table, *this, col_key, return_ndx); } std::optional Query::max(ColKey col_key, ObjKey* return_ndx) const { -#if REALM_METRICS - auto metric_timer = QueryInfo::track(this, QueryInfo::type_Maximum); -#endif return AggregateHelper::max(*m_table, *this, col_key, return_ndx); } @@ -1207,10 +1194,6 @@ ObjKey Query::find() const if (!m_table) return ret; -#if REALM_METRICS - std::unique_ptr metric_timer = QueryInfo::track(this, QueryInfo::type_Find); -#endif - auto logger = m_table->get_logger(); bool do_log = false; std::chrono::steady_clock::time_point t1; @@ -1392,10 +1375,6 @@ void Query::do_find_all(QueryStateBase& st) const TableView Query::find_all(size_t limit) const { -#if REALM_METRICS - std::unique_ptr metric_timer = QueryInfo::track(this, QueryInfo::type_FindAll); -#endif - TableView ret(*this, limit); if (m_ordering) { // apply_descriptor_ordering will call do_sync @@ -1515,9 +1494,6 @@ size_t Query::do_count(size_t limit) const size_t Query::count() const { -#if REALM_METRICS - std::unique_ptr metric_timer = QueryInfo::track(this, QueryInfo::type_Count); -#endif if (!m_table) return 0; return do_count(); @@ -1525,9 +1501,6 @@ size_t Query::count() const TableView Query::find_all(const DescriptorOrdering& descriptor) const { -#if REALM_METRICS - std::unique_ptr metric_timer = QueryInfo::track(this, QueryInfo::type_FindAll); -#endif if (descriptor.is_empty()) { return find_all(); } @@ -1558,9 +1531,6 @@ TableView Query::find_all(const DescriptorOrdering& descriptor) const size_t Query::count(const DescriptorOrdering& descriptor) const { -#if REALM_METRICS - std::unique_ptr metric_timer = QueryInfo::track(this, QueryInfo::type_Count); -#endif if (!m_table) return 0; realm::util::Optional min_limit = descriptor.get_min_limit(); diff --git a/src/realm/query.hpp b/src/realm/query.hpp index 0ed4330c7e9..cb89b22c2f6 100644 --- a/src/realm/query.hpp +++ b/src/realm/query.hpp @@ -57,10 +57,6 @@ class TableView; class Timestamp; class Transaction; -namespace metrics { -class QueryInfo; -} - struct QueryGroup { enum class State { Default, @@ -379,7 +375,6 @@ class Query final { friend class TableView; friend class SubQueryCount; friend class PrimitiveListCount; - friend class metrics::QueryInfo; template friend class AggregateHelper; diff --git a/src/realm/query_engine.hpp b/src/realm/query_engine.hpp index 33e0dcb75ef..998132eeea5 100644 --- a/src/realm/query_engine.hpp +++ b/src/realm/query_engine.hpp @@ -85,7 +85,6 @@ TConditionValue: Type of values in condition column. That is, int64_t, float, #include #include #include -#include #include #include #include diff --git a/src/realm/query_expression.hpp b/src/realm/query_expression.hpp index 6832c4a868e..b1e70c65123 100644 --- a/src/realm/query_expression.hpp +++ b/src/realm/query_expression.hpp @@ -148,7 +148,6 @@ The Columns class encapsulates all this into a simple class that, for any type T #include #include #include -#include #include #include diff --git a/src/realm/table.hpp b/src/realm/table.hpp index a8dfc50d490..769ea29959b 100644 --- a/src/realm/table.hpp +++ b/src/realm/table.hpp @@ -73,9 +73,6 @@ class TableFriend; namespace util { class Logger; } -namespace metrics { -class QueryInfo; -} namespace query_parser { class Arguments; class KeyPathMapping; @@ -851,7 +848,6 @@ class Table { friend class _impl::TableFriend; friend class Query; - friend class metrics::QueryInfo; template friend class SimpleQuerySupport; friend class TableView; diff --git a/src/realm/transaction.cpp b/src/realm/transaction.cpp index f45cf438951..0cefaba0b91 100644 --- a/src/realm/transaction.cpp +++ b/src/realm/transaction.cpp @@ -118,7 +118,6 @@ Transaction::Transaction(DBRef _db, SlabAlloc* alloc, DB::ReadLockInfo& rli, DB: { bool writable = stage == DB::transact_Writing; m_transact_stage = DB::transact_Ready; - set_metrics(db->m_metrics); set_transact_stage(stage); m_alloc.note_reader_start(this); attach_shared(m_read_lock.m_top_ref, m_read_lock.m_file_size, writable, @@ -928,41 +927,6 @@ void Transaction::initialize_replication() void Transaction::set_transact_stage(DB::TransactStage stage) noexcept { -#if REALM_METRICS - REALM_ASSERT(m_metrics == db->m_metrics); - if (m_metrics) { // null if metrics are disabled - size_t free_space; - size_t used_space; - db->get_stats(free_space, used_space); - size_t total_size = used_space + free_space; - - size_t num_objects = m_total_rows; - size_t num_available_versions = static_cast(db->get_number_of_versions()); - size_t num_decrypted_pages = realm::util::get_num_decrypted_pages(); - - if (stage == DB::transact_Reading) { - if (m_transact_stage == DB::transact_Writing) { - m_metrics->end_write_transaction(total_size, free_space, num_objects, num_available_versions, - num_decrypted_pages); - } - m_metrics->start_read_transaction(); - } - else if (stage == DB::transact_Writing) { - if (m_transact_stage == DB::transact_Reading) { - m_metrics->end_read_transaction(total_size, free_space, num_objects, num_available_versions, - num_decrypted_pages); - } - m_metrics->start_write_transaction(); - } - else if (stage == DB::transact_Ready) { - m_metrics->end_read_transaction(total_size, free_space, num_objects, num_available_versions, - num_decrypted_pages); - m_metrics->end_write_transaction(total_size, free_space, num_objects, num_available_versions, - num_decrypted_pages); - } - } -#endif - m_transact_stage = stage; } diff --git a/src/realm/util/config.h.in b/src/realm/util/config.h.in index 8b423306e55..c9efb97cb97 100644 --- a/src/realm/util/config.h.in +++ b/src/realm/util/config.h.in @@ -13,6 +13,5 @@ #cmakedefine01 REALM_ENABLE_MEMDEBUG #cmakedefine01 REALM_ENABLE_GEOSPATIAL #cmakedefine01 REALM_VALGRIND -#cmakedefine01 REALM_METRICS #cmakedefine01 REALM_ASAN #cmakedefine01 REALM_TSAN diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a0ab739161f..7e524e298b0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -53,7 +53,6 @@ set(CORE_TEST_SOURCES test_json.cpp test_link_query_view.cpp test_links.cpp - test_metrics.cpp test_mixed_null_assertions.cpp test_object_id.cpp test_optional.cpp diff --git a/test/test_metrics.cpp b/test/test_metrics.cpp deleted file mode 100644 index 7fea9f9b511..00000000000 --- a/test/test_metrics.cpp +++ /dev/null @@ -1,1207 +0,0 @@ -/************************************************************************* - * - * Copyright 2016 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - **************************************************************************/ - -#include "testsettings.hpp" - -#if defined(TEST_METRICS) -#include "test.hpp" - - -// Test independence and thread-safety -// ----------------------------------- -// -// All tests must be thread safe and independent of each other. This -// is required because it allows for both shuffling of the execution -// order and for parallelized testing. -// -// In particular, avoid using std::rand() since it is not guaranteed -// to be thread safe. Instead use the API offered in -// `test/util/random.hpp`. -// -// All files created in tests must use the TEST_PATH macro (or one of -// its friends) to obtain a suitable file system path. See -// `test/util/test_path.hpp`. -// -// -// Debugging and the ONLY() macro -// ------------------------------ -// -// A simple way of disabling all tests except one called `Foo`, is to -// replace TEST(Foo) with ONLY(Foo) and then recompile and rerun the -// test suite. Note that you can also use filtering by setting the -// environment varible `UNITTEST_FILTER`. See `README.md` for more on -// this. -// -// Another way to debug a particular test, is to copy that test into -// `experiments/testcase.cpp` and then run `sh build.sh -// check-testcase` (or one of its friends) from the command line. - -#include -#include - -using namespace realm; -using namespace realm::metrics; -using namespace realm::test_util; -using namespace realm::util; - -#if REALM_METRICS - -#include -#include -#include - -#include -#include -#include -#include -#include - - -TEST(Metrics_HasNoReportsWhenDisabled) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = false; - DBRef sg = DB::create(*hist, path, options); - CHECK(!sg->get_metrics()); - auto wt = sg->start_write(); - auto table = wt->add_table("table"); - auto col = table->add_column(type_Int, "first"); - std::vector keys; - table->create_objects(10, keys); - wt->commit(); - auto rt = sg->start_read(); - table = rt->get_table("table"); - CHECK(bool(table)); - Query query = table->column(col) == 0; - query.count(); - rt->end_read(); - CHECK(!sg->get_metrics()); -} - -TEST(Metrics_HasReportsWhenEnabled) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - DBRef sg = DB::create(*hist, path, options); - CHECK(sg->get_metrics()); - auto wt = sg->start_write(); - auto table = wt->add_table("table"); - auto col = table->add_column(type_Int, "first"); - std::vector keys; - table->create_objects(10, keys); - wt->commit(); - auto rt = sg->start_read(); - table = rt->get_table("table"); - CHECK(bool(table)); - Query query = table->column(col) == 0; - query.count(); - rt->end_read(); - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - CHECK(metrics->num_query_metrics() != 0); - CHECK(metrics->num_transaction_metrics() != 0); -} - -TEST(Metrics_QueryTypes) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - DBRef sg = DB::create(*hist, path, options); - CHECK(sg->get_metrics()); - auto wt = sg->start_write(); - auto table = wt->add_table("table"); - auto int_col = table->add_column(type_Int, "col_int"); - auto double_col = table->add_column(type_Double, "col_double"); - auto float_col = table->add_column(type_Float, "col_float"); - auto timestamp_col = table->add_column(type_Timestamp, "col_timestamp"); - std::vector keys; - table->create_objects(10, keys); - wt->commit(); - auto rt = sg->start_read(); - table = rt->get_table("table"); - CHECK(bool(table)); - Query query = table->column(int_col) == 0; - query.find(); - query.find_all(); - query.count(); - query.sum(int_col); - query.avg(int_col); - query.max(int_col); - query.min(int_col); - - query.sum(double_col); - query.avg(double_col); - query.max(double_col); - query.min(double_col); - - query.sum(float_col); - query.avg(float_col); - query.max(float_col); - query.min(float_col); - - ObjKey return_dummy; - query.max(timestamp_col, &return_dummy); - query.min(timestamp_col, &return_dummy); - - rt->end_read(); - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - CHECK_EQUAL(metrics->num_query_metrics(), 17); - std::unique_ptr queries = metrics->take_queries(); - CHECK_EQUAL(metrics->num_query_metrics(), 0); - CHECK(queries); - CHECK_EQUAL(queries->size(), 17); - CHECK_EQUAL(queries->at(0).get_type(), QueryInfo::type_Find); - CHECK_EQUAL(queries->at(1).get_type(), QueryInfo::type_FindAll); - CHECK_EQUAL(queries->at(2).get_type(), QueryInfo::type_Count); - CHECK_EQUAL(queries->at(3).get_type(), QueryInfo::type_Sum); - CHECK_EQUAL(queries->at(4).get_type(), QueryInfo::type_Average); - CHECK_EQUAL(queries->at(5).get_type(), QueryInfo::type_Maximum); - CHECK_EQUAL(queries->at(6).get_type(), QueryInfo::type_Minimum); - - CHECK_EQUAL(queries->at(7).get_type(), QueryInfo::type_Sum); - CHECK_EQUAL(queries->at(8).get_type(), QueryInfo::type_Average); - CHECK_EQUAL(queries->at(9).get_type(), QueryInfo::type_Maximum); - CHECK_EQUAL(queries->at(10).get_type(), QueryInfo::type_Minimum); - - CHECK_EQUAL(queries->at(11).get_type(), QueryInfo::type_Sum); - CHECK_EQUAL(queries->at(12).get_type(), QueryInfo::type_Average); - CHECK_EQUAL(queries->at(13).get_type(), QueryInfo::type_Maximum); - CHECK_EQUAL(queries->at(14).get_type(), QueryInfo::type_Minimum); - - CHECK_EQUAL(queries->at(15).get_type(), QueryInfo::type_Maximum); - CHECK_EQUAL(queries->at(16).get_type(), QueryInfo::type_Minimum); -} - -static size_t find_count(std::string haystack, std::string needle) -{ - size_t find_pos = 0; - size_t count = 0; - while (find_pos < haystack.size()) { - find_pos = haystack.find(needle, find_pos); - if (find_pos == std::string::npos) - break; - ++find_pos; - ++count; - } - return count; -} - -static void populate(DBRef sg) -{ - auto wt = sg->start_write(); - auto person = wt->add_table("person"); - auto pet = wt->add_table("pet"); - person->add_column(type_Int, "age"); - person->add_column(type_Double, "paid"); - person->add_column(type_Float, "weight"); - person->add_column(type_Timestamp, "date_of_birth"); - person->add_column(type_String, "name"); - person->add_column(type_Bool, "account_overdue"); - person->add_column(type_Binary, "data"); - auto owes_col = person->add_column_list(*person, "owes_coffee_to"); - - auto create_person = [&](int age, double paid, float weight, Timestamp dob, std::string name, bool overdue, - std::string data, std::vector owes_coffee_to) { - BinaryData bd(data); - Obj obj = person->create_object().set_all(age, paid, weight, dob, name, overdue, bd); - auto ll = obj.get_linklist(owes_col); - for (auto key : owes_coffee_to) { - ll.add(key); - } - return obj.get_key(); - }; - - auto k0 = create_person(27, 28.80, 170.7f, Timestamp(27, 5), "Bob", true, "e72s", {}); - auto k1 = create_person(28, 10.70, 165.8f, Timestamp(28, 8), "Ryan", false, "s83f", {k0}); - auto k2 = create_person(33, 55.28, 183.3f, Timestamp(33, 3), "Cole", true, "s822k", {k1, k0}); - auto k3 = create_person(39, 22.72, 173.8f, Timestamp(39, 2), "Nathan", true, "h282l", {k1, k1, k0, k2}); - create_person(33, 29.28, 188.7f, Timestamp(33, 9), "Riley", false, "a208s", {k3, k3, k2, k1}); - - pet->add_column(type_String, "name"); - pet->add_column(*person, "owner"); - - auto create_pet = [&](std::string name, ObjKey owner) { - pet->create_object().set_all(name, owner); - }; - - create_pet("Fido", k0); - create_pet("Max", k1); - create_pet("Buddy", k2); - create_pet("Rocky", k3); - create_pet("Toby", k3); - create_pet("Duke", k0); - - wt->commit(); -} - -TEST(Metrics_QueryEqual) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - DBRef sg = DB::create(*hist, path, options); - populate(sg); - - std::string person_table_name = "person"; - std::string pet_table_name = "pet"; - std::string query_search_term = "=="; - - auto wt = sg->start_write(); - TableRef person = wt->get_table(person_table_name); - TableRef pet = wt->get_table(pet_table_name); - CHECK(bool(person)); - - CHECK_EQUAL(person->get_column_count(), 8); - std::vector column_names; - for (auto col : person->get_column_keys()) { - column_names.push_back(person->get_column_name(col)); - } - for (auto col : pet->get_column_keys()) { - column_names.push_back(pet->get_column_name(col)); - } - - Obj p0 = person->get_object(0); - - auto col_age = person->get_column_key("age"); - auto col_paid = person->get_column_key("paid"); - auto col_weight = person->get_column_key("weight"); - auto col_birth = person->get_column_key("date_of_birth"); - auto col_name = person->get_column_key("name"); - auto col_overdue = person->get_column_key("account_overdue"); - auto col_data = person->get_column_key("data"); - auto col_owes = person->get_column_key("owes_coffee_to"); - - auto col_pet_name = pet->get_column_key("name"); - auto col_owner = pet->get_column_key("owner"); - - Query q0 = person->column(col_age) == 0; - Query q1 = person->column(col_paid) == 0.0; - Query q2 = person->column(col_weight) == 0.0f; - Query q3 = person->column(col_birth) == Timestamp(0, 0); - StringData name(""); - Query q4 = person->column(col_name) == name; - Query q5 = person->column(col_overdue) == false; - BinaryData bd(""); - Query q6 = person->column(col_data) == bd; - Query q7 = person->column(col_owes) == p0; - Query q8 = pet->column(col_pet_name) == name; - Query q9 = pet->column(col_owner) == p0; - - q0.find_all(); - q1.find_all(); - q2.find_all(); - q3.find_all(); - q4.find_all(); - q5.find_all(); - q6.find_all(); - q7.find_all(); - q8.find_all(); - q9.find_all(); - - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - std::unique_ptr queries = metrics->take_queries(); - CHECK(queries); - CHECK_EQUAL(queries->size(), 10); - - for (size_t i = 0; i < 10; ++i) { - std::string description = queries->at(i).get_description(); - std::string table_name = queries->at(i).get_table_name(); - CHECK_EQUAL(find_count(description, column_names[i]), 1); - CHECK_GREATER_EQUAL(find_count(description, query_search_term), 1); - if (i < 8) { - CHECK_EQUAL(table_name, "person"); - } - else { - CHECK_EQUAL(table_name, "pet"); - } - } -} - -TEST(Metrics_QueryOrAndNot) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - DBRef sg = DB::create(*hist, path, options); - populate(sg); - - std::string person_table_name = "person"; - std::string pet_table_name = "pet"; - std::string query_search_term = "=="; - std::string not_text = "!"; - - auto wt = sg->start_write(); - TableRef person = wt->get_table(person_table_name); - wt->get_table(pet_table_name); - CHECK(bool(person)); - - CHECK_EQUAL(person->get_column_count(), 8); - std::vector column_names; - for (auto col : person->get_column_keys()) { - column_names.push_back(person->get_column_name(col)); - } - - auto col_age = person->get_column_key("age"); - auto col_paid = person->get_column_key("paid"); - auto col_weight = person->get_column_key("weight"); - Query q0 = person->column(col_age) == 0; - Query q1 = person->column(col_paid) == 0.0; - Query q2 = person->column(col_weight) == 0.1f; - - Query simple_and = q0 && q1; - Query simple_or = q0 || q1; - Query simple_not = !q0; - - Query or_and = q2 || (simple_and); - Query and_or = simple_and || q2; - Query or_nested = q2 || simple_or; - Query and_nested = q2 && simple_and; - Query not_simple_and = !(simple_and); - Query not_simple_or = !(simple_or); - Query not_or_and = !(or_and); - Query not_and_or = !(and_or); - Query not_or_nested = !(or_nested); - Query not_and_nested = !(and_nested); - Query and_true = q0 && std::unique_ptr(new TrueExpression); - Query and_false = q0 && std::unique_ptr(new FalseExpression); - - simple_and.find_all(); - simple_or.find_all(); - simple_not.find_all(); - or_and.find_all(); - and_or.find_all(); - or_nested.find_all(); - and_nested.find_all(); - not_simple_and.find_all(); - not_simple_or.find_all(); - not_or_and.find_all(); - not_and_or.find_all(); - not_or_nested.find_all(); - not_and_nested.find_all(); - and_true.find_all(); - and_false.find_all(); - - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - std::unique_ptr queries = metrics->take_queries(); - CHECK(queries); - CHECK_EQUAL(queries->size(), 15); - - std::string and_description = queries->at(0).get_description(); - CHECK_EQUAL(find_count(and_description, " and "), 1); - CHECK_EQUAL(find_count(and_description, column_names[0]), 1); - CHECK_EQUAL(find_count(and_description, column_names[1]), 1); - CHECK_EQUAL(find_count(and_description, query_search_term), 2); - - std::string or_description = queries->at(1).get_description(); - CHECK_EQUAL(find_count(or_description, " or "), 1); - CHECK_EQUAL(find_count(or_description, column_names[0]), 1); - CHECK_EQUAL(find_count(or_description, column_names[1]), 1); - CHECK_EQUAL(find_count(or_description, query_search_term), 2); - - std::string not_description = queries->at(2).get_description(); - CHECK_EQUAL(find_count(not_description, not_text), 1); - CHECK_EQUAL(find_count(not_description, column_names[0]), 1); - CHECK_EQUAL(find_count(not_description, query_search_term), 1); - - std::string or_and_description = queries->at(3).get_description(); - CHECK_EQUAL(find_count(or_and_description, and_description), 1); - CHECK_EQUAL(find_count(or_and_description, " or "), 1); - CHECK_EQUAL(find_count(or_and_description, column_names[2]), 1); - - std::string and_or_description = queries->at(4).get_description(); - CHECK_EQUAL(find_count(and_or_description, and_description), 1); - CHECK_EQUAL(find_count(and_or_description, " or "), 1); - CHECK_EQUAL(find_count(and_or_description, column_names[2]), 1); - - std::string or_nested_description = queries->at(5).get_description(); - CHECK_EQUAL(find_count(or_nested_description, or_description), 1); - CHECK_EQUAL(find_count(or_nested_description, " or "), 2); - CHECK_EQUAL(find_count(or_nested_description, column_names[2]), 1); - - std::string and_nested_description = queries->at(6).get_description(); - CHECK_EQUAL(find_count(and_nested_description, and_description), 1); - CHECK_EQUAL(find_count(and_nested_description, " and "), 2); - CHECK_EQUAL(find_count(and_nested_description, column_names[2]), 1); - - std::string not_simple_and_description = queries->at(7).get_description(); - CHECK_EQUAL(find_count(not_simple_and_description, and_description), 1); - CHECK_EQUAL(find_count(not_simple_and_description, not_text), 1); - - std::string not_simple_or_description = queries->at(8).get_description(); - CHECK_EQUAL(find_count(not_simple_or_description, or_description), 1); - CHECK_EQUAL(find_count(not_simple_or_description, not_text), 1); - - std::string not_or_and_description = queries->at(9).get_description(); - CHECK_EQUAL(find_count(not_or_and_description, or_and_description), 1); - CHECK_EQUAL(find_count(not_or_and_description, not_text), 1); - - std::string not_and_or_description = queries->at(10).get_description(); - CHECK_EQUAL(find_count(not_and_or_description, and_or_description), 1); - CHECK_EQUAL(find_count(not_and_or_description, not_text), 1); - - std::string not_or_nested_description = queries->at(11).get_description(); - CHECK_EQUAL(find_count(not_or_nested_description, or_nested_description), 1); - CHECK_EQUAL(find_count(not_or_nested_description, not_text), 1); - - std::string not_and_nested_description = queries->at(12).get_description(); - CHECK_EQUAL(find_count(not_and_nested_description, and_nested_description), 1); - CHECK_EQUAL(find_count(not_and_nested_description, not_text), 1); - - std::string and_true_description = queries->at(13).get_description(); - CHECK_EQUAL(find_count(and_true_description, "and"), 1); - CHECK_EQUAL(find_count(and_true_description, "TRUEPREDICATE"), 1); - - std::string and_false_description = queries->at(14).get_description(); - CHECK_EQUAL(find_count(and_false_description, "and"), 1); - CHECK_EQUAL(find_count(and_false_description, "FALSEPREDICATE"), 1); -} - - -TEST(Metrics_LinkQueries) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - DBRef sg = DB::create(*hist, path, options); - populate(sg); - - std::string person_table_name = "person"; - std::string pet_table_name = "pet"; - - auto wt = sg->start_write(); - TableRef person = wt->get_table(person_table_name); - TableRef pet = wt->get_table(pet_table_name); - CHECK(bool(person)); - - CHECK_EQUAL(person->get_column_count(), 8); - std::vector column_names; - for (auto col : person->get_column_keys()) { - column_names.push_back(person->get_column_name(col)); - } - - std::string pet_link_col_name = "owner"; - ColKey col_owner = pet->get_column_key(pet_link_col_name); - auto col_age = person->get_column_key("age"); - - Query q0 = pet->column(col_owner).is_null(); - Query q1 = pet->column(col_owner).is_not_null(); - Query q2 = pet->column(col_owner).count() == 1; - Query q3 = pet->column(col_owner, person->column(col_age) >= 27).count() == 1; - - q0.find_all(); - q1.find_all(); - q2.find_all(); - q3.find_all(); - - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - std::unique_ptr queries = metrics->take_queries(); - CHECK(queries); - - CHECK_EQUAL(queries->size(), 4); - - std::string null_links_description = queries->at(0).get_description(); - CHECK_EQUAL(find_count(null_links_description, "NULL"), 1); - CHECK_EQUAL(find_count(null_links_description, pet_link_col_name), 1); - - std::string not_null_links_description = queries->at(1).get_description(); - CHECK_EQUAL(find_count(not_null_links_description, "NULL"), 1); - CHECK_EQUAL(find_count(not_null_links_description, "!"), 1); - CHECK_EQUAL(find_count(not_null_links_description, pet_link_col_name), 1); - - std::string count_link_description = queries->at(2).get_description(); - CHECK_EQUAL(find_count(count_link_description, "@count"), 1); - CHECK_EQUAL(find_count(count_link_description, pet_link_col_name), 1); - CHECK_EQUAL(find_count(count_link_description, "=="), 1); - - std::string link_subquery_description = queries->at(3).get_description(); - CHECK_EQUAL(find_count(link_subquery_description, "@count"), 1); - CHECK_EQUAL(find_count(link_subquery_description, pet_link_col_name), 1); - CHECK_EQUAL(find_count(link_subquery_description, "=="), 1); - CHECK_EQUAL(find_count(link_subquery_description, column_names[0]), 1); - CHECK_EQUAL(find_count(link_subquery_description, ">"), 1); -} - - -TEST(Metrics_LinkListQueries) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - DBRef sg = DB::create(*hist, path, options); - populate(sg); - - std::string person_table_name = "person"; - std::string pet_table_name = "pet"; - - auto wt = sg->start_write(); - TableRef person = wt->get_table(person_table_name); - wt->get_table(pet_table_name); - CHECK(bool(person)); - - CHECK_EQUAL(person->get_column_count(), 8); - std::map column_names; - for (auto col : person->get_column_keys()) { - column_names[col] = person->get_column_name(col); - } - - Obj p0 = person->get_object(0); - - ColKey ll_col_key = person->get_column_key("owes_coffee_to"); - auto col_name = person->get_column_key("name"); - auto col_paid = person->get_column_key("paid"); - - Query q0 = person->column(ll_col_key).is_null(); - Query q1 = person->column(ll_col_key).is_not_null(); - Query q2 = person->column(ll_col_key).count() == 1; - Query q3 = person->column(ll_col_key) == p0; - Query q4 = person->column(ll_col_key).column(col_paid).sum() >= 1; - Query q5 = person->column(ll_col_key, person->column(col_name) == "Bob").count() == 1; - - q0.find_all(); - q1.find_all(); - q2.find_all(); - q3.find_all(); - q4.find_all(); - q5.find_all(); - - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - std::unique_ptr queries = metrics->take_queries(); - CHECK(queries); - - CHECK_EQUAL(queries->size(), 6); - - std::string null_links_description = queries->at(0).get_description(); - CHECK_EQUAL(find_count(null_links_description, "NULL"), 1); - CHECK_EQUAL(find_count(null_links_description, column_names[ll_col_key]), 1); - - std::string not_null_links_description = queries->at(1).get_description(); - CHECK_EQUAL(find_count(not_null_links_description, "NULL"), 1); - CHECK_EQUAL(find_count(not_null_links_description, "!"), 1); - CHECK_EQUAL(find_count(not_null_links_description, column_names[ll_col_key]), 1); - - std::string count_link_description = queries->at(2).get_description(); - CHECK_EQUAL(find_count(count_link_description, "@count"), 1); - CHECK_EQUAL(find_count(count_link_description, column_names[ll_col_key]), 1); - CHECK_EQUAL(find_count(count_link_description, "=="), 1); - - std::string links_description = queries->at(3).get_description(); - CHECK_EQUAL(find_count(links_description, "L0:0"), 1); - CHECK_EQUAL(find_count(links_description, column_names[ll_col_key]), 1); - CHECK_EQUAL(find_count(links_description, "=="), 1); - - std::string sum_link_description = queries->at(4).get_description(); - CHECK_EQUAL(find_count(sum_link_description, "@sum"), 1); - CHECK_EQUAL(find_count(sum_link_description, column_names[ll_col_key]), 1); - CHECK_EQUAL(find_count(sum_link_description, column_names[col_paid]), 1); - // the query system can choose to flip the argument order and operators so that >= might be <= - CHECK_EQUAL(find_count(sum_link_description, "<=") + find_count(sum_link_description, ">="), 1); - - std::string link_subquery_description = queries->at(5).get_description(); - CHECK_EQUAL(find_count(link_subquery_description, "@count"), 1); - CHECK_EQUAL(find_count(link_subquery_description, column_names[ll_col_key]), 1); - CHECK_EQUAL(find_count(link_subquery_description, "=="), 2); - CHECK_EQUAL(find_count(link_subquery_description, column_names[col_name]), 1); -} - - -TEST(Metrics_SubQueries) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - DBRef sg = DB::create(*hist, path, options); - - auto wt = sg->start_write(); - - std::string table_name = "table"; - std::string int_col_name = "integers"; - std::string str_col_name = "strings"; - - TableRef table = wt->add_table(table_name); - - auto col_list_int = table->add_column_list(type_Int, int_col_name); - auto col_list_string = table->add_column_list(type_String, str_col_name, true); - auto col_other = table->add_column(type_String, "other"); - - std::vector keys; - table->create_objects(4, keys); - - // see Query_SubtableExpression - auto set_int_list = [](LstPtr list, const std::vector& value_list) { - list->clear(); - for (auto i : value_list) { - list->add(i); - } - }; - auto set_string_list = [](LstPtr list, const std::vector& value_list) { - list->clear(); - for (auto i : value_list) { - if (i < 100) { - std::string str("Str_"); - str += util::to_string(i); - list->add(StringData(str)); - } - else { - list->add(StringData()); - } - } - }; - set_int_list(table->get_object(keys[0]).get_list_ptr(col_list_int), std::vector({0, 1})); - set_int_list(table->get_object(keys[1]).get_list_ptr(col_list_int), std::vector({2, 3, 4, 5})); - set_int_list(table->get_object(keys[2]).get_list_ptr(col_list_int), std::vector({6, 7, 8, 9})); - set_int_list(table->get_object(keys[3]).get_list_ptr(col_list_int), std::vector({})); - - set_string_list(table->get_object(keys[0]).get_list_ptr(col_list_string), std::vector({0, 1})); - set_string_list(table->get_object(keys[1]).get_list_ptr(col_list_string), std::vector({2, 3, 4, 5})); - set_string_list(table->get_object(keys[2]).get_list_ptr(col_list_string), - std::vector({6, 7, 100, 8, 9})); - table->get_object(keys[0]).set(col_other, StringData("foo")); - table->get_object(keys[1]).set(col_other, StringData("str")); - table->get_object(keys[2]).set(col_other, StringData("str_9_baa")); - - Query q0 = table->column>(col_list_int) == 10; - Query q1 = table->column>(col_list_int).max() > 5; - Query q2 = table->column>(col_list_string).begins_with("Str"); - Query q3 = table->column>(col_list_string) == "Str_0"; - - q0.find_all(); - q1.find_all(); - q2.find_all(); - q3.find_all(); - - wt->commit(); - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - std::unique_ptr queries = metrics->take_queries(); - CHECK(queries); - - CHECK_EQUAL(queries->size(), 4); - - std::string int_equal_description = queries->at(0).get_description(); - CHECK_EQUAL(int_equal_description, "10 == integers"); - - std::string int_max_description = queries->at(1).get_description(); - CHECK_EQUAL(int_max_description, "5 < integers.@max"); - - std::string str_begins_description = queries->at(2).get_description(); - CHECK_EQUAL(str_begins_description, "strings BEGINSWITH \"Str\""); - - std::string str_equal_description = queries->at(3).get_description(); - CHECK_EQUAL(str_equal_description, "\"Str_0\" == strings"); -} - -NONCONCURRENT_TEST(Metrics_TransactionTimings) -{ - ColKey col; - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - DBRef sg = DB::create(*hist, path, options); - CHECK(sg->get_metrics()); - { - auto wt = sg->start_write(); - auto table = wt->add_table("table"); - col = table->add_column(type_Int, "first"); - std::vector keys; - table->create_objects(10, keys); - wt->commit(); - } - { - auto rt = sg->start_read(); - auto table = rt->get_table("table"); - CHECK(bool(table)); - Query query = table->column(col) == 0; - query.count(); - rt->end_read(); - } - - using namespace std::literals::chrono_literals; - { - ReadTransaction rt(sg); - std::this_thread::sleep_for(60ms); - } - { - WriteTransaction wt(sg); - TableRef t = wt.get_table("table"); - t->create_object(); - std::this_thread::sleep_for(80ms); - wt.commit(); - } - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - CHECK_NOT_EQUAL(metrics->num_query_metrics(), 0); - CHECK_NOT_EQUAL(metrics->num_transaction_metrics(), 0); - - std::unique_ptr transactions = metrics->take_transactions(); - CHECK(transactions); - CHECK_EQUAL(metrics->num_transaction_metrics(), 0); - - CHECK_EQUAL(transactions->size(), 4); - - for (auto t : *transactions) { - CHECK_GREATER(t.get_transaction_time_nanoseconds(), 0); - - if (t.get_transaction_type() == TransactionInfo::read_transaction) { - CHECK_EQUAL(t.get_fsync_time_nanoseconds(), 0.0); - CHECK_EQUAL(t.get_write_time_nanoseconds(), 0.0); - } - else { - if (!get_disable_sync_to_disk()) { - CHECK_NOT_EQUAL(t.get_fsync_time_nanoseconds(), 0.0); - } - CHECK_NOT_EQUAL(t.get_write_time_nanoseconds(), 0.0); - CHECK_LESS(t.get_fsync_time_nanoseconds(), t.get_transaction_time_nanoseconds()); - CHECK_LESS(t.get_write_time_nanoseconds(), t.get_transaction_time_nanoseconds()); - } - } - // test that the timings reported are in the right ballpark - // read transaction - CHECK_EQUAL(transactions->at(2).get_transaction_type(), - metrics::TransactionInfo::TransactionType::read_transaction); - CHECK_GREATER(transactions->at(2).get_transaction_time_nanoseconds(), 1'000); // > 1us - CHECK_LESS(transactions->at(2).get_transaction_time_nanoseconds(), 2'000'000'000); // < 2s - CHECK_EQUAL(transactions->at(2).get_fsync_time_nanoseconds(), 0); // no fsync on read - // write transaction - CHECK_EQUAL(transactions->at(3).get_transaction_type(), - metrics::TransactionInfo::TransactionType::write_transaction); - CHECK_GREATER(transactions->at(3).get_transaction_time_nanoseconds(), 10'000); // > 10us - CHECK_LESS(transactions->at(3).get_transaction_time_nanoseconds(), 2'000'000'000); // < 2s - // TODO: Investigate why this check is failing, since it sometimes fails and, since this is a - // non-concurrent test, the sync_to_disk setting should not change during the execution of this test. -#if 0 - if (!get_disable_sync_to_disk()) { - // This check returns 0 for get_fsync_time_nanoseconds if sync to disk is disabled - CHECK_GREATER(transactions->at(3).get_fsync_time_nanoseconds(), 0); // fsync on write takes some time - } -#endif -} - - -TEST(Metrics_TransactionData) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - DBRef sg = DB::create(*hist, path, options); - populate(sg); - - { - ReadTransaction rt(sg); - } - { - auto wt = sg->start_write(); - auto table_keys = wt->get_table_keys(); - TableRef t0 = wt->get_table(table_keys[0]); - TableRef t1 = wt->get_table(table_keys[1]); - std::vector keys; - t0->create_objects(3, keys); - t1->create_objects(7, keys); - wt->commit(); - } - - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - - std::unique_ptr transactions = metrics->take_transactions(); - CHECK(transactions); - CHECK_EQUAL(metrics->num_transaction_metrics(), 0); - - CHECK_EQUAL(transactions->size(), 3); - - CHECK_EQUAL(transactions->at(0).get_total_objects(), 11); - CHECK_EQUAL(transactions->at(1).get_total_objects(), 11); - CHECK_EQUAL(transactions->at(2).get_total_objects(), 11 + 3 + 7); -} - -TEST(Metrics_TransactionVersions) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - DBRef sg = DB::create(*hist, path, options); - populate(sg); - const size_t num_writes_while_pinned = 10; - TableKey tk0; - TableKey tk1; - { - auto rt = sg->start_read(); - auto table_keys = rt->get_table_keys(); - tk0 = table_keys[0]; - tk1 = table_keys[1]; - } - { - auto wt = sg->start_write(); - TableRef t0 = wt->get_table(tk0); - TableRef t1 = wt->get_table(tk1); - std::vector keys; - t0->create_objects(3, keys); - t1->create_objects(7, keys); - wt->commit(); - } - { - std::unique_ptr hist2(make_in_realm_history()); - DBRef sg2 = DB::create(*hist2, path, options); - - // Pin this version. Note that since this read transaction is against a different shared group - // it doesn't get tracked in the transaction metrics of the original shared group. - ReadTransaction rt(sg2); - - for (size_t i = 0; i < num_writes_while_pinned; ++i) { - auto wt = sg->start_write(); - TableRef t0 = wt->get_table(tk0); - t0->create_object(); - wt->commit(); - } - } - - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - - std::unique_ptr transactions = metrics->take_transactions(); - CHECK(transactions); - CHECK_EQUAL(metrics->num_transaction_metrics(), 0); - - CHECK_EQUAL(transactions->size(), 3 + num_writes_while_pinned); - - CHECK_EQUAL(transactions->at(0).get_num_available_versions(), 2); - CHECK_EQUAL(transactions->at(1).get_num_available_versions(), 2); - CHECK_EQUAL(transactions->at(2).get_num_available_versions(), 2); - CHECK_EQUAL(transactions->at(3).get_num_available_versions(), 2); - - // from here intermediate versions are reclaimed, leaving us - // with 3 active versions regardless of the number of commits - for (size_t i = 1; i < num_writes_while_pinned; ++i) { - CHECK_EQUAL(transactions->at(3 + i).get_num_available_versions(), 3); - } -} - -TEST(Metrics_MaxNumTransactionsIsNotExceeded) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - options.metrics_buffer_size = 10; - auto sg = DB::create(*hist, path, options); - populate(sg); // 1 - { - ReadTransaction rt(sg); // 2 - } - { - WriteTransaction wt(sg); // 3 - TableRef t0 = wt.get_table("person"); - TableRef t1 = wt.get_table("pet"); - for (int i = 0; i < 3; i++) { - t0->create_object(); - } - for (int i = 0; i < 7; i++) { - t1->create_object(); - } - wt.commit(); - } - - for (size_t i = 0; i < options.metrics_buffer_size; ++i) { - ReadTransaction rt(sg); - } - - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - - CHECK_EQUAL(metrics->num_query_metrics(), 0); - CHECK_EQUAL(metrics->num_transaction_metrics(), options.metrics_buffer_size); - std::unique_ptr transactions = metrics->take_transactions(); - CHECK(transactions); - for (auto transaction : *transactions) { - CHECK_EQUAL(transaction.get_transaction_type(), - realm::metrics::TransactionInfo::TransactionType::read_transaction); - } -} - -TEST(Metrics_MaxNumQueriesIsNotExceeded) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - options.metrics_buffer_size = 10; - auto sg = DB::create(*hist, path, options); - - { - auto tr = sg->start_write(); - auto table = tr->add_table("table"); - table->add_column(type_Int, "col_int"); - for (int i = 0; i < 10; i++) { - table->create_object(); - } - tr->commit(); - } - - { - auto rt = sg->start_read(); - auto table = rt->get_table("table"); - auto int_col = table->get_column_key("col_int"); - CHECK(bool(table)); - Query query = table->column(int_col) == 0; - for (size_t i = 0; i < 2 * options.metrics_buffer_size; ++i) { - query.find(); - } - } - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - CHECK_EQUAL(metrics->num_query_metrics(), options.metrics_buffer_size); -} - -// The number of decrypted pages is updated periodically by the governor. -// To test this, we need our own governor implementation which does not reclaim pages but runs at least once. -class NoPageReclaimGovernor : public realm::util::PageReclaimGovernor { -public: - NoPageReclaimGovernor() - { - has_run_twice = will_run.get_future(); - } - - util::UniqueFunction current_target_getter(size_t) override - { - return []() { - return realm::util::PageReclaimGovernor::no_match; - }; - } - - void report_target_result(int64_t) override - { - if (run_count == 2) { // need to run twice before we're done - will_run.set_value(); - } - ++run_count; - } - - std::future has_run_twice; - std::promise will_run; - int run_count = 0; -}; - -// this test relies on the global state of the number of decrypted pages and therefore must be run in isolation -NONCONCURRENT_TEST(Metrics_NumDecryptedPagesWithoutEncryption) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(nullptr); - options.enable_metrics = true; - options.metrics_buffer_size = 10; - auto sg = DB::create(*hist, path, options); - - { - auto tr = sg->start_write(); - tr->add_table("table"); - -#if REALM_ENABLE_ENCRYPTION - // we need this here because other unit tests might be using encryption and we need a guarantee - // that the global pages are from this shared group only. - NoPageReclaimGovernor gov; - realm::util::set_page_reclaim_governor(&gov); - // the remainder of the test suite should use the default. - auto on_exit = make_scope_exit([]() noexcept { - realm::util::set_page_reclaim_governor_to_default(); - }); - CHECK(gov.has_run_twice.valid()); - REALM_ASSERT_RELEASE(gov.has_run_twice.wait_for(std::chrono::seconds(30)) == std::future_status::ready); -#endif - - tr->commit(); - } - - { - auto rt = sg->start_read(); - } - - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - - CHECK_EQUAL(metrics->num_transaction_metrics(), 2); - std::unique_ptr transactions = metrics->take_transactions(); - CHECK(transactions); - CHECK_EQUAL(transactions->size(), 2); - CHECK_EQUAL(transactions->at(0).get_transaction_type(), - realm::metrics::TransactionInfo::TransactionType::write_transaction); - CHECK_EQUAL(transactions->at(0).get_num_decrypted_pages(), 0); - CHECK_EQUAL(transactions->at(1).get_transaction_type(), - realm::metrics::TransactionInfo::TransactionType::read_transaction); - CHECK_EQUAL(transactions->at(1).get_num_decrypted_pages(), 0); -} - -// this test relies on the global state of the number of decrypted pages and therefore must be run in isolation -NONCONCURRENT_TEST_IF(Metrics_NumDecryptedPagesWithEncryption, REALM_ENABLE_ENCRYPTION) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key(true)); - options.enable_metrics = true; - options.metrics_buffer_size = 10; - auto sg = DB::create(*hist, path, options); - - { - auto tr = sg->start_write(); - tr->add_table("table"); - -#if REALM_ENABLE_ENCRYPTION - NoPageReclaimGovernor gov; - realm::util::set_page_reclaim_governor(&gov); - // the remainder of the test suite should use the default. - auto on_exit = make_scope_exit([]() noexcept { - realm::util::set_page_reclaim_governor_to_default(); - }); - CHECK(gov.has_run_twice.valid()); - REALM_ASSERT_RELEASE(gov.has_run_twice.wait_for(std::chrono::seconds(30)) == std::future_status::ready); -#endif - - tr->commit(); - } - - { - auto rt = sg->start_read(); - } - - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - - CHECK_EQUAL(metrics->num_transaction_metrics(), 2); - std::unique_ptr transactions = metrics->take_transactions(); - CHECK(transactions); - CHECK_EQUAL(transactions->size(), 2); - CHECK_EQUAL(transactions->at(0).get_transaction_type(), - realm::metrics::TransactionInfo::TransactionType::write_transaction); - CHECK_EQUAL(transactions->at(0).get_num_decrypted_pages(), 1); - CHECK_EQUAL(transactions->at(1).get_transaction_type(), - realm::metrics::TransactionInfo::TransactionType::read_transaction); - CHECK_EQUAL(transactions->at(1).get_num_decrypted_pages(), 1); -} - -TEST(Metrics_MemoryChecks) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(nullptr); - options.enable_metrics = true; - options.metrics_buffer_size = 10; - auto sg = DB::create(*hist, path, options); - populate(sg); - - { - auto rt = sg->start_read(); - } - - std::shared_ptr metrics = sg->get_metrics(); - CHECK(metrics); - - CHECK_EQUAL(metrics->num_transaction_metrics(), 2); - std::unique_ptr transactions = metrics->take_transactions(); - CHECK(transactions); - - for (auto transaction : *transactions) { - CHECK_GREATER(transaction.get_disk_size(), 0); - CHECK_GREATER(transaction.get_free_space(), 0); - } -} - -#else // REALM_METRICS - -TEST(Metrics_APIAvailability) -{ - SHARED_GROUP_TEST_PATH(path); - std::unique_ptr hist(make_in_realm_history()); - DBOptions options(crypt_key()); - options.enable_metrics = true; - DBRef sg = DB::create(*hist, path, options); - CHECK(!sg->get_metrics()); - { - auto tr = sg->start_write(); - auto table = tr->add_table("table"); - table->add_column(type_Int, "first"); - for (int i = 0; i < 10; i++) { - table->create_object(); - } - tr->commit(); - } - - { - ReadTransaction rt(sg); - auto table = rt.get_table("table"); - auto col = table->get_column_key("first"); - CHECK(bool(table)); - Query q = table->column(col) == 0; - q.count(); - } - std::shared_ptr metrics = sg->get_metrics(); - - // the following will never execute since when REALM_METRICS is undefined, - // then sg.get_metrics() will always return a nullptr, however, the purpose - // of the remainder of the test is to ensure that all of the methods below - // are still accessible at compile time so that users of core do not need to check - // REALM_METRICS, but can use a core with or without the flag in the same way. - if (metrics) { - CHECK_EQUAL(metrics->num_transaction_metrics(), 0); - CHECK_EQUAL(metrics->num_query_metrics(), 0); - std::unique_ptr transactions = metrics->take_transactions(); - - if (transactions) { - for (auto transaction : *transactions) { - transaction.get_disk_size(); - transaction.get_free_space(); - transaction.get_transaction_time(); - transaction.get_fsync_time(); - transaction.get_write_time(); - transaction.get_disk_size(); - transaction.get_free_space(); - transaction.get_total_objects(); - transaction.get_num_available_versions(); - transaction.get_num_decrypted_pages(); - } - } - std::unique_ptr queries = metrics->take_queries(); - if (queries) { - for (auto query : *queries) { - query.get_description(); - query.get_table_name(); - query.get_type(); - query.get_query_time(); - } - } - } -} - -#endif // REALM_METRICS -#endif // TEST_METRICS diff --git a/test/test_parser.cpp b/test/test_parser.cpp index 20a6e4db435..5b0ee14c1d9 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -70,7 +70,6 @@ #include using namespace realm; -using namespace realm::metrics; using namespace realm::test_util; using namespace realm::util; diff --git a/test/testsettings.hpp b/test/testsettings.hpp index c799e7cf26c..ab159805840 100644 --- a/test/testsettings.hpp +++ b/test/testsettings.hpp @@ -59,7 +59,6 @@ #define TEST_UPGRADE #define TEST_INDEX_STRING #define TEST_LANG_BIND_HELPER -#define TEST_METRICS #define TEST_PARSER #define TEST_QUERY #define TEST_SHARED From 57f6da94e40979e6fe98142b9fb756b801d2d396 Mon Sep 17 00:00:00 2001 From: James Stone Date: Wed, 20 Sep 2023 13:54:40 -0700 Subject: [PATCH 2/2] remove metrics from package.swift --- Package.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Package.swift b/Package.swift index 1bdf234c4cb..816de82e813 100644 --- a/Package.swift +++ b/Package.swift @@ -403,7 +403,6 @@ let package = Package( "realm/CMakeLists.txt", "realm/exec", "realm/geospatial.cpp", - "realm/metrics", "realm/object-store/CMakeLists.txt", "realm/object-store/c_api", "realm/object-store/impl/epoll", @@ -451,7 +450,6 @@ let package = Package( "external", "realm/CMakeLists.txt", "realm/exec", - "realm/metrics", "realm/object-store", "realm/parser", "realm/sync/CMakeLists.txt",