Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variable size buffer management #265

Merged
merged 34 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
39aec8a
Add a hash map for fixed-sized string keys.
ehpor Nov 27, 2024
09dd48a
Add a pool allocator that can work from shared memory.
ehpor Nov 27, 2024
a744542
Make pool allocator only manage an outside buffer.
ehpor Nov 27, 2024
92ad8da
Put implementation into inl file.
ehpor Nov 29, 2024
7491502
Fix typos.
ehpor Dec 2, 2024
ca90158
Add a lock-free free list allocator.
ehpor Dec 6, 2024
7b7f191
Check for coalecense requirements before owning block A.
ehpor Dec 6, 2024
abe8d2f
Add benchmarks for FreeListAllocator.
ehpor Dec 6, 2024
9684a46
Add threadtest benchmark.
ehpor Dec 6, 2024
b77b24c
Add benchmark for pool allocator.
ehpor Dec 6, 2024
bbcb886
Fix for expected cannot be atomic.
ehpor Dec 6, 2024
35542f6
Fix typename compiler warning.
ehpor Dec 6, 2024
2fd43a4
Add missing include.
ehpor Dec 6, 2024
c610187
Use 32bit offset and size.
ehpor Dec 7, 2024
b7543ce
Put free-flag on the size (since it's usually smaller).
ehpor Dec 7, 2024
7cd9c22
Fix typo.
ehpor Dec 7, 2024
53c3376
Use an external buffer.
ehpor Dec 7, 2024
267cee0
Refactor pool allocator to use an external buffer.
ehpor Dec 11, 2024
f9f77b3
Refactor free list allocator to use external buffer.
ehpor Dec 11, 2024
0ff6bcf
Fix import to use C++ version.
ehpor Dec 11, 2024
d5ed5af
Copy using std::copy().
ehpor Dec 11, 2024
1062563
Rename and fix hash map implementation.
ehpor Dec 12, 2024
3120d84
Convert indentation to tabs.
ehpor Dec 12, 2024
1fba625
Add benchmark for hash map.
ehpor Dec 12, 2024
1346321
Import cstring library for strcmp().
ehpor Dec 12, 2024
9545c86
Use size_t for number of blocks.
ehpor Dec 12, 2024
61d1e0e
Compute time per operation in ns.
ehpor Dec 12, 2024
613d263
Add maximum key length check, safe string compare, and byte packing.
ehpor Dec 13, 2024
97cd3d0
Do not return a const pointer.
ehpor Dec 20, 2024
25c9c5d
Use string_view instead of c or c++ strings.
ehpor Dec 20, 2024
a0cfe0b
Fix fence-post counting issue.
ehpor Dec 20, 2024
820b565
Use Open() and Create().
ehpor Dec 20, 2024
8cbc70c
Use Open() and Create() functions instead of Initialize().
ehpor Dec 20, 2024
7c5bd95
Use actual number of blocks, not read from non-initialized memory.
ehpor Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading