diff --git a/Worksheet2/bumpall.hpp b/Worksheet2/bumpall.hpp index ce88b2a10807a548d08acf80f3d081168cacc7e4..44105bc64428193a8cd99b1e1671de78d8a5f91a 100644 --- a/Worksheet2/bumpall.hpp +++ b/Worksheet2/bumpall.hpp @@ -1,5 +1,6 @@ #include <cstddef> #include <iostream> +//Print lines are commented out for speed when running the benchmark class BumpAllocator { @@ -38,3 +39,5 @@ public: //std::cout << "Memory block deallocated!" << std::endl; } }; + +// Reference OPENAI CHATGPT, 2023. ChatGPT response to James Tulloch, (personal communication, 10th December) diff --git a/Worksheet2/bumpalld.hpp b/Worksheet2/bumpalld.hpp index 220f9801f9374bff2942b190c0eca28b44879f63..6c3cd3cac789e3e9b7f7e69cbd59092d46a1f819 100644 --- a/Worksheet2/bumpalld.hpp +++ b/Worksheet2/bumpalld.hpp @@ -1,5 +1,6 @@ #include <iostream> #include <cstddef> +//Print lines are commented out for speed when running the benchmark class BumpAllocator { char* start; // Pointer to the start of the allocated memory block @@ -38,3 +39,4 @@ public: } }; +// Reference OPENAI CHATGPT, 2023. ChatGPT response to James Tulloch, (personal communication, 10th December) \ No newline at end of file diff --git a/Worksheet2/readme.md b/Worksheet2/readme.md index 46a22343e53999c08eccdbd76c2d4f1dcaef6ca7..80ef582071c60ef490920fb5e01bb96a7bf557d2 100644 --- a/Worksheet2/readme.md +++ b/Worksheet2/readme.md @@ -4,96 +4,56 @@ James Tulloch - Student No: 21032766 ## *Task 1* -*Implement a class which prints the following output.* +*Implement a bump allocator.* -**Output:** - -> Hello world - String S is constructed and printed. \ -> Hello world - New scope, T is asssigned as an object which is a copy of S.\ -> Hello world - Prints the content of S again.\ -> e - Gets the char at the index of [1] in S, which is 'e'. \ -> Hello world - Prints the contents of S again.\ -> Hello world - Prints the contents of T again.\ -> HEllo world - S is modified so that the char at the index of [1] is now 'E'. - - -> [!To run this file:] -> clang++ filetest_string.cpp my_string.cpp -> ./a.out - -**Description:** - -The class my_string is correctly implemented and prints the ouput specified. It does so through using constructors, copy constructors and a destructor. It also has the functions get and set char, for the 4th line of output 'e' and the 7th line, where "Hello" is changed to be "HEllo" +The first implementation of the bump allocator is found in the bumpall.hpp file. +It correctly allocates the memory, stores its position and checks when allocating +if there is enough space left within the heap. ## *Task 2* -*Extend the programme to support automatic reference counting.* - -**Output:** - ->Hello world [1] - *One instance of S exists, reference count is 1.* \ ->Hello world [2] - *Two references of S now exist, with T being a \copy of S. The reference count is now 2.* \ ->Hello world [2] - *S is printed, there are still two objects which refer to the contents of S.* \ ->e - *No reference is printed because a specific index of s, [1], is being called instead of the object.* \ ->Hello world [2] - *S is printed again, the objects refering to its content are still 2. \* ->Hello world [2]- T is printed again, the the objects refering to the content of S are still 2. ->HEllo world [1] - T is now out of scope, and S[1] is modified to be 'E' instead of 'e'. There is now only one reference to the contents of S. - -> [!To run this file:] -> clang++ filetest_string.cpp my_string.cpp -> ./a.out +*Unit tests* -**Description:** +Implemented three tests, output show below. The first test file tests that memory is correctly +allocated and that the bump allocator performs as expected. The second file -The reference counting is implemented in the my_string class, with a pointer called "reference_count". This pointer keeps track of how many instances of the object are in existence, when they are constructed or destroyed. +**Output:** -## *Task 3* +>Test case 1: Create an allocator and allocate some memory +>Allocation of 50 bytes succeeded. -*Extend the programme to demonstrate a reference count of 0.* +>Test case 2: Attempt to allocate more than remaining space +>Allocation of 60 bytes failed as expected. -**Output:** +>Test case 3: Allocate remaining space +>Allocation of remaining 50 bytes succeeded. ->Hello world [1] \ ->Hello world [2] \ ->Hello world [2] \ ->e \ ->Hello world [2] \ ->Hello world [2] \ ->HEllo world [1] \ ->Reference count is now 0, freeing memory. - *Once the final object of S is destroyed, the memory is freed using 'nullptr', setting its value to 0.* +>Test case 4: Reset the allocator and allocate again +>Allocation of 100 bytes after reset succeeded. > [!To run this file:] -> -> clang++ -o task3 filetest_string.cpp my_string.cpp -> -> ./task3 +> clang++ test1.cpp -o test1 +> ./test1 -**Description:** - -The implementation deletes the pointer to the reference count using "nullptr" when the destructor is called. This returns the memory used to null or 0. +**Description:** -## *Task 4* +Implements four test cases: +* Allocating 50 bytes of 100 bytes available. +* Allocating 60 bytes to overflow the allocator. +* Allocating the further 50 bytes available. +* Resetting the allocator and allocating 100 bytes again. -Extend the example so reference counting is in a template rather than the "my_string" class. -**Output:** +## *Task 3* ->Hello world [1] \ ->Hello world [2] \ ->Hello world [2] \ ->e \ ->Hello world [2] \ ->Hello world [2] \ ->HEllo world [2] - *The output is the same as task 2, despite the template being called and instead of using "ref_count" from within the class.* \ +*Reverse the bump allocators direction and benchmark both implementations* +The direction of the bump allocator is reversed by switching the direction which +the "allocator" function uses and initialising its pointer at the end of the block of memory. -> [!To run this file:] -> clang++ -o task4 filetest_string.cpp my_string.cpp -> -> ./task4 - -**Description:** +When running the benchmark, you can comment out the different header files to switch between +them. -The class RefCount is implemented in the header file refcount.hpp. This file contains the functionality of task 3's "refcount" implementation inside of the "my_string" class and creates it as a template. +As expected the downwards facing bump allocator is much faster than upwards. diff --git a/Worksheet2/test1.cpp b/Worksheet2/test1.cpp index 24ce8622e20722f88c6708e8c2f86a44c305db31..ec2355b909d78e39c3cb83518c0d6935f2bf04b2 100644 --- a/Worksheet2/test1.cpp +++ b/Worksheet2/test1.cpp @@ -36,3 +36,5 @@ int main() { return 0; } + +// Reference OPENAI CHATGPT, 2023. ChatGPT response to James Tulloch, (personal communication, 10th December) \ No newline at end of file diff --git a/Worksheet2/test2.cpp b/Worksheet2/test2.cpp index 79447be1136ed975c754e7ae408abffb361a72d8..229ecfba7bfc563c4ddfed42ad2507390f91a134 100644 --- a/Worksheet2/test2.cpp +++ b/Worksheet2/test2.cpp @@ -1,40 +1,36 @@ +#include <chrono> #include <iostream> -#include <cstddef> -#include "bumpalld.hpp" // Include the BumpAllocator class definition - -// Simple Test Framework -#define TEST_MESSAGE(condition, message) \ - if (!(condition)) { \ - std::cout << "Test failed: " << message << std::endl; \ - return 1; \ - } \ - else { \ - std::cout << "Test passed: " << #condition << std::endl; \ - } - -int BumpTest() { - std::cout << "Running BumpTest..." << std::endl; - - BumpAllocator bumper(20 * sizeof(int)); // Create an allocator with space for 20 integers - - int *x = static_cast<int*>(bumper.allocate(10 * sizeof(int))); // Allocate space for 10 integers - TEST_MESSAGE(x != nullptr, "Failed to allocate 10 integers"); +#include "bumpalld.hpp" +//#include "bumpall.hpp" // Remove and comment the above to compare the compile times - int *y = static_cast<int*>(bumper.allocate(10 * sizeof(int))); // Allocate space for another 10 integers - TEST_MESSAGE(y != nullptr, "Failed to allocate another 10 integers"); - int *z = static_cast<int*>(bumper.allocate(10 * sizeof(int))); // Try to allocate space for 10 more integers - TEST_MESSAGE(z == nullptr, "Should have failed to allocate 10 more integers"); +void benchmarkBumpAllocator() { + const size_t blockSize = 1000000; // Size of the memory block + BumpAllocator allocator(blockSize); - return 0; // Return 0 to indicate success + // Example allocation/deallocation operations + for (int i = 0; i < 10000; ++i) { + allocator.allocate(100); // Allocate 100 bytes + allocator.reset(); // Reset the allocator for the next iteration + } } int main() { - int result = BumpTest(); - if (result != 0) { - std::cerr << "Some tests failed." << std::endl; - return 1; - } - std::cout << "All tests passed!" << std::endl; + using std::chrono::high_resolution_clock; + using std::chrono::duration_cast; + using std::chrono::duration; + using std::chrono::milliseconds; + + auto t1 = high_resolution_clock::now(); + benchmarkBumpAllocator(); + auto t2 = high_resolution_clock::now(); + + auto ms_int = duration_cast<milliseconds>(t2 - t1); + duration<double, std::milli> ms_double = t2 - t1; + + std::cout << ms_int.count() << "ms\n"; + std::cout << ms_double.count() << "ms\n"; return 0; } + +// Reference OPENAI CHATGPT, 2023. ChatGPT response to James Tulloch, (personal communication, 10th December) \ No newline at end of file diff --git a/Worksheet2/test3.cpp b/Worksheet2/test3.cpp deleted file mode 100644 index 4b81b528d782a63ae0fca7b336b95327282964ce..0000000000000000000000000000000000000000 --- a/Worksheet2/test3.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include <chrono> -#include <iostream> -#include "bumpalld.hpp" -//#include "bumpall.hpp" // Remove and comment the above to compare the compile times - - -void benchmarkBumpAllocator() { - const size_t blockSize = 1000000; // Size of the memory block - BumpAllocator allocator(blockSize); - - // Example allocation/deallocation operations - for (int i = 0; i < 10000; ++i) { - allocator.allocate(100); // Allocate 100 bytes - allocator.reset(); // Reset the allocator for the next iteration - } -} - -int main() { - using std::chrono::high_resolution_clock; - using std::chrono::duration_cast; - using std::chrono::duration; - using std::chrono::milliseconds; - - auto t1 = high_resolution_clock::now(); - benchmarkBumpAllocator(); - auto t2 = high_resolution_clock::now(); - - auto ms_int = duration_cast<milliseconds>(t2 - t1); - duration<double, std::milli> ms_double = t2 - t1; - - std::cout << ms_int.count() << "ms\n"; - std::cout << ms_double.count() << "ms\n"; - return 0; -}