benchmark folder has been removed from the root dir, README update, measure_time.hpp comments
This commit is contained in:
parent
d4e3c4cd10
commit
0198b37f21
86
README.md
86
README.md
@ -14,82 +14,10 @@ Some code contains linux-specific libraries and the build is only supported
|
|||||||
on a 64 bit linux kernel.
|
on a 64 bit linux kernel.
|
||||||
|
|
||||||
* linux
|
* linux
|
||||||
* clang 3.5 or Gcc 4.8 (good c++11 support, especially lock free atomics)
|
* clang 3.8 (good c++11 support, especially lock free atomics)
|
||||||
* boost 1.55 (or something, probably works with almost anything)
|
* antlr (compiler frontend)
|
||||||
* lexertl (2015-07-14)
|
* cppitertools
|
||||||
* lemon (parser generator)
|
* fmt format
|
||||||
* catch (for compiling tests)
|
* google benchmark
|
||||||
|
* google test
|
||||||
### Bolt
|
* yaml-cpp
|
||||||
|
|
||||||
sudo apt-get install libssl-dev
|
|
||||||
|
|
||||||
## build
|
|
||||||
```
|
|
||||||
cd build
|
|
||||||
cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DRUNTIME_ASSERT=OFF -DTHROW_EXCEPTION_ON_ERROR=OFF -DNDEBUG=OFF ..
|
|
||||||
|
|
||||||
# Flags:
|
|
||||||
# -DCMAKE_C_COMPILER=clang
|
|
||||||
# -DCMAKE_CXX_COMPILER=clang++
|
|
||||||
# -DRUNTIME_ASSERT=OFF
|
|
||||||
# -DTHROW_EXCEPTION_ON_ERROR=OFF
|
|
||||||
# -DNDEBUG=ON
|
|
||||||
# -DCMAKE_BUILD_TYPE:STRING=debug
|
|
||||||
# -DCMAKE_BUILD_TYPE:STRING=release
|
|
||||||
|
|
||||||
make
|
|
||||||
ctest
|
|
||||||
ctest -V
|
|
||||||
ctest -R test_name
|
|
||||||
ctest -R unit
|
|
||||||
ctest -R concurrent
|
|
||||||
ctest -R concurrent --parallel 4
|
|
||||||
```
|
|
||||||
|
|
||||||
## Proof of concept
|
|
||||||
|
|
||||||
### Dressipi
|
|
||||||
|
|
||||||
Run command:
|
|
||||||
```
|
|
||||||
cd build/poc
|
|
||||||
MEMGRAPH_CONFIG=/path/to/config/memgraph.yaml ./poc_astar -v "dressipi/graph_nodes_export.csv" -e "dressipi/graph_edges_export.csv"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Powerlinx
|
|
||||||
|
|
||||||
Run command:
|
|
||||||
```
|
|
||||||
cd build/poc
|
|
||||||
MEMGRAPH_CONFIG=/path/to/config/memgraph.yaml ./profile -d ";" -v "node_account.csv" -v "node_company.csv" -v "node_opportunity.csv" -v "node_personnel.csv" -e "rel_created.csv" -e "rel_has_match.csv" -e "rel_interested_in.csv" -e "rel_is_employee.csv" -e "rel_partnered_with.csv" -e "rel_reached_to.csv" -e "rel_searched_and_clicked.csv" -e "rel_viewed.csv" -e "rel_works_in.csv"
|
|
||||||
```
|
|
||||||
|
|
||||||
# Custom test build example
|
|
||||||
clang++ -std=c++1y -o concurrent_skiplist ../tests/concurrent/skiplist.cpp -pg -I../src/ -I../libs/fmt -Lfmt-prefix/src/fmt-build/fmt -lfmt -lpthread
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
* implement basic subset of queries:
|
|
||||||
* create node
|
|
||||||
* create edge
|
|
||||||
* find node
|
|
||||||
* find edge
|
|
||||||
* update node
|
|
||||||
* update edge
|
|
||||||
* delete node
|
|
||||||
* delete edge
|
|
||||||
|
|
||||||
* implement index
|
|
||||||
* label index
|
|
||||||
* type index
|
|
||||||
* property index
|
|
||||||
|
|
||||||
* from header only approach to .hpp + .cpp
|
|
||||||
* query engine has to be statically linked with the rest of the code
|
|
||||||
|
|
||||||
* unit test of queries that are manually implemented
|
|
||||||
* src/query_engine/main_queries.cpp -> tests/unit/manual_queries
|
|
||||||
|
|
||||||
* unit test of query_engine
|
|
||||||
|
|
||||||
* console with history
|
|
||||||
|
1
benchmark/.gitignore
vendored
1
benchmark/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
*.out
|
|
@ -1,58 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include "utils/memory/allocator.hpp"
|
|
||||||
#include "utils/memory/maker.hpp"
|
|
||||||
|
|
||||||
struct TestStruct
|
|
||||||
{
|
|
||||||
TestStruct(int a, int b, int c, int d)
|
|
||||||
: a(a), b(b), c(c), d(d) {}
|
|
||||||
|
|
||||||
int a, b, c, d;
|
|
||||||
};
|
|
||||||
|
|
||||||
void test_classic(int N)
|
|
||||||
{
|
|
||||||
TestStruct** xs = new TestStruct*[N];
|
|
||||||
|
|
||||||
for(int i = 0; i < N; ++i)
|
|
||||||
xs[i] = new TestStruct(i, i, i, i);
|
|
||||||
|
|
||||||
for(int i = 0; i < N; ++i)
|
|
||||||
delete xs[i];
|
|
||||||
|
|
||||||
delete[] xs;
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_fast(int N)
|
|
||||||
{
|
|
||||||
TestStruct** xs = new TestStruct*[N];
|
|
||||||
|
|
||||||
for(int i = 0; i < N; ++i)
|
|
||||||
xs[i] = makeme<TestStruct>(i, i, i, i);
|
|
||||||
|
|
||||||
for(int i = 0; i < N; ++i)
|
|
||||||
delete xs[i];
|
|
||||||
|
|
||||||
delete[] xs;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
constexpr int n_threads = 256;
|
|
||||||
constexpr int N = 80000000 / n_threads;
|
|
||||||
|
|
||||||
std::vector<std::thread> threads;
|
|
||||||
|
|
||||||
for(int i = 0; i < n_threads; ++i)
|
|
||||||
threads.push_back(std::thread(test_fast, N));
|
|
||||||
|
|
||||||
for(auto& thread : threads){
|
|
||||||
thread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
neo4j-driver==1.0.2
|
|
@ -1,2 +0,0 @@
|
|||||||
#define CATCH_CONFIG_MAIN
|
|
||||||
#include "catch.hpp"
|
|
@ -1,17 +0,0 @@
|
|||||||
#include "data_structures/bitset/dynamic_bitset.hpp"
|
|
||||||
#include "catch.hpp"
|
|
||||||
|
|
||||||
TEST_CASE("Dynamic bitset basic functionality") {
|
|
||||||
DynamicBitset<> db;
|
|
||||||
db.set(222555, 1);
|
|
||||||
bool value = db.at(222555, 1);
|
|
||||||
REQUIRE(value == true);
|
|
||||||
|
|
||||||
db.set(32, 1);
|
|
||||||
value = db.at(32, 1);
|
|
||||||
REQUIRE(value == true);
|
|
||||||
|
|
||||||
db.clear(32, 1);
|
|
||||||
value = db.at(32, 1);
|
|
||||||
REQUIRE(value == false);
|
|
||||||
}
|
|
95
src/utils/measure_time.hpp
Normal file
95
src/utils/measure_time.hpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <ratio>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
using ms = std::chrono::milliseconds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Casts the time difference into DurationUnit (default values is
|
||||||
|
* std::chrono::nanoseconds).
|
||||||
|
*
|
||||||
|
* @tparam DurationUnit type of return value
|
||||||
|
* @param delta time difference
|
||||||
|
* @return time difference in DurationUnit
|
||||||
|
*/
|
||||||
|
template <typename DurationUnit = std::chrono::nanoseconds>
|
||||||
|
auto to_duration(const std::chrono::duration<long, std::nano> &delta) {
|
||||||
|
return std::chrono::duration_cast<DurationUnit>(delta).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Measures time for the function call.
|
||||||
|
*
|
||||||
|
* @tparam DurationUnit unit of returned value
|
||||||
|
* @param func function to execute
|
||||||
|
* @param args function arguments
|
||||||
|
* @return duration of a function call
|
||||||
|
*/
|
||||||
|
template <typename DurationUnit, typename F, typename... Args>
|
||||||
|
auto measure_time(F func, Args &&... args) {
|
||||||
|
auto start_time = std::chrono::high_resolution_clock::now();
|
||||||
|
func(std::forward<Args>(args)...);
|
||||||
|
return to_duration<DurationUnit>(std::chrono::high_resolution_clock::now() -
|
||||||
|
start_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stopwatch
|
||||||
|
*
|
||||||
|
* idea from Optimized C++ Kurt Guntheroth 2016
|
||||||
|
*
|
||||||
|
* The instance of this class can return delta time from a single start point.
|
||||||
|
* The start point in time is stored within the object.
|
||||||
|
*/
|
||||||
|
class Stopwatch {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Initializes start point to system clock min.
|
||||||
|
*/
|
||||||
|
Stopwatch() : start_(std::chrono::system_clock::time_point::min()) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set start point to system clock min.
|
||||||
|
*/
|
||||||
|
void Clear() { start_ = std::chrono::system_clock::time_point::min(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If start isn't system clock min than the Stopwatch has been started.
|
||||||
|
*
|
||||||
|
* @return bool is the Stopwatch started.
|
||||||
|
*/
|
||||||
|
auto IsStarted() const {
|
||||||
|
return (start_ != std::chrono::system_clock::time_point::min());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set start point to the current time.
|
||||||
|
*/
|
||||||
|
void Start() { start_ = std::chrono::system_clock::now(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return elapsed time in milliseconds
|
||||||
|
* if the Stopwatch isn't active returns 0
|
||||||
|
*/
|
||||||
|
auto GetMs() {
|
||||||
|
if (IsStarted()) {
|
||||||
|
std::chrono::system_clock::duration diff;
|
||||||
|
diff = std::chrono::system_clock::now() - start_;
|
||||||
|
return std::chrono::duration_cast<std::chrono::milliseconds>(diff);
|
||||||
|
}
|
||||||
|
return std::chrono::milliseconds(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty destructor.
|
||||||
|
*/
|
||||||
|
~Stopwatch() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::chrono::system_clock::time_point start_;
|
||||||
|
};
|
||||||
|
}
|
@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
|
||||||
|
|
||||||
using ms = std::chrono::milliseconds;
|
|
@ -1,51 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <ratio>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "utils/time/time.hpp"
|
|
||||||
|
|
||||||
#define time_now() std::chrono::high_resolution_clock::now()
|
|
||||||
|
|
||||||
template <typename DurationUnit = std::chrono::nanoseconds>
|
|
||||||
auto to_duration(const std::chrono::duration<long, std::nano> &delta) {
|
|
||||||
return std::chrono::duration_cast<DurationUnit>(delta).count();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename DurationUnit, typename F, typename... Args>
|
|
||||||
auto timer(F func, Args &&... args) {
|
|
||||||
auto start_time = time_now();
|
|
||||||
func(std::forward<Args>(args)...);
|
|
||||||
return to_duration<DurationUnit>(time_now() - start_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
// idea from Optimized C++ Kurt Guntheroth 2016
|
|
||||||
// TODO: make more modular and easier to use
|
|
||||||
class Stopwatch {
|
|
||||||
public:
|
|
||||||
Stopwatch() : start(std::chrono::system_clock::time_point::min()) {}
|
|
||||||
|
|
||||||
void Clear() { start = std::chrono::system_clock::time_point::min(); }
|
|
||||||
|
|
||||||
bool IsStarted() const {
|
|
||||||
return (start != std::chrono::system_clock::time_point::min());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Start() { start = std::chrono::system_clock::now(); }
|
|
||||||
|
|
||||||
unsigned long GetMs() {
|
|
||||||
if (IsStarted()) {
|
|
||||||
std::chrono::system_clock::duration diff;
|
|
||||||
diff = std::chrono::system_clock::now() - start;
|
|
||||||
return (unsigned)(std::chrono::duration_cast<ms>(diff).count());
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Stopwatch() { std::cout << "Time: " << GetMs() << "ms" << std::endl; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::chrono::system_clock::time_point start;
|
|
||||||
};
|
|
@ -8,12 +8,15 @@
|
|||||||
|
|
||||||
#include "logging/default.hpp"
|
#include "logging/default.hpp"
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Timer
|
* @class Timer
|
||||||
*
|
*
|
||||||
* @brief The timer contains counter and handler.
|
* @brief The timer contains counter and handler which is executed when the time
|
||||||
|
* exceedes.
|
||||||
*
|
*
|
||||||
* With every clock interval the counter should be decresed for
|
* With every clock interval the counter should be decreased for
|
||||||
* delta count. Delta count is one for now but it should be a variable in the
|
* delta count. Delta count is one for now but it should be a variable in the
|
||||||
* near future. The handler is function that will be called when counter
|
* near future. The handler is function that will be called when counter
|
||||||
* becomes zero or smaller than zero.
|
* becomes zero or smaller than zero.
|
||||||
@ -151,3 +154,4 @@ class TimerScheduler {
|
|||||||
std::thread run_thread;
|
std::thread run_thread;
|
||||||
std::atomic<bool> is_running;
|
std::atomic<bool> is_running;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
58
tests/benchmark/allocator.cpp
Normal file
58
tests/benchmark/allocator.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "utils/assert.hpp"
|
||||||
|
#include "utils/measure_time.hpp"
|
||||||
|
#include "utils/memory/allocator.hpp"
|
||||||
|
#include "utils/memory/maker.hpp"
|
||||||
|
|
||||||
|
struct TestStructure {
|
||||||
|
TestStructure(int a, int b, int c, int d) : a(a), b(b), c(c), d(d) {}
|
||||||
|
int a, b, c, d;
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_classic(int N) {
|
||||||
|
TestStructure** xs = new TestStructure*[N];
|
||||||
|
for (int i = 0; i < N; ++i) xs[i] = new TestStructure(i, i, i, i);
|
||||||
|
for (int i = 0; i < N; ++i) delete xs[i];
|
||||||
|
delete[] xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_fast(int N) {
|
||||||
|
TestStructure** xs = new TestStructure*[N];
|
||||||
|
for (int i = 0; i < N; ++i) xs[i] = makeme<TestStructure>(i, i, i, i);
|
||||||
|
for (int i = 0; i < N; ++i) delete xs[i];
|
||||||
|
delete[] xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
constexpr int n_threads = 32;
|
||||||
|
constexpr int N = 80000000 / n_threads;
|
||||||
|
|
||||||
|
auto elapsed_classic = utils::measure_time<std::chrono::milliseconds>([&]() {
|
||||||
|
std::vector<std::thread> threads;
|
||||||
|
for (int i = 0; i < n_threads; ++i)
|
||||||
|
threads.push_back(std::thread(test_classic, N));
|
||||||
|
for (auto& thread : threads) {
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
std::cout << "Classic (new): " << elapsed_classic << "ms" << std::endl;
|
||||||
|
|
||||||
|
auto elapsed_fast = utils::measure_time<std::chrono::milliseconds>([&]() {
|
||||||
|
std::vector<std::thread> threads;
|
||||||
|
for (int i = 0; i < n_threads; ++i)
|
||||||
|
threads.push_back(std::thread(test_fast, N));
|
||||||
|
for (auto& thread : threads) {
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
std::cout << "Fast (fast allocator): " << elapsed_fast << "ms" << std::endl;
|
||||||
|
permanent_assert(elapsed_fast < elapsed_classic,
|
||||||
|
"Custom fast allocator "
|
||||||
|
"has to perform faster on simple array allocation");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
|
#define LOG_NO_INFO 1
|
||||||
|
|
||||||
#include "logging/default.hpp"
|
#include "logging/default.hpp"
|
||||||
#include "logging/streams/stdout.hpp"
|
#include "logging/streams/stdout.hpp"
|
||||||
#include "query/preprocessor.hpp"
|
#include "query/preprocessor.hpp"
|
||||||
#include "utils/time/timer.hpp"
|
|
||||||
|
|
||||||
#include "benchmark/benchmark_api.h"
|
#include "benchmark/benchmark_api.h"
|
||||||
#include "yaml-cpp/yaml.h"
|
#include "yaml-cpp/yaml.h"
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "utils/timer/timer.hpp"
|
#include "utils/timer/timer.hpp"
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
using namespace utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a test timer which will log timeout message at the timeout event.
|
* Creates a test timer which will log timeout message at the timeout event.
|
Loading…
Reference in New Issue
Block a user