diff --git a/src/query/interpret/eval.hpp b/src/query/interpret/eval.hpp index 1ea20846d..8ed737eea 100644 --- a/src/query/interpret/eval.hpp +++ b/src/query/interpret/eval.hpp @@ -1,4 +1,4 @@ -// Copyright 2022 Memgraph Ltd. +// Copyright 2023 Memgraph Ltd. // // Use of this software is governed by the Business Source License // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source @@ -31,6 +31,78 @@ namespace memgraph::query { +static std::chrono::duration total2; +static std::chrono::duration new_print2; + +class ReferenceExpressionEvaluator : public ExpressionVisitor { + public: + ReferenceExpressionEvaluator(Frame *frame, const SymbolTable *symbol_table, const EvaluationContext *ctx, + DbAccessor *dba, storage::View view) + : frame_(frame), symbol_table_(symbol_table), ctx_(ctx), dba_(dba), view_(view) {} + + using ExpressionVisitor::Visit; + + utils::MemoryResource *GetMemoryResource() const { return ctx_->memory; } + +#define UNSUCCESFUL_VISIT(expr_name) \ + TypedValue *Visit(expr_name &expr) override { return nullptr; } + + TypedValue *Visit(Identifier &ident) override { return &frame_->at(symbol_table_->at(ident)); } + + UNSUCCESFUL_VISIT(NamedExpression); + UNSUCCESFUL_VISIT(OrOperator); + UNSUCCESFUL_VISIT(XorOperator); + UNSUCCESFUL_VISIT(AdditionOperator); + UNSUCCESFUL_VISIT(SubtractionOperator); + UNSUCCESFUL_VISIT(MultiplicationOperator); + UNSUCCESFUL_VISIT(DivisionOperator); + UNSUCCESFUL_VISIT(ModOperator); + UNSUCCESFUL_VISIT(NotEqualOperator); + UNSUCCESFUL_VISIT(EqualOperator); + UNSUCCESFUL_VISIT(LessOperator); + UNSUCCESFUL_VISIT(GreaterOperator); + UNSUCCESFUL_VISIT(LessEqualOperator); + UNSUCCESFUL_VISIT(GreaterEqualOperator); + + UNSUCCESFUL_VISIT(NotOperator); + UNSUCCESFUL_VISIT(UnaryPlusOperator); + UNSUCCESFUL_VISIT(UnaryMinusOperator); + + UNSUCCESFUL_VISIT(AndOperator); + UNSUCCESFUL_VISIT(IfOperator); + UNSUCCESFUL_VISIT(InListOperator); + + UNSUCCESFUL_VISIT(SubscriptOperator); + + UNSUCCESFUL_VISIT(ListSlicingOperator); + UNSUCCESFUL_VISIT(IsNullOperator); + UNSUCCESFUL_VISIT(PropertyLookup); + UNSUCCESFUL_VISIT(LabelsTest); + + UNSUCCESFUL_VISIT(PrimitiveLiteral); + UNSUCCESFUL_VISIT(ListLiteral); + UNSUCCESFUL_VISIT(MapLiteral); + UNSUCCESFUL_VISIT(Aggregation); + UNSUCCESFUL_VISIT(Coalesce); + UNSUCCESFUL_VISIT(Function); + UNSUCCESFUL_VISIT(Reduce); + UNSUCCESFUL_VISIT(Extract); + UNSUCCESFUL_VISIT(All); + UNSUCCESFUL_VISIT(Single); + UNSUCCESFUL_VISIT(Any); + UNSUCCESFUL_VISIT(None); + UNSUCCESFUL_VISIT(ParameterLookup); + UNSUCCESFUL_VISIT(RegexMatch); + + private: + Frame *frame_; + const SymbolTable *symbol_table_; + const EvaluationContext *ctx_; + DbAccessor *dba_; + // which switching approach should be used when evaluating + storage::View view_; +}; + class ExpressionEvaluator : public ExpressionVisitor { public: ExpressionEvaluator(Frame *frame, const SymbolTable &symbol_table, const EvaluationContext &ctx, DbAccessor *dba, @@ -159,49 +231,61 @@ class ExpressionEvaluator : public ExpressionVisitor { } TypedValue Visit(SubscriptOperator &list_indexing) override { - auto lhs = list_indexing.expression1_->Accept(*this); + auto start = std::chrono::steady_clock::now(); + + ReferenceExpressionEvaluator referenceExpressionEvaluator(frame_, symbol_table_, ctx_, dba_, view_); + + auto *lhs = list_indexing.expression1_->Accept(referenceExpressionEvaluator); auto index = list_indexing.expression2_->Accept(*this); - if (!lhs.IsList() && !lhs.IsMap() && !lhs.IsVertex() && !lhs.IsEdge() && !lhs.IsNull()) + if (!lhs->IsList() && !lhs->IsMap() && !lhs->IsVertex() && !lhs->IsEdge() && !lhs->IsNull()) throw QueryRuntimeException( "Expected a list, a map, a node or an edge to index with '[]', got " "{}.", - lhs.type()); - if (lhs.IsNull() || index.IsNull()) return TypedValue(ctx_->memory); - if (lhs.IsList()) { + lhs->type()); + if (lhs->IsNull() || index.IsNull()) return TypedValue(ctx_->memory); + if (lhs->IsList()) { if (!index.IsInt()) throw QueryRuntimeException("Expected an integer as a list index, got {}.", index.type()); auto index_int = index.ValueInt(); // NOTE: Take non-const reference to list, so that we can move out the // indexed element as the result. - auto &list = lhs.ValueList(); + const auto &list = lhs->ValueList(); if (index_int < 0) { index_int += static_cast(list.size()); } if (index_int >= static_cast(list.size()) || index_int < 0) return TypedValue(ctx_->memory); // NOTE: Explicit move is needed, so that we return the move constructed // value and preserve the correct MemoryResource. - return std::move(list[index_int]); + auto end = std::chrono::steady_clock::now(); + std::chrono::duration dif = end - start; + total2 += dif; + + if (total2 > new_print2) { + std::cout << "Time difference visit = " << total2.count() << "[s]" << std::endl; + new_print2 += static_cast>(1.0); + } + return TypedValue(list[index_int]); } - if (lhs.IsMap()) { + if (lhs->IsMap()) { if (!index.IsString()) throw QueryRuntimeException("Expected a string as a map index, got {}.", index.type()); // NOTE: Take non-const reference to map, so that we can move out the // looked-up element as the result. - auto &map = lhs.ValueMap(); + const auto &map = lhs->ValueMap(); auto found = map.find(index.ValueString()); if (found == map.end()) return TypedValue(ctx_->memory); // NOTE: Explicit move is needed, so that we return the move constructed // value and preserve the correct MemoryResource. - return std::move(found->second); + return TypedValue(found->second); } - if (lhs.IsVertex()) { + if (lhs->IsVertex()) { if (!index.IsString()) throw QueryRuntimeException("Expected a string as a property name, got {}.", index.type()); - return TypedValue(GetProperty(lhs.ValueVertex(), index.ValueString()), ctx_->memory); + return TypedValue(GetProperty(lhs->ValueVertex(), index.ValueString()), ctx_->memory); } - if (lhs.IsEdge()) { + if (lhs->IsEdge()) { if (!index.IsString()) throw QueryRuntimeException("Expected a string as a property name, got {}.", index.type()); - return TypedValue(GetProperty(lhs.ValueEdge(), index.ValueString()), ctx_->memory); + return TypedValue(GetProperty(lhs->ValueEdge(), index.ValueString()), ctx_->memory); } // lhs is Null diff --git a/src/query/plan/operator.cpp b/src/query/plan/operator.cpp index 01f9fd405..77b0f4f48 100644 --- a/src/query/plan/operator.cpp +++ b/src/query/plan/operator.cpp @@ -155,6 +155,9 @@ uint64_t ComputeProfilingKey(const T *obj) { #define SCOPED_PROFILE_OP(name) ScopedProfile profile{ComputeProfilingKey(this), name, &context}; +std::chrono::duration total; +std::chrono::duration new_print; + bool Once::OnceCursor::Pull(Frame &, ExecutionContext &context) { SCOPED_PROFILE_OP("Once"); @@ -208,6 +211,8 @@ VertexAccessor &CreateLocalVertex(const NodeCreationInfo &node_info, Frame *fram storage::View::NEW); // TODO: PropsSetChecked allocates a PropertyValue, make it use context.memory // when we update PropertyValue with custom allocator. + + auto start = std::chrono::steady_clock::now(); if (const auto *node_info_properties = std::get_if(&node_info.properties)) { for (const auto &[key, value_expression] : *node_info_properties) { PropsSetChecked(&new_node, key, value_expression->Accept(evaluator)); @@ -219,6 +224,14 @@ VertexAccessor &CreateLocalVertex(const NodeCreationInfo &node_info, Frame *fram PropsSetChecked(&new_node, property_id, value); } } + auto end = std::chrono::steady_clock::now(); + std::chrono::duration dif = end - start; + total += dif; + + if (total > new_print) { + std::cout << "Time difference props set checked = " << total.count() << "[s]" << std::endl; + new_print += static_cast>(10.0); + } (*frame)[node_info.symbol] = new_node; return (*frame)[node_info.symbol].ValueVertex(); @@ -4580,19 +4593,17 @@ class LoadCsvCursor : public Cursor { // pulling MATCH). if (!input_is_once_ && !input_pulled) return false; - bool read_something = false; - // read and parse each row - while (auto row = reader_->GetNextRow(context.evaluation_context.memory)) { - if (!reader_->HasHeader()) { - frame[self_->row_var_] = CsvRowToTypedList(*row); - } else { - frame[self_->row_var_] = - CsvRowToTypedMap(*row, csv::Reader::Header(reader_->GetHeader(), context.evaluation_context.memory)); - } - read_something = true; + auto row = reader_->GetNextRow(context.evaluation_context.memory); + if (!row) { + return false; } - - return read_something; + if (!reader_->HasHeader()) { + frame[self_->row_var_] = CsvRowToTypedList(*row); + } else { + frame[self_->row_var_] = + CsvRowToTypedMap(*row, csv::Reader::Header(reader_->GetHeader(), context.evaluation_context.memory)); + } + return true; } void Reset() override { input_cursor_->Reset(); } diff --git a/src/query/typed_value.cpp b/src/query/typed_value.cpp index 13db88e1c..869a21bb7 100644 --- a/src/query/typed_value.cpp +++ b/src/query/typed_value.cpp @@ -1,4 +1,4 @@ -// Copyright 2022 Memgraph Ltd. +// Copyright 2023 Memgraph Ltd. // // Use of this software is governed by the Business Source License // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source @@ -26,6 +26,9 @@ namespace memgraph::query { +std::chrono::duration total; +std::chrono::duration new_print; + TypedValue::TypedValue(const storage::PropertyValue &value) // TODO: MemoryResource in storage::PropertyValue : TypedValue(value, utils::NewDeleteResource()) {} @@ -289,8 +292,18 @@ TypedValue::operator storage::PropertyValue() const { return storage::PropertyValue(int_v); case TypedValue::Type::Double: return storage::PropertyValue(double_v); - case TypedValue::Type::String: - return storage::PropertyValue(std::string(string_v)); + case TypedValue::Type::String: { + auto start = std::chrono::steady_clock::now(); + auto value = storage::PropertyValue(std::string(string_v)); + auto end = std::chrono::steady_clock::now(); + std::chrono::duration dif = end - start; + total += dif; + if (total > new_print) { + std::cout << "Time typed value difference = " << total.count() << "[s]" << std::endl; + new_print += static_cast>(10.0); + } + return value; + } case TypedValue::Type::List: return storage::PropertyValue(std::vector(list_v.begin(), list_v.end())); case TypedValue::Type::Map: { diff --git a/src/storage/v2/vertex_accessor.cpp b/src/storage/v2/vertex_accessor.cpp index 05ba1ebcc..fdf6aba4e 100644 --- a/src/storage/v2/vertex_accessor.cpp +++ b/src/storage/v2/vertex_accessor.cpp @@ -1,4 +1,4 @@ -// Copyright 2022 Memgraph Ltd. +// Copyright 2023 Memgraph Ltd. // // Use of this software is governed by the Business Source License // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source @@ -13,6 +13,7 @@ #include +#include #include "storage/v2/edge_accessor.hpp" #include "storage/v2/id_types.hpp" #include "storage/v2/indices.hpp" @@ -60,6 +61,9 @@ std::pair IsVisible(Vertex *vertex, Transaction *transaction, View v } // namespace } // namespace detail +std::chrono::duration total; +std::chrono::duration new_print; + std::optional VertexAccessor::Create(Vertex *vertex, Transaction *transaction, Indices *indices, Constraints *constraints, Config::Items config, View view) { if (const auto [exists, deleted] = detail::IsVisible(vertex, transaction, view); !exists || deleted) { @@ -208,6 +212,8 @@ Result> VertexAccessor::Labels(View view) const { } Result VertexAccessor::SetProperty(PropertyId property, const PropertyValue &value) { + auto start = std::chrono::steady_clock::now(); + utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception; std::lock_guard guard(vertex_->lock); @@ -227,6 +233,15 @@ Result VertexAccessor::SetProperty(PropertyId property, const Pro UpdateOnSetProperty(indices_, property, value, vertex_, *transaction_); + auto end = std::chrono::steady_clock::now(); + std::chrono::duration dif = end - start; + total += dif; + + if (total > new_print) { + std::cout << "Time difference = " << total.count() << "[s]" << std::endl; + new_print += static_cast>(2.0); + } + return std::move(current_value); } diff --git a/src/storage/v2/vertex_accessor.hpp b/src/storage/v2/vertex_accessor.hpp index 840eec910..916c45a20 100644 --- a/src/storage/v2/vertex_accessor.hpp +++ b/src/storage/v2/vertex_accessor.hpp @@ -1,4 +1,4 @@ -// Copyright 2022 Memgraph Ltd. +// Copyright 2023 Memgraph Ltd. // // Use of this software is governed by the Business Source License // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source