diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e3e8e214..535633790 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,7 +116,7 @@ foreach(source_folder ${source_folders}) endforeach() # compiler options -SET(COMPILE_OPTIONS "-O0 -g3 -Wall -Werror -fmessage-length=0") +SET(COMPILE_OPTIONS "-O2 -Wall -Werror -fmessage-length=0") # add all cpp file recursive into sourceFiles varibale # FILE(GLOB_RECURSE sourceFiles ${src_dir}/*.cpp) @@ -152,30 +152,38 @@ include_directories(${r3_source_dir}/include) # creates build/libcypher_lib.a add_library(cypher_lib STATIC ${CMAKE_BINARY_DIR}/cypher.cpp) -# tests -enable_testing() -add_subdirectory(tests) - # REST API preprocessor EXECUTE_PROCESS( COMMAND python link_resources.py WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/api ) -# memgraph executable -add_executable(memgraph src/memgraph.cpp) -add_dependencies(memgraph cypher_lib) -# memgraph link libraries -target_link_libraries(memgraph Threads::Threads) -target_link_libraries(memgraph pcre) -target_link_libraries(memgraph ${libuv_static_lib}) -target_link_libraries(memgraph ${r3_static_lib}) -target_link_libraries(memgraph ${http_parser_static_lib}) +# # memgraph executable +# add_executable(memgraph src/memgraph.cpp) +# add_dependencies(memgraph cypher_lib) +# # memgraph link libraries +# target_link_libraries(memgraph Threads::Threads) +# target_link_libraries(memgraph pcre) +# target_link_libraries(memgraph ${libuv_static_lib}) +# target_link_libraries(memgraph ${r3_static_lib}) +# target_link_libraries(memgraph ${http_parser_static_lib}) -# query_engine executable -add_executable(query_engine src/query_engine/main.cpp) -# query_engine link libraries -target_link_libraries(query_engine Threads::Threads) -target_link_libraries(query_engine dl) -target_link_libraries(query_engine cypher_lib) -target_link_libraries(query_engine ${fmt_static_lib}) +# # query_engine executable +# add_executable(query_engine src/query_engine/main_query_engine.cpp) +# # query_engine link libraries +# target_link_libraries(query_engine Threads::Threads) +# target_link_libraries(query_engine dl) +# target_link_libraries(query_engine cypher_lib) +# target_link_libraries(query_engine ${fmt_static_lib}) + +# # query hasher executable +# add_executable(query_hasher src/query_engine/main_query_hasher.cpp) +# target_link_libraries(query_hasher ${fmt_static_lib}) +# +# # hard coded implementation of queries +# add_executable(queries src/query_engine/main_queries.cpp) +# target_link_libraries(queries ${fmt_static_lib}) + +# tests +enable_testing() +add_subdirectory(tests) diff --git a/src/cypher/cypher.y b/src/cypher/cypher.y index b9b277062..b09fbeb63 100644 --- a/src/cypher/cypher.y +++ b/src/cypher/cypher.y @@ -13,6 +13,7 @@ %syntax_error { +#ifndef NDEBUG int n = sizeof(yyTokenName) / sizeof(yyTokenName[0]); for (int i = 0; i < n; ++i) { int a = yy_find_shift_action(yypParser, (YYCODETYPE)i); @@ -21,6 +22,7 @@ } } throw SyntaxError(TOKEN->value); +#endif } %stack_overflow diff --git a/src/data_structures/skiplist/skiplist.hpp b/src/data_structures/skiplist/skiplist.hpp index f2c52171a..26b0341c3 100644 --- a/src/data_structures/skiplist/skiplist.hpp +++ b/src/data_structures/skiplist/skiplist.hpp @@ -453,7 +453,7 @@ public: return Accessor(this); } - Accessor access() const + const Accessor access() const { return Accessor(this); } diff --git a/src/data_structures/skiplist/skiplist_gc.hpp b/src/data_structures/skiplist/skiplist_gc.hpp index f1950e5da..86e597325 100644 --- a/src/data_structures/skiplist/skiplist_gc.hpp +++ b/src/data_structures/skiplist/skiplist_gc.hpp @@ -28,18 +28,24 @@ public: } } - long long counter = 0; - - // destroy all elements from local_freelist - for (auto element : local_freelist) { - counter++; - if (element->flags.is_marked()) T::destroy(element); + if (local_freelist.size() > 0) { + std::cout << "GC started" << std::endl; + std::cout << "Local skiplist size: " << + local_freelist.size() << std::endl; + long long counter = 0; + // destroy all elements from local_freelist + for (auto element : local_freelist) { + counter++; + if (element->flags.is_marked()) T::destroy(element); + } + std::cout << "Number of destroyed elements " << counter << std::endl; } - - std::cout << "Destroy has been called: " << counter << std::endl; } - void collect(T *node) { freelist.add(node); } + void collect(T *node) + { + freelist.add(node); + } private: FreeList freelist; diff --git a/src/memory/freelist.hpp b/src/memory/freelist.hpp index 3d1f8df14..d425282dd 100644 --- a/src/memory/freelist.hpp +++ b/src/memory/freelist.hpp @@ -17,6 +17,11 @@ public: data.emplace_back(element); } + size_t size() const + { + return data.size(); + } + private: std::vector data; }; diff --git a/src/query_engine/compile.sh b/src/query_engine/compile.sh deleted file mode 100755 index 21a2d6860..000000000 --- a/src/query_engine/compile.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -# TODO: create Makefile or cmake script -# cd compiled/cpu -# clang++ -std=c++1y create_return.cpp -o create_return.so -I../../../ -shared -fPIC -# cd ../.. -# clang++ -std=c++1y -g -I../ -I ../lib/yaml-cpp/include main.cpp ../cypher/cypher.cpp -o engine -L ../lib/yaml-cpp/build -l yaml-cpp -l dl -# clang++ -std=c++1y -g -O2 -I../ main.cpp ../cypher/cypher.cpp -o engine.out -l dl -pthread -clang++ -std=c++1y -g -I../ main.cpp ../cypher/cypher.cpp -o engine.out -l dl -pthread diff --git a/src/query_engine/main_queries.cpp b/src/query_engine/main_queries.cpp new file mode 100644 index 000000000..890bf0858 --- /dev/null +++ b/src/query_engine/main_queries.cpp @@ -0,0 +1,108 @@ +#include + +#include "database/db.hpp" +#include "query_stripper.hpp" +#include "storage/model/properties/property.hpp" +#include "utils/command_line/arguments.hpp" +#include "cypher/common.hpp" +#include "utils/time/timer.hpp" + +// -- +// DESCRIPTION: create account +// FULL: CREATE (n:ACCOUNT {id: 50, name: "Nikola", country: "Croatia", created_at: 14634563}) RETURN n +// STRIPPED: CREATE(n:ACCOUNT{id:0,name:1,country:2,created_at:3})RETURNn +// HASH: 10597108978382323595 +// -- +// DESCRIPTION: create personnel +// FULL: CREATE (n:PERSONNEL {id: 23, role: "CTO", created_at: 1235345}) RETURN n +// STRIPPED: CREATE(n:PERSONNEL{id:0,role:1,created_at:2})RETURNn +// HASH: 4037885257628527960 +// -- +// DESCRIPTION: create edge between ACCOUNT node and PERSONNEL node (IS type) +// FULL: MATCH (a:ACCOUNT {id:50}), (p:PERSONNEL {id: 23}) CREATE (a)-[:IS]->(p) +// STRIPPED: MATCH(a:ACCOUNT{id:0}),(p:PERSONNEL{id:1})CREATE(a)-[:IS]->(p) +// HASH: 16888190822925675190 +// -- +// DESCRIPTION: find ACCOUNT node, PERSONNEL node and edge between them +// FULL: MATCH (a:ACCOUNT {id:50})-[r:IS]->(p:PERSONNEL {id: 23}) RETURN a,r,p +// STRIPPED: MATCH(a:ACCOUNT{id:0})-[r:IS]->(p:PERSONNEL{id:1})RETURNa,r,p +// HASH: 9672752533852902744 +// -- +// DESCRIPTION: create OPPORTUNITY +// FULL: +// STRIPPED: +// HASH: +// -- +// DESCRIPTION: create PERSONNEL-[:CREATED]->OPPORTUNITY +// FULL: +// STRIPPED: +// HASH: +// -- +// DESCRIPTION: create COMPANY +// FULL: +// STRIPPED: +// HASH: +// -- +// DESCRIPTION: create OPPORTUNITY-[:MATCH]->COMPANY +// FULL: +// STRIPPED: +// HASH: +// -- +// DESCRIPTION: create edge between two nodes found by the ID +// DESCRIPTION: fine node by the ID +// DESCRIPTION: find edge by the ID +// DESCRIPTION: find shortest path between two nodes specified by ID + +int main(int argc, char** argv) +{ + Db db; + std::map> queries; + + auto create_account = [&db](const properties_t& args) + { + auto& t = db.tx_engine.begin(); + auto vertex_accessor = db.graph.vertices.insert(t); + vertex_accessor.property( + "id", args[0] + ); + vertex_accessor.property( + "name", args[1] + ); + vertex_accessor.property( + "country", args[2] + ); + vertex_accessor.property( + "created_at", args[3] + ); + auto label = db.graph.label_store.find_or_create("ACCOUNT"); + vertex_accessor.add_label(label); + t.commit(); + // TODO: return the result once the bolt will be implemented + }; + + auto find_node_by_id = [&db](const properties_t& args) + { + auto& t = db.tx_engine.begin(); + auto id = static_cast(*args[0]); + auto vertex_accessor = db.graph.vertices.find(t, Id(id.value)); + t.commit(); + // TODO: return the result once the bolt will be implemented + }; + + queries[10597108978382323595u] = create_account; + + auto arguments = all_arguments(argc, argv); + auto input_query = extract_query(arguments); + + auto stripper = make_query_stripper(TK_INT, TK_FLOAT, TK_STR, TK_BOOL); + auto stripped = stripper.strip(input_query); + + auto time = timer([&stripped, &queries]() { + for (int i = 0; i < 1000000; ++i) { + queries[stripped.hash](stripped.arguments); + } + }); + std::cout << time << std::endl; + + return 0; +} diff --git a/src/query_engine/main.cpp b/src/query_engine/main_query_engine.cpp similarity index 100% rename from src/query_engine/main.cpp rename to src/query_engine/main_query_engine.cpp diff --git a/src/query_engine/main_query_hasher.cpp b/src/query_engine/main_query_hasher.cpp new file mode 100644 index 000000000..3077498c9 --- /dev/null +++ b/src/query_engine/main_query_hasher.cpp @@ -0,0 +1,38 @@ +#include + +#include "query_hasher.hpp" +#include "cypher/common.hpp" +#include "query_stripper.hpp" +#include "utils/command_line/arguments.hpp" +#include "utils/type_discovery.hpp" + +using std::cout; +using std::cin; +using std::endl; + +int main(int argc, char** argv) +{ + // arguments parsing + auto arguments = all_arguments(argc, argv); + + // query extraction + auto input_query = extract_query(arguments); + + cout << "QUERY: " << input_query << endl; + + auto stripper = make_query_stripper(TK_INT, TK_FLOAT, TK_STR, TK_BOOL); + auto stripped = stripper.strip(input_query); + + cout << "STRIPPED QUERY: " << stripped.query << endl; + + QueryHasher query_hasher; + + cout << "QUERY HASH: " << query_hasher.hash(stripped.query) << endl; + + cout << "PROPERTIES:" << endl; + for (auto property : stripped.arguments) { + cout << " " << *property << endl; + } + + return 0; +} diff --git a/src/query_engine/program_loader.hpp b/src/query_engine/program_loader.hpp index c1706789c..d1c80e70f 100644 --- a/src/query_engine/program_loader.hpp +++ b/src/query_engine/program_loader.hpp @@ -34,8 +34,7 @@ public: auto stripped = stripper.strip(query); LOG_INFO("stripped_query=" + stripped.query); - auto stripped_hash = fnv(stripped.query); - auto hash_string = std::to_string(stripped_hash); + auto hash_string = std::to_string(stripped.hash); LOG_INFO("query_hash=" + hash_string); auto code_lib_iter = code_libs.find(stripped_hash); diff --git a/src/query_engine/query_hasher.hpp b/src/query_engine/query_hasher.hpp new file mode 100644 index 000000000..8ffbe1dfe --- /dev/null +++ b/src/query_engine/query_hasher.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "cypher/common.hpp" +#include "query_stripper.hpp" +#include "utils/hashing/fnv.hpp" + +class QueryHasher +{ +public: + QueryHasher() + : stripper(make_query_stripper(TK_INT, TK_FLOAT, TK_STR, TK_BOOL)) {} + + std::string hash(std::string &query) + { + auto stripped = stripper.strip(query); + auto stripped_hash = fnv(stripped.query); + auto hash_string = std::to_string(stripped_hash); + return hash_string; + } + +private: + QueryStripper stripper; +}; diff --git a/src/query_engine/query_stripped.hpp b/src/query_engine/query_stripped.hpp index bfea73ef3..a69d9dca1 100644 --- a/src/query_engine/query_stripped.hpp +++ b/src/query_engine/query_stripped.hpp @@ -8,8 +8,9 @@ using code_args_t = std::vector; struct QueryStripped { - QueryStripped(const std::string &&query, code_args_t &&arguments) - : query(std::forward(query)), + QueryStripped(const std::string &&query, uint64_t hash, + code_args_t &&arguments) + : query(std::forward(query)), hash(hash), arguments(std::forward(arguments)) { } @@ -17,6 +18,7 @@ struct QueryStripped QueryStripped(QueryStripped &other) = delete; QueryStripped(QueryStripped &&other) = default; - std::string query; code_args_t arguments; + uint64_t hash; + std::string query; }; diff --git a/src/query_engine/query_stripper.hpp b/src/query_engine/query_stripper.hpp index a4e4cb5ce..82e7abd9b 100644 --- a/src/query_engine/query_stripper.hpp +++ b/src/query_engine/query_stripper.hpp @@ -7,6 +7,7 @@ #include "cypher/cypher.h" #include "cypher/tokenizer/cypher_lexer.hpp" +#include "utils/hashing/fnv.hpp" #include "query_stripped.hpp" #include "storage/model/properties/all.hpp" #include "utils/string/transform.hpp" @@ -84,6 +85,7 @@ public: } return QueryStripped(std::move(stripped_query), + fnv(stripped_query), std::move(stripped_arguments)); } diff --git a/src/storage/graph.hpp b/src/storage/graph.hpp index 6197cff2d..166a6c885 100644 --- a/src/storage/graph.hpp +++ b/src/storage/graph.hpp @@ -1,14 +1,15 @@ #pragma once -#include "data_structures/skiplist/skiplist.hpp" #include "storage/vertices.hpp" #include "storage/edges.hpp" +#include "storage/label_store.hpp" class Graph { public: Graph() {} - Vertices vertices; Edges edges; + Vertices vertices; + LabelStore label_store; }; diff --git a/src/storage/label_store.hpp b/src/storage/label_store.hpp index f40e37a8b..13de699bb 100644 --- a/src/storage/label_store.hpp +++ b/src/storage/label_store.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "model/label.hpp" #include "data_structures/skiplist/skiplistset.hpp" @@ -13,12 +15,15 @@ public: return accessor.insert(Label(name)).first; } - bool contains(const std::string& name) const + bool contains(const std::string& name) // const { auto accessor = labels.access(); return accessor.find(Label(name)) != accessor.end(); } + // TODO: implement find method + // return { Label, is_found } + private: SkipListSet