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/*
|
18
README.md
18
README.md
@ -11,4 +11,20 @@ objects before giving them to another caller.
|
||||
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
|
||||
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:
|
||||
std::vector<T *> vec;
|
||||
std::mutex positionMapMutex;
|
||||
std::unordered_map<T *, size_t> positionMap;
|
||||
size_t pivot;
|
||||
|
||||
@ -59,7 +60,7 @@ private:
|
||||
threads.reserve(amountOfThreads);
|
||||
|
||||
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)
|
||||
t.join();
|
||||
@ -72,6 +73,9 @@ private:
|
||||
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.
|
||||
vec[startIdx + i] = new T;
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(positionMapMutex);
|
||||
for (size_t i{}; i < amount; i++) {
|
||||
positionMap[vec[startIdx + i]] = i;
|
||||
}
|
||||
}
|
||||
|
32
main.cpp
32
main.cpp
@ -1,7 +1,39 @@
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#include "tests.hpp"
|
||||
|
||||
int main() {
|
||||
tests t;
|
||||
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;
|
||||
}
|
||||
|
12
tests.cpp
12
tests.cpp
@ -24,4 +24,16 @@ ADD_TEST(allocPoolSimple) {
|
||||
pool.returnPtr(var1);
|
||||
pool.returnPtr(var4);
|
||||
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