Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
39 changes: 28 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
cmake_minimum_required (VERSION 3.5)
project (memory-allocators LANGUAGES CXX)
cmake_minimum_required(VERSION 3.5)
project(memory-allocators LANGUAGES CXX)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(SOURCES src/Allocator.cpp
src/CAllocator.cpp
src/LinearAllocator.cpp
src/StackAllocator.cpp
src/PoolAllocator.cpp
src/FreeListAllocator.cpp
src/Benchmark.cpp
src/main.cpp)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()

set(SOURCES
src/CAllocator.cpp
src/LinearAllocator.cpp
src/StackAllocator.cpp
src/PoolAllocator.cpp
src/FreeListAllocator.cpp
src/Benchmark.cpp
src/main.cpp)

add_executable(main ${SOURCES})

target_include_directories(main PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/includes)
target_compile_features(main PRIVATE cxx_std_11)

target_compile_options(main PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang>:
-Wall -Wextra -Wpedantic -Wshadow -Wnon-virtual-dtor
-Wcast-align -Woverloaded-virtual -Wnull-dereference>
$<$<CONFIG:Release>:-O3 -march=native>
$<$<CONFIG:Debug>:-O0 -g -fsanitize=address,undefined>)

target_link_options(main PRIVATE
$<$<CONFIG:Debug>:-fsanitize=address,undefined>)
20 changes: 12 additions & 8 deletions includes/Allocator.h
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
#ifndef ALLOCATOR_H
#define ALLOCATOR_H

#include <cstddef> // size_t
#include <cstddef>

