Skip to content

Commit

Permalink
Merge pull request #265 from spacetelescope/feature/messaging_system
Browse files Browse the repository at this point in the history
Variable size buffer management
  • Loading branch information
ehpor authored Dec 23, 2024
2 parents de4e6ee + 7c5bd95 commit ff2e9d2
Show file tree
Hide file tree
Showing 10 changed files with 1,285 additions and 0 deletions.
18 changes: 18 additions & 0 deletions benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,25 @@ add_executable(timestamp timestamp.cpp)
target_include_directories(timestamp PUBLIC ../catkit_core)
target_link_libraries(timestamp PUBLIC catkit_core)

# Free list allocator benchmark
add_executable(free_list_allocator free_list_allocator.cpp)
target_include_directories(free_list_allocator PUBLIC ../catkit_core)
target_link_libraries(free_list_allocator PUBLIC catkit_core)

# Pool allocator benchmark
add_executable(pool_allocator pool_allocator.cpp)
target_include_directories(pool_allocator PUBLIC ../catkit_core)
target_link_libraries(pool_allocator PUBLIC catkit_core)

# Hash map benchmark
add_executable(hash_map hash_map.cpp)
target_include_directories(hash_map PUBLIC ../catkit_core)
target_link_libraries(hash_map PUBLIC catkit_core)

# Add install files
install(TARGETS datastream_latency DESTINATION bin)
install(TARGETS datastream_submit DESTINATION bin)
install(TARGETS timestamp DESTINATION bin)
install(TARGETS free_list_allocator DESTINATION bin)
install(TARGETS pool_allocator DESTINATION bin)
install(TARGETS hash_map DESTINATION bin)
141 changes: 141 additions & 0 deletions benchmarks/free_list_allocator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#include "FreeListAllocator.h"
#include "Timing.h"
#include <iostream>

void benchmark_linux_scalability()
{
const size_t N = 10000000;

const size_t NUM_BLOCKS = N * 2;
const size_t ALIGNMENT = 32;

auto *handles = new FreeListAllocator::BlockHandle[N];

size_t buffer_size = FreeListAllocator::ComputeMetadataBufferSize(NUM_BLOCKS);
char *buffer = new char[buffer_size];

auto allocator = FreeListAllocator::Create(buffer, NUM_BLOCKS, ALIGNMENT, NUM_BLOCKS * ALIGNMENT);

auto start = GetTimeStamp();

for (size_t i = 0; i < N; ++i)
{
handles[i] = allocator->Allocate(16);
}

for (size_t i = 0; i < N; ++i)
{
allocator->Deallocate(handles[i]);
}

auto end = GetTimeStamp();

std::cout << "Linux Scalability:" << std::endl;
std::cout << "Time: " << (end - start) / 1e9 << " sec" << std::endl;
std::cout << "Throughput: " << 2 * N / ((end - start) / 1e9) << " ops/s" << std::endl;
std::cout << "Time per operation: " << (end - start) / (2 * N) << " ns" << std::endl;

delete[] handles;
delete[] buffer;
}

void benchmark_threadtest()
{
const size_t N = 100;
const size_t M = 100000;
const size_t NUM_BLOCKS = N * 2;
const size_t ALIGNMENT = 32;

auto *handles = new FreeListAllocator::BlockHandle[M];

size_t buffer_size = FreeListAllocator::ComputeMetadataBufferSize(NUM_BLOCKS);
char *buffer = new char[buffer_size];

auto allocator = FreeListAllocator::Create(buffer, NUM_BLOCKS, ALIGNMENT, NUM_BLOCKS * ALIGNMENT);

auto start = GetTimeStamp();

for (size_t i = 0; i < M; ++i)
{
for (size_t j = 0; j < N; ++j)
{
handles[j] = allocator->Allocate(16);
}

for (size_t j = 0; j < N; ++j)
{
allocator->Deallocate(handles[j]);
}
}

auto end = GetTimeStamp();

std::cout << "Threadtest:" << std::endl;
std::cout << "Time: " << (end - start) / 1e9 << " sec" << std::endl;
std::cout << "Throughput: " << 2 * N * M / ((end - start) / 1e9) << " ops/s" << std::endl;
std::cout << "Time per operation: " << (end - start) / (2 * N * M) << " ns" << std::endl;

delete[] handles;
}

