benchmark folder has been removed from the root dir, README update, measure_time.hpp comments

This commit is contained in:
Marko Budiselic 2017-02-18 14:36:50 +01:00
parent d4e3c4cd10
commit 0198b37f21
13 changed files with 169 additions and 220 deletions

View File

@ -14,82 +14,10 @@ Some code contains linux-specific libraries and the build is only supported
on a 64 bit linux kernel.
* linux
* clang 3.5 or Gcc 4.8 (good c++11 support, especially lock free atomics)
* boost 1.55 (or something, probably works with almost anything)
* lexertl (2015-07-14)
* lemon (parser generator)
* catch (for compiling tests)
### Bolt
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
* clang 3.8 (good c++11 support, especially lock free atomics)
* antlr (compiler frontend)
* cppitertools
* fmt format
* google benchmark
* google test
* yaml-cpp

View File

@ -1 +0,0 @@
*.out

View File

@ -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;
}

View File

@ -1 +0,0 @@
neo4j-driver==1.0.2

View File

@ -1,2 +0,0 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"

View File

@ -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);
}

View 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_;
};
}

View File

@ -1,7 +0,0 @@
#pragma once
#include <chrono>
using namespace std::chrono_literals;
using ms = std::chrono::milliseconds;

View File

@ -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;
};

View File

@ -8,12 +8,15 @@
#include "logging/default.hpp"
namespace utils {
/**
* @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
* near future. The handler is function that will be called when counter
* becomes zero or smaller than zero.
@ -151,3 +154,4 @@ class TimerScheduler {
std::thread run_thread;
std::atomic<bool> is_running;
};
}

View 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;
}

View File

@ -1,8 +1,8 @@
#define LOG_NO_INFO 1
#include "logging/default.hpp"
#include "logging/streams/stdout.hpp"
#include "query/preprocessor.hpp"
#include "utils/time/timer.hpp"
#include "benchmark/benchmark_api.h"
#include "yaml-cpp/yaml.h"

View File

@ -8,6 +8,7 @@
#include "utils/timer/timer.hpp"
using namespace std::chrono_literals;
using namespace utils;
/**
* Creates a test timer which will log timeout message at the timeout event.