class Allocator {
protected:
std::size_t m_totalSize;
std::size_t m_used;
std::size_t m_used;
std::size_t m_peak;

public:

Allocator(const std::size_t totalSize) : m_totalSize { totalSize }, m_used { 0 }, m_peak { 0 } { }
explicit Allocator(const std::size_t totalSize) noexcept : m_totalSize(totalSize), m_used(0), m_peak(0) {}

virtual ~Allocator() noexcept {
m_totalSize = 0;
}

virtual ~Allocator() { m_totalSize = 0; }
Allocator(const Allocator&) = delete;
Allocator& operator=(const Allocator&) = delete;

virtual void* Allocate(const std::size_t size, const std::size_t alignment = 0) = 0;
virtual void* Allocate(std::size_t size, std::size_t alignment = 0) = 0;

virtual void Free(void* ptr) = 0;

Expand All @@ -23,5 +28,4 @@ class Allocator {
friend class Benchmark;
};

#endif /* ALLOCATOR_H */

#endif /* ALLOCATOR_H */
68 changes: 27 additions & 41 deletions includes/Benchmark.h
Original file line number Diff line number Diff line change
@@ -1,73 +1,59 @@
#ifndef BENCHMARK_H
#define BENCHMARK_H

#include <time.h> // timespec
#include <cstddef> // std::size_t
#include <chrono>
#include <ratio>
#include <cstddef> // std::size_t
#include <random>
#include <vector>

#include "Allocator.h" // base class allocator
#include "IO.h"

#if 0
#define OPERATIONS (m_nOperations)
#else
#define OPERATIONS (10)
#endif

struct BenchmarkResults
{
std::size_t Operations;
std::chrono::milliseconds Milliseconds;
double OperationsPerSec;
double TimePerOperation;
std::size_t Operations;
std::chrono::nanoseconds Nanoseconds;
double OperationsPerSec;
double TimePerOperation;
std::size_t MemoryPeak;
};

class Benchmark {
public:
Benchmark() = delete;
explicit Benchmark(unsigned int nOperations) noexcept;

Benchmark(const unsigned int nOperations) : m_nOperations { nOperations } { }
void SingleAllocation(Allocator* allocator, std::size_t size, std::size_t alignment);
void SingleFree(Allocator* allocator, std::size_t size, std::size_t alignment);

void SingleAllocation(Allocator* allocator, const std::size_t size, const std::size_t alignment);
void SingleFree(Allocator* allocator, const std::size_t size, const std::size_t alignment);
void MultipleAllocation(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments);
void MultipleFree(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments);

void MultipleAllocation(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments);
void MultipleFree(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments);

void RandomAllocation(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments);
void RandomFree(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments);
void RandomAllocation(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments);
void RandomFree(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments);

private:
void PrintResults(const BenchmarkResults& results) const;

void RandomAllocationAttr(const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments, std::size_t & size, std::size_t & alignment);
void PrintResults(const BenchmarkResults& results) const;

const BenchmarkResults buildResults(std::size_t nOperations, std::chrono::milliseconds&& ellapsedTime, const std::size_t memoryUsed) const;

void SetStartTime() noexcept { Start = std::chrono::high_resolution_clock::now(); }
void RandomAllocationAttr(const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments, std::size_t& size, std::size_t& alignment) noexcept;

void SetFinishTime() noexcept { Finish = std::chrono::high_resolution_clock::now(); }
BenchmarkResults BuildResults(std::size_t nOperations, std::chrono::nanoseconds elapsedTime, std::size_t memoryPeak) const noexcept;

void SetElapsedTime() noexcept { TimeElapsed = std::chrono::duration_cast<std::chrono::milliseconds>(Finish - Start); }

void StartRound() noexcept { SetStartTime(); }

void FinishRound() noexcept
{
SetFinishTime();
SetElapsedTime();
void StartRound() noexcept {
m_start = std::chrono::high_resolution_clock::now();
}

private:
std::size_t m_nOperations;
void FinishRound() noexcept {
m_finish = std::chrono::high_resolution_clock::now();
m_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(m_finish - m_start);
}

std::chrono::time_point<std::chrono::high_resolution_clock> Start;
std::chrono::time_point<std::chrono::high_resolution_clock> Finish;
unsigned int m_nOperations;
std::mt19937 m_rng;

std::chrono::milliseconds TimeElapsed;
std::chrono::time_point<std::chrono::high_resolution_clock> m_start;
std::chrono::time_point<std::chrono::high_resolution_clock> m_finish;
std::chrono::nanoseconds m_elapsed;
};

#endif /* BENCHMARK_H */
16 changes: 9 additions & 7 deletions includes/CAllocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@
#include "Allocator.h"

class CAllocator : public Allocator {
private:
bool m_lastWasAligned;

public:
CAllocator();
CAllocator() noexcept;

virtual ~CAllocator();
virtual ~CAllocator() noexcept;

virtual void* Allocate(const std::size_t size, const std::size_t alignment = 0) override;
virtual void* Allocate(std::size_t size, std::size_t alignment = 0);

virtual void Free(void* ptr) override;
virtual void Free(void* ptr);

virtual void Init() override;
virtual void Init();
};

#endif /* CALLOCATOR_H */

#endif /* CALLOCATOR_H */
18 changes: 10 additions & 8 deletions includes/DoublyLinkedList.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef DOUBLYLINKEDLIST_H
#define DOUBLYLINKEDLIST_H

#include <cstddef>

template <class T>
class DoublyLinkedList {
public:
Expand All @@ -10,16 +12,16 @@ class DoublyLinkedList {
Node* next;
};
Node* head;
public:
DoublyLinkedList();

void insert(Node* previousNode, Node* newNode);
void remove(Node* deleteNode);
private:
DoublyLinkedList(DoublyLinkedList &doublyLinkedList);
DoublyLinkedList() : head(NULL) {}

DoublyLinkedList(const DoublyLinkedList&) = delete;
DoublyLinkedList& operator=(const DoublyLinkedList&) = delete;

void insert(Node* previousNode, Node* newNode) noexcept;
void remove(Node* deleteNode) noexcept;
};

#include "DoublyLinkedListImpl.h"

#endif /* DOUBLYLINKEDLIST_H */

#endif /* DOUBLYLINKEDLIST_H */
75 changes: 26 additions & 49 deletions includes/DoublyLinkedListImpl.h
Original file line number Diff line number Diff line change
@@ -1,60 +1,37 @@
#include "DoublyLinkedList.h"

template <class T>
DoublyLinkedList<T>::DoublyLinkedList() {
void DoublyLinkedList<T>::insert(Node* previousNode, Node* newNode) noexcept {
if (previousNode == NULL) {
newNode->previous = NULL;
newNode->next = head;

}
if (head != NULL)
head->previous = newNode;

template <class T>
void DoublyLinkedList<T>::insert(Node* previousNode, Node* newNode) {
if (previousNode == nullptr) {
// Is the first node
if (head != nullptr) {
// The list has more elements
newNode->next = head;
newNode->next->previous = newNode;
}else {
newNode->next = nullptr;
}
head = newNode;
head->previous = nullptr;
} else {
if (previousNode->next == nullptr){
// Is the last node
previousNode->next = newNode;
newNode->next = nullptr;
}else {
// Is a middle node
newNode->next = previousNode->next;
if (newNode->next != nullptr){
newNode->next->previous = newNode;
}
previousNode->next = newNode;
newNode->previous = previousNode;
}
}
else {
newNode->previous = previousNode;
newNode->next = previousNode->next;

if (previousNode->next != NULL)
previousNode->next->previous = newNode;

previousNode->next = newNode;
}
}

template <class T>
void DoublyLinkedList<T>::remove(Node* deleteNode) {
if (deleteNode->previous == nullptr){
// Is the first node
if (deleteNode->next == nullptr){
// List only has one element
head = nullptr;
}else {
// List has more elements
head = deleteNode->next;
head->previous = nullptr;
}
}else {
if (deleteNode->next == nullptr){
// Is the last node
deleteNode->previous->next = nullptr;
}else {
// Middle node
deleteNode->previous->next = deleteNode->next;
deleteNode->next->previous = deleteNode->previous;
}
}
void DoublyLinkedList<T>::remove(Node* deleteNode) noexcept {
if (deleteNode->previous != NULL)
deleteNode->previous->next = deleteNode->next;
else
head = deleteNode->next;

if (deleteNode->next != NULL)
deleteNode->next->previous = deleteNode->previous;

deleteNode->previous = NULL;
deleteNode->next = NULL;
}
Loading