void benchmark_larson()
{
const size_t ALIGNMENT = 32;

const size_t N = 10000000;
const size_t M = 1000;
const size_t MIN_SIZE = 16;
const size_t MAX_SIZE = 128;
const size_t NUM_BLOCKS = M * 2;

auto *handles = new FreeListAllocator::BlockHandle[M];
for (size_t i = 0; i < M; ++i)
{
handles[i] = -1;
}

size_t buffer_size = FreeListAllocator::ComputeMetadataBufferSize(NUM_BLOCKS);
char *buffer = new char[buffer_size];

auto allocator = FreeListAllocator::Create(buffer, NUM_BLOCKS, ALIGNMENT, MAX_SIZE * NUM_BLOCKS);

auto *indices = new size_t[N];
auto *sizes = new size_t[N];
for (size_t i = 0; i < N; ++i)
{
indices[i] = rand() % M;
sizes[i] = (MIN_SIZE + (rand() % (MAX_SIZE - MIN_SIZE))) * ALIGNMENT;
}

auto start = GetTimeStamp();

for (size_t i = 0; i < N; ++i)
{
size_t index = indices[i];
size_t size = sizes[i];

if (handles[index] != -1)
{
allocator->Deallocate(handles[index]);
}

handles[index] = allocator->Allocate(size);
}

auto end = GetTimeStamp();
std::cout << "Larson benchmark:" << std::endl;
std::cout << "Time: " << (end - start) / 1e9 << " sec" << std::endl;
std::cout << "Throughput: " << (N * 2 - M) / ((end - start) / 1e9) << " ops/s" << std::endl;
std::cout << "Time per operation: " << (end - start) / (2 * N - M) << " ns" << std::endl;

delete[] handles;
}

int main(int argc, char **argv)
{
benchmark_linux_scalability();
benchmark_threadtest();
benchmark_larson();

return 0;
}
61 changes: 61 additions & 0 deletions benchmarks/hash_map.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "HashMap.h"
#include "Timing.h"

#include <iostream>

int main(int argc, char **argv)
{
typedef HashMap<uint16_t, 16384, 13> MyHashMap;

std::size_t buffer_size = MyHashMap::CalculateBufferSize();
std::cout << "Buffer size: " << buffer_size << " bytes" << std::endl;
char *buffer = new char[buffer_size];

MyHashMap map(buffer);
map.Initialize();

std::uint64_t total_time = 0;
std::size_t N = 5000;

for (size_t i = 0; i < N; ++i)
{
std::string key = "key" + std::to_string(i);

auto start = GetTimeStamp();
bool success = map.Insert(key, uint16_t(i));
auto end = GetTimeStamp();

if (!success)
{
std::cout << "Insertion failed." << std::endl;
}

total_time += end - start;
}

std::cout << "Insertion time: " << total_time / N << " ns" << std::endl;

total_time = 0;

for (size_t i = 0; i < N; ++i)
{
std::string key = "key" + std::to_string(i);

auto start = GetTimeStamp();
auto *value = map.Find(key);
auto end = GetTimeStamp();

if (value == nullptr || *value != i)
{
std::cout << "Key not found." << std::endl;
}

total_time += end - start;
}

std::cout << "Lookup time: " << total_time / N << " ns" << std::endl;

delete[] buffer;

return 0;
}
44 changes: 44 additions & 0 deletions benchmarks/pool_allocator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "PoolAllocator.h"
#include "Timing.h"
#include <iostream>

void benchmark_linux_scalability()
{
const size_t N = 10000000;
const size_t CAPACITY = 2 * N;

char *buffer = new char[PoolAllocator::CalculateMetadataBufferSize(CAPACITY)];

auto allocator = PoolAllocator::Create(buffer, CAPACITY);

auto *handles = new PoolAllocator::BlockHandle[N];

auto start = GetTimeStamp();

for (size_t i = 0; i < N; ++i)
{
handles[i] = allocator->Allocate();
}

for (size_t i = 0; i < N; ++i)
{
allocator->Deallocate(handles[i]);
}

auto end = GetTimeStamp();

std::cout << "Linux Scalability:" << std::endl;
std::cout << "Time: " << (end - start) / 1e9 << " sec" << std::endl;
std::cout << "Throughput: " << 2 * N / ((end - start) / 1e9) << " ops/s" << std::endl;
std::cout << "Time per operation: " << (end - start) / (2 * N) << " ns" << std::endl;

delete[] handles;
delete[] buffer;
}

int main(int argc, char **argv)
{
benchmark_linux_scalability();

return 0;
}
2 changes: 2 additions & 0 deletions catkit_core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ add_library(catkit_core STATIC
Tracing.cpp
Types.cpp
Util.cpp
PoolAllocator.cpp
FreeListAllocator.cpp
proto/core.pb.cc
proto/logging.pb.cc
proto/testbed.pb.cc
Expand Down
Loading

0 comments on commit ff2e9d2

Please sign in to comment.