Startup improvements (#639)
* Benchmark for testing startup performance. * Make pool pass spare space to pooled item The pool will result in power of 2 allocations as it doesn't have a local state when it is initially set up. This commit passes this extra space to the constructor of the pooled type, so that it can be feed into the freshly created allocator. Co-authored-by: Nathaniel Wesley Filardo <nfilardo@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
126e77f2a5
commit
5543347543
@@ -11,7 +11,7 @@ struct PoolAEntry : Pooled<PoolAEntry>
|
||||
{
|
||||
int field;
|
||||
|
||||
PoolAEntry() : field(1){};
|
||||
PoolAEntry(Range<capptr::bounds::Alloc>&) : field(1){};
|
||||
};
|
||||
|
||||
using PoolA = Pool<PoolAEntry, Alloc::Config>;
|
||||
@@ -20,8 +20,8 @@ struct PoolBEntry : Pooled<PoolBEntry>
|
||||
{
|
||||
int field;
|
||||
|
||||
PoolBEntry() : field(0){};
|
||||
PoolBEntry(int f) : field(f){};
|
||||
PoolBEntry(Range<capptr::bounds::Alloc>&) : field(0){};
|
||||
PoolBEntry(Range<capptr::bounds::Alloc>&, int f) : field(f){};
|
||||
};
|
||||
|
||||
using PoolB = Pool<PoolBEntry, Alloc::Config>;
|
||||
@@ -30,7 +30,7 @@ struct PoolLargeEntry : Pooled<PoolLargeEntry>
|
||||
{
|
||||
std::array<int, 2'000'000> payload;
|
||||
|
||||
PoolLargeEntry()
|
||||
PoolLargeEntry(Range<capptr::bounds::Alloc>&)
|
||||
{
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
@@ -48,7 +48,7 @@ struct PoolSortEntry : Pooled<PoolSortEntry<order>>
|
||||
{
|
||||
int field;
|
||||
|
||||
PoolSortEntry(int f) : field(f){};
|
||||
PoolSortEntry(Range<capptr::bounds::Alloc>&, int f) : field(f){};
|
||||
};
|
||||
|
||||
template<bool order>
|
||||
|
||||
94
src/test/perf/startup/startup.cc
Normal file
94
src/test/perf/startup/startup.cc
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "test/opt.h"
|
||||
#include "test/setup.h"
|
||||
#include "test/usage.h"
|
||||
#include "test/xoroshiro.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <snmalloc/snmalloc.h>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
using namespace snmalloc;
|
||||
|
||||
std::vector<uint64_t> counters{};
|
||||
|
||||
template<typename F>
|
||||
class ParallelTest
|
||||
{
|
||||
private:
|
||||
std::atomic<bool> flag = false;
|
||||
std::atomic<size_t> ready = 0;
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
std::atomic<size_t> complete = 0;
|
||||
size_t cores;
|
||||
F f;
|
||||
|
||||
void run(size_t id)
|
||||
{
|
||||
auto prev = ready.fetch_add(1);
|
||||
if (prev + 1 == cores)
|
||||
{
|
||||
start = Aal::tick();
|
||||
flag = true;
|
||||
}
|
||||
while (!flag)
|
||||
Aal::pause();
|
||||
|
||||
f(id);
|
||||
|
||||
prev = complete.fetch_add(1);
|
||||
if (prev + 1 == cores)
|
||||
{
|
||||
end = Aal::tick();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
ParallelTest(F&& f, size_t cores) : cores(cores), f(std::forward<F>(f))
|
||||
{
|
||||
std::thread* t = new std::thread[cores];
|
||||
|
||||
for (size_t i = 0; i < cores; i++)
|
||||
{
|
||||
t[i] = std::thread(&ParallelTest::run, this, i);
|
||||
}
|
||||
// Wait for all the threads.
|
||||
for (size_t i = 0; i < cores; i++)
|
||||
{
|
||||
t[i].join();
|
||||
}
|
||||
|
||||
delete[] t;
|
||||
}
|
||||
|
||||
uint64_t time()
|
||||
{
|
||||
return end - start;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
counters.resize(std::thread::hardware_concurrency());
|
||||
|
||||
ParallelTest test(
|
||||
[](size_t id) {
|
||||
auto start = Aal::tick();
|
||||
auto& alloc = snmalloc::ThreadAlloc::get();
|
||||
alloc.dealloc(alloc.alloc(1));
|
||||
auto end = Aal::tick();
|
||||
counters[id] = end - start;
|
||||
},
|
||||
counters.size());
|
||||
|
||||
std::cout << "Taken: " << test.time() << std::endl;
|
||||
std::sort(counters.begin(), counters.end());
|
||||
uint64_t start = 0;
|
||||
for (auto counter : counters)
|
||||
{
|
||||
std::cout << "Thread time " << counter << " (" << counter - start << ")"
|
||||
<< std::endl;
|
||||
start = counter;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user