-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13 from mjshakir/fix_cmake
Fix cmake
- Loading branch information
Showing
15 changed files
with
566 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,7 @@ jobs: | |
uses: actions/checkout@v2 | ||
|
||
- name: Install dependencies | ||
run: sudo apt-get update && sudo apt-get install -y libgtest-dev cmake | ||
run: sudo apt-get update && sudo apt-get install -y libgtest-dev libbenchmark-dev cmake | ||
|
||
- name: Setup CMake and Ninja | ||
uses: lukka/[email protected] | ||
|
@@ -35,4 +35,13 @@ jobs: | |
|
||
- name: Test | ||
working-directory: build | ||
run: ctest --output-on-failure | ||
run: ctest --output-on-failure | ||
|
||
- name: Run PriorityQueue Benchmarks | ||
run: ./build/benchmarkbin/ThreadPool_PriorityQueue_Benchmark | ||
|
||
- name: Run ThreadTask Benchmarks | ||
run: ./build/benchmarkbin/ThreadPool_ThreadTask_Benchmark | ||
|
||
- name: Run ThreadPool Benchmarks | ||
run: ./build/benchmarkbin/ThreadPool_ThreadPool_Benchmark |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,7 @@ jobs: | |
uses: actions/checkout@v2 | ||
|
||
- name: Install dependencies | ||
run: sudo apt-get update && sudo apt-get install -y libgtest-dev cmake | ||
run: sudo apt-get update && sudo apt-get install -y libgtest-dev libbenchmark-dev cmake | ||
|
||
- name: Setup CMake and Ninja | ||
uses: lukka/[email protected] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,7 @@ jobs: | |
uses: actions/checkout@v2 | ||
|
||
- name: Install dependencies | ||
run: sudo apt-get update && sudo apt-get install -y libgtest-dev cmake | ||
run: sudo apt-get update && sudo apt-get install -y libgtest-dev libbenchmark-dev cmake | ||
|
||
- name: Setup CMake and Ninja | ||
uses: lukka/[email protected] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,12 @@ jobs: | |
vcpkg search gtest | ||
vcpkg install gtest:arm64-windows | ||
vcpkg integrate install | ||
- name: Install Benchmark | ||
run: | | ||
vcpkg search benchmark | ||
vcpkg install benchmark:x64-windows | ||
vcpkg integrate install | ||
- name: Setup CMake and Ninja | ||
uses: lukka/[email protected] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,12 @@ jobs: | |
vcpkg install gtest:x64-windows | ||
vcpkg integrate install | ||
- name: Install Benchmark | ||
run: | | ||
vcpkg search benchmark | ||
vcpkg install benchmark:x64-windows | ||
vcpkg integrate install | ||
- name: Setup CMake and Ninja | ||
uses: lukka/[email protected] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# Try Finding Installed Google Benchmark | ||
find_package(benchmark QUIET) | ||
#------------------------------------------------------------------------------------------ | ||
# Use Installed Version or Fetch | ||
if(NOT benchmark_FOUND) | ||
include(FetchContent) | ||
FetchContent_Declare( | ||
googlebenchmark | ||
GIT_REPOSITORY https://github.com/google/benchmark.git | ||
GIT_TAG main | ||
GIT_SHALLOW TRUE # Do a shallow clone to speed up the process | ||
) | ||
|
||
# This line ensures Google Benchmark uses the same runtime library | ||
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE) | ||
set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "" FORCE) | ||
|
||
FetchContent_MakeAvailable(googlebenchmark) | ||
add_library(benchmark::benchmark ALIAS benchmark) | ||
endif() | ||
#------------------------------------------------------------------------------------------ | ||
# Function to setup a benchmark executable | ||
function(create_benchmark_target TARGET_NAME SOURCE_FILE) | ||
# Correcting the file path according to the directory structure | ||
add_executable(${TARGET_NAME} ${SOURCE_FILE}) | ||
target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/include) | ||
|
||
# Set the output directories for benchmark executables | ||
set_target_properties(${TARGET_NAME} PROPERTIES | ||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/benchmarkbin | ||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/benchmarklib | ||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/benchmarklib | ||
) | ||
|
||
# Link the main project library and Google Benchmark | ||
target_link_libraries(${TARGET_NAME} PRIVATE ${PROJECT_NAME}) | ||
if(benchmark_FOUND) | ||
target_link_libraries(${TARGET_NAME} PRIVATE benchmark::benchmark) | ||
else() | ||
target_link_libraries(${TARGET_NAME} PRIVATE benchmark) | ||
endif() | ||
|
||
# Enable testing and add the benchmark to CTest | ||
enable_testing() | ||
add_test(NAME ${TARGET_NAME} COMMAND ${TARGET_NAME}) | ||
endfunction() | ||
#------------------------------------------------------------------------------------------ | ||
# Add the benchmarks without the 'benchmark/' prefix since we are already in the benchmark directory | ||
create_benchmark_target(${PROJECT_NAME}_PriorityQueue_Benchmark PriorityQueueBenchmark.cpp) | ||
create_benchmark_target(${PROJECT_NAME}_ThreadTask_Benchmark ThreadTaskBenchmark.cpp) | ||
create_benchmark_target(${PROJECT_NAME}_ThreadPool_Benchmark ThreadPoolBenchmark.cpp) | ||
#------------------------------------------------------------------------------------------ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
#include <random> | ||
#include <vector> | ||
#include <algorithm> | ||
|
||
#include <benchmark/benchmark.h> | ||
#include "PriorityQueue.hpp" | ||
|
||
using namespace ThreadPool; | ||
|
||
// Utility function to generate a random vector of integers | ||
std::vector<int> generate_random_vector(size_t size, int min = 0, int max = 1000000) { | ||
std::random_device rd; | ||
std::mt19937 gen(rd()); | ||
std::uniform_int_distribution<> dis(min, max); | ||
|
||
std::vector<int> vec(size); | ||
std::generate(vec.begin(), vec.end(), [&]() { return dis(gen); }); | ||
return vec; | ||
} | ||
|
||
static void BM_PriorityQueue_Push(benchmark::State& state) { | ||
PriorityQueue<int> pq; | ||
auto random_values = generate_random_vector(state.range(0)); | ||
for (auto _ : state) { | ||
for (const auto& value : random_values) { | ||
pq.push(value); | ||
} | ||
} | ||
state.SetComplexityN(state.range(0)); | ||
} | ||
BENCHMARK(BM_PriorityQueue_Push)->RangeMultiplier(10)->Range(1, 10000)->Complexity(benchmark::oAuto); | ||
|
||
static void BM_PriorityQueue_Emplace(benchmark::State& state) { | ||
PriorityQueue<int> pq; | ||
auto random_values = generate_random_vector(state.range(0)); | ||
for (auto _ : state) { | ||
for (const auto& value : random_values) { | ||
pq.emplace(value); | ||
} | ||
} | ||
state.SetComplexityN(state.range(0)); | ||
} | ||
BENCHMARK(BM_PriorityQueue_Emplace)->RangeMultiplier(10)->Range(1, 10000)->Complexity(benchmark::oAuto); | ||
|
||
static void BM_PriorityQueue_Top(benchmark::State& state) { | ||
PriorityQueue<int> pq; | ||
auto random_values = generate_random_vector(state.range(0)); | ||
for (const auto& value : random_values) { | ||
pq.push(value); | ||
} | ||
for (auto _ : state) { | ||
auto top = pq.top(); | ||
benchmark::DoNotOptimize(top); | ||
} | ||
state.SetComplexityN(state.range(0)); | ||
} | ||
BENCHMARK(BM_PriorityQueue_Top)->RangeMultiplier(10)->Range(1, 10000)->Complexity(benchmark::oAuto); | ||
|
||
static void BM_PriorityQueue_Pop(benchmark::State& state) { | ||
PriorityQueue<int> pq; | ||
auto random_values = generate_random_vector(state.range(0)); | ||
for (const auto& value : random_values) { | ||
pq.push(value); | ||
} | ||
for (auto _ : state) { | ||
if (!pq.empty()) { | ||
pq.pop(); | ||
} | ||
} | ||
state.SetComplexityN(state.range(0)); | ||
} | ||
BENCHMARK(BM_PriorityQueue_Pop)->RangeMultiplier(10)->Range(1, 10000)->Complexity(benchmark::oAuto); | ||
|
||
static void BM_PriorityQueue_Size(benchmark::State& state) { | ||
PriorityQueue<int> pq; | ||
auto random_values = generate_random_vector(state.range(0)); | ||
for (const auto& value : random_values) { | ||
pq.push(value); | ||
} | ||
for (auto _ : state) { | ||
auto size = pq.size(); | ||
benchmark::DoNotOptimize(size); | ||
} | ||
state.SetComplexityN(state.range(0)); | ||
} | ||
BENCHMARK(BM_PriorityQueue_Size)->RangeMultiplier(10)->Range(1, 10000)->Complexity(benchmark::oAuto); | ||
|
||
static void BM_PriorityQueue_RemoveTask(benchmark::State& state) { | ||
PriorityQueue<int> pq; | ||
auto random_values = generate_random_vector(state.range(0)); | ||
for (const auto& value : random_values) { | ||
pq.push(value); | ||
} | ||
for (auto _ : state) { | ||
if (!pq.empty()) { | ||
pq.remove(random_values[state.range(0) / 2]); | ||
} | ||
} | ||
state.SetComplexityN(state.range(0)); | ||
} | ||
BENCHMARK(BM_PriorityQueue_RemoveTask)->RangeMultiplier(10)->Range(1, 10000)->Complexity(benchmark::oAuto); | ||
|
||
BENCHMARK_MAIN(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#include <thread> | ||
#include <vector> | ||
#include <future> | ||
#include <chrono> | ||
#include <benchmark/benchmark.h> | ||
#include "ThreadPool.hpp" | ||
|
||
// Utility function to simulate work | ||
int simulate_work(int value) { | ||
std::this_thread::sleep_for(std::chrono::nanoseconds(10)); // Reduced sleep time to avoid prolonged blocking | ||
return value * 2; | ||
} | ||
|
||
// Benchmark for ThreadPool constructor and destructor | ||
static void BM_ThreadPool_Constructor(benchmark::State& state) { | ||
for (auto _ : state) { | ||
ThreadPool::ThreadPool<ThreadPool::ThreadMode::STANDARD> pool(state.range(0)); | ||
} | ||
state.SetComplexityN(state.range(0)); | ||
} | ||
BENCHMARK(BM_ThreadPool_Constructor)->RangeMultiplier(2)->Range(4, 64)->Complexity(benchmark::oAuto); | ||
|
||
// Benchmark for queueing tasks | ||
static void BM_ThreadPool_QueueTask(benchmark::State& state) { | ||
ThreadPool::ThreadPool<ThreadPool::ThreadMode::STANDARD> pool(state.range(0)); | ||
for (auto _ : state) { | ||
auto future = pool.queue(simulate_work, 42); | ||
benchmark::DoNotOptimize(future); | ||
} | ||
state.SetComplexityN(state.range(0)); | ||
} | ||
BENCHMARK(BM_ThreadPool_QueueTask)->RangeMultiplier(2)->Range(4, 64)->Complexity(benchmark::oAuto); | ||
|
||
// Benchmark for executing tasks | ||
static void BM_ThreadPool_ExecuteTask(benchmark::State& state) { | ||
ThreadPool::ThreadPool<ThreadPool::ThreadMode::STANDARD> pool(state.range(0)); | ||
for (auto _ : state) { | ||
auto future = pool.queue(simulate_work, 42); | ||
future.wait(); | ||
benchmark::DoNotOptimize(future.get()); | ||
} | ||
state.SetComplexityN(state.range(0)); | ||
} | ||
BENCHMARK(BM_ThreadPool_ExecuteTask)->RangeMultiplier(2)->Range(4, 64)->Complexity(benchmark::oAuto); | ||
|
||
// Benchmark for handling a burst of tasks | ||
static void BM_ThreadPool_BurstTasks(benchmark::State& state) { | ||
ThreadPool::ThreadPool<ThreadPool::ThreadMode::STANDARD> pool(state.range(0)); | ||
for (auto _ : state) { | ||
std::vector<std::future<int>> futures; | ||
for (int i = 0; i < state.range(1); ++i) { | ||
futures.push_back(pool.queue(simulate_work, i)); | ||
} | ||
for (auto& future : futures) { | ||
benchmark::DoNotOptimize(future.get()); | ||
} | ||
} | ||
state.SetComplexityN(state.range(0) * state.range(1)); | ||
} | ||
BENCHMARK(BM_ThreadPool_BurstTasks)->Ranges({{4, 64}, {10, 1000}})->Complexity(benchmark::oAuto); | ||
|
||
// Benchmark for priority-based task execution | ||
static void BM_ThreadPool_PriorityQueueTask(benchmark::State& state) { | ||
ThreadPool::ThreadPool<ThreadPool::ThreadMode::PRIORITY> pool(state.range(0)); | ||
for (auto _ : state) { | ||
auto task = pool.queue(true, simulate_work, 42); | ||
task.set_priority(10); | ||
benchmark::DoNotOptimize(task.get_future()); | ||
} | ||
state.SetComplexityN(state.range(0)); | ||
} | ||
BENCHMARK(BM_ThreadPool_PriorityQueueTask)->RangeMultiplier(2)->Range(4, 64)->Complexity(benchmark::oAuto); | ||
|
||
BENCHMARK_MAIN(); | ||
|
||
/* | ||
Time Complexity Analysis: | ||
1. ThreadPool Constructor/Destructor: | ||
- Complexity: O(1) per thread, as the number of threads created is fixed by the input range. | ||
- Reasoning: The constructor creates the worker threads, and the destructor joins them. | ||
2. Queueing a Task: | ||
- Complexity: O(1) per task. | ||
- Reasoning: Adding a task to the queue is a constant time operation. | ||
3. Executing a Task: | ||
- Complexity: O(1) per task. | ||
- Reasoning: Each task execution is independent, so adding and retrieving a task is O(1). | ||
4. Handling a Burst of Tasks: | ||
- Complexity: O(N * M), where N is the number of threads and M is the number of tasks per burst. | ||
- Reasoning: Each thread processes multiple tasks, and each task retrieval and execution takes O(1). | ||
5. Priority Queue Task Execution: | ||
- Complexity: O(log N) for adding a task, where N is the number of tasks in the priority queue. | ||
- Reasoning: PriorityQueue uses a heap, and adding/removing elements takes O(log N) time. | ||
*/ |
Oops, something went wrong.