allocPool: Fix threading issue and add benchmark.
This commit is contained in:
parent
dead668fb7
commit
6cd26d5ee9
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.idea/*
|
||||||
|
cmake-build-debug/*
|
16
README.md
16
README.md
@ -12,3 +12,19 @@ This pool uses a hashmap and a pivot to make returnPtr(ptr) extremely fast.
|
|||||||
|
|
||||||
It will automatically grow when the max capacity is reached, though there will
|
It will automatically grow when the max capacity is reached, though there will
|
||||||
be a performance penalty.
|
be a performance penalty.
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
With a simple stub class and a pool of 10000 objects, using the pool to take a pointer
|
||||||
|
and give it back takes 3 ms vs 19 ms when allocating and deallocating by hand.
|
||||||
|
```
|
||||||
|
class stub {
|
||||||
|
public:
|
||||||
|
stub() {
|
||||||
|
for (int j{}; j < 1000; j++) { i++; }
|
||||||
|
};
|
||||||
|
void reset() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int i = 15;
|
||||||
|
};
|
||||||
|
```
|
@ -47,6 +47,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<T *> vec;
|
std::vector<T *> vec;
|
||||||
|
std::mutex positionMapMutex;
|
||||||
std::unordered_map<T *, size_t> positionMap;
|
std::unordered_map<T *, size_t> positionMap;
|
||||||
size_t pivot;
|
size_t pivot;
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ private:
|
|||||||
threads.reserve(amountOfThreads);
|
threads.reserve(amountOfThreads);
|
||||||
|
|
||||||
for (size_t i{}; i < amountOfThreads; i++)
|
for (size_t i{}; i < amountOfThreads; i++)
|
||||||
threads.emplace_back(&allocPool::initObjects, this, i, amountPerThreads);
|
threads.emplace_back(&allocPool::initObjects, this, i * amountPerThreads, amountPerThreads);
|
||||||
|
|
||||||
for (auto &t: threads)
|
for (auto &t: threads)
|
||||||
t.join();
|
t.join();
|
||||||
@ -72,6 +73,9 @@ private:
|
|||||||
for (size_t i{}; i < amount; i++) {
|
for (size_t i{}; i < amount; i++) {
|
||||||
// TODO: Be more cache friendly by making a vector per thread, then doing memcpy into the original vector.
|
// TODO: Be more cache friendly by making a vector per thread, then doing memcpy into the original vector.
|
||||||
vec[startIdx + i] = new T;
|
vec[startIdx + i] = new T;
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> guard(positionMapMutex);
|
||||||
|
for (size_t i{}; i < amount; i++) {
|
||||||
positionMap[vec[startIdx + i]] = i;
|
positionMap[vec[startIdx + i]] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
32
main.cpp
32
main.cpp
@ -1,7 +1,39 @@
|
|||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "tests.hpp"
|
#include "tests.hpp"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
tests t;
|
tests t;
|
||||||
t.runTests();
|
t.runTests();
|
||||||
|
|
||||||
|
auto startSlow{std::chrono::high_resolution_clock::now()};
|
||||||
|
stub *ptr{};
|
||||||
|
for (size_t i{}; i < 10000; i++) {
|
||||||
|
ptr = new stub();
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
auto endSlow{std::chrono::high_resolution_clock::now()};
|
||||||
|
|
||||||
|
std::cout << "Time (milliseconds) required for allocations without pool: " <<
|
||||||
|
std::chrono::duration_cast<std::chrono::milliseconds>(endSlow - startSlow).count() << "\n";
|
||||||
|
|
||||||
|
auto startAlloc{std::chrono::high_resolution_clock::now()};
|
||||||
|
allocPool<stub> a(10000);
|
||||||
|
auto endAlloc{std::chrono::high_resolution_clock::now()};
|
||||||
|
|
||||||
|
auto startFast{std::chrono::high_resolution_clock::now()};
|
||||||
|
for (size_t i{}; i < 10000; i++) {
|
||||||
|
ptr = a.getPtr();
|
||||||
|
a.returnPtr(ptr);
|
||||||
|
}
|
||||||
|
auto endFast{std::chrono::high_resolution_clock::now()};
|
||||||
|
|
||||||
|
std::cout << "Time (milliseconds) required for allocations with pool: " <<
|
||||||
|
std::chrono::duration_cast<std::chrono::milliseconds>(endFast - startFast).count() << "\n";
|
||||||
|
|
||||||
|
std::cout << "Time (milliseconds) required for real allocations when constructing pool: " <<
|
||||||
|
std::chrono::duration_cast<std::chrono::milliseconds>(endAlloc - startAlloc).count() << "\n";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
12
tests.cpp
12
tests.cpp
@ -25,3 +25,15 @@ ADD_TEST(allocPoolSimple) {
|
|||||||
pool.returnPtr(var4);
|
pool.returnPtr(var4);
|
||||||
pool.returnPtr(var3);
|
pool.returnPtr(var3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ADD_TEST(allocPoolSimple2) {
|
||||||
|
allocPool<stub> pool(10);
|
||||||
|
auto *var1{pool.getPtr()};
|
||||||
|
auto *var2{pool.getPtr()};
|
||||||
|
auto *var3{pool.getPtr()};
|
||||||
|
pool.returnPtr(var2);
|
||||||
|
auto *var4{pool.getPtr()};
|
||||||
|
pool.returnPtr(var1);
|
||||||
|
pool.returnPtr(var4);
|
||||||
|
pool.returnPtr(var3);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user