This commit is contained in:
Victor Olin 2023-03-21 17:35:33 +01:00
parent 7105c570d9
commit 87dc0fef2d
6 changed files with 135 additions and 5 deletions

View file

@ -5,6 +5,13 @@
namespace GC
{
/**
* The basic element of what can be stored on
* the heap. A chunk contains a start address
* on the actual heap, the size of memory that
* is allocated at that address and if the
* chunk is reachable (marked).
*/
struct Chunk
{
bool m_marked {false};

View file

@ -9,7 +9,9 @@
namespace GC
{
/**
* Types of events that can occur on the heap.
*/
enum GCEventType
{
HeapInit,
@ -24,6 +26,9 @@ namespace GC
ProfilerDispose
};
/**
* Stores metadeta about an event on the heap.
*/
class GCEvent
{
private:

View file

@ -15,7 +15,10 @@
namespace GC
{
/**
* Flags for the collect overlead for conditional
* collection (mark/sweep/free/all).
*/
enum CollectOption {
MARK=0x1,
SWEEP=0x2,
@ -24,9 +27,16 @@ namespace GC
COLLECT_ALL=0x7
};
/**
* The heap class to represent the heap for the
* garbage collection. The heap is a singleton
* instance and can be retrieved by Heap::the()
* inside the heap class. The heap is represented
* by a char array of size 65536 and can enable
* a profiler to track the actions on the heap.
*/
class Heap
{
private:
Heap() : m_heap(static_cast<char *>(malloc(HEAP_SIZE))) {}
@ -35,6 +45,14 @@ namespace GC
std::free((char *)m_heap);
}
/**
* If m_instance is a nullptr (the singleton has not
* been initialized yet) initialize the singleton
* and return the pointer. Otherwise return the
* previously initialized pointer.
*
* @returns The pointer to the heap singleton.
*/
static Heap *the()
{
if (m_instance) // if m_instance is not a nullptr
@ -43,6 +61,16 @@ namespace GC
return m_instance;
}
/**
* Advances an iterator and returns an element
* at position `n`.
*
* @param list The list to retrieve an element from.
*
* @param n The position to retrieve an element at.
*
* @returns The pointer to the chunk at position n in list.
*/
static Chunk *get_at(std::vector<Chunk *> &list, size_t n)
{
auto iter = list.begin();
@ -52,6 +80,13 @@ namespace GC
return *iter;
}
/**
* Returns a bool whether the profiler is enabled
* or not.
*
* @returns True or false if the profiler is enabled
* or disabled respectively.
*/
inline bool profiler_enabled() {
auto heap = Heap::the();
return heap->m_profiler_enable;
@ -60,7 +95,6 @@ namespace GC
char *const m_heap;
size_t m_size {0};
inline static Heap *m_instance {nullptr};
// size_t m_allocated_size {0};
uintptr_t *m_stack_top {nullptr};
bool m_profiler_enable {false};
@ -85,6 +119,7 @@ namespace GC
* that the address of the topmost stack frame is
* saved as the limit for scanning the stack in collect.
*/
static void init();
static void dispose();
static void *alloc(size_t size);

View file

@ -16,6 +16,15 @@ namespace GC {
delete c;
}
/**
* Returns the instance of the Profiler singleton.
* If m_instance is the nullptr and the profiler
* is not initialized yet, initialize it and return
* the pointer to it. Otherwise return the previously
* initialized pointer.
*
* @returns The pointer to the profiler singleton.
*/
static Profiler *the()
{
if (m_instance)

View file

@ -7,27 +7,54 @@
namespace GC
{
/**
* @returns The type of the event
*/
GCEventType GCEvent::get_type()
{
return m_type;
}
/**
* @returns The time the event happened in
* the form of time_t.
*/
std::time_t GCEvent::get_time_stamp()
{
return m_timestamp;
}
/**
* If the event is related to a chunk, this
* function returns the chunk that it is
* related to. If the event is independent
* of a chunk, it returns the nullptr.
*
* @returns A chunk pointer or the nullptr.
*/
const Chunk *GCEvent::get_chunk()
{
return m_chunk;
}
/**
* If the event is an AllocStart event, this
* returns the size of the alloc() request.
* otherwise this returns 0.
*
* @returns A number representing the number
* of bytes requested to alloc()
* or 0 if the event is not an
* AllocStart event.
*/
size_t GCEvent::get_size()
{
return m_size;
}
/**
* @returns The string conversion of the event type.
*/
const char *GCEvent::type_to_string()
{
switch (m_type)

View file

@ -13,6 +13,11 @@
namespace GC
{
/**
* Records an event independent of a chunk.
*
* @param type The type of event to record.
*/
void Profiler::record(GCEventType type)
{
auto event = new GCEvent(type);
@ -20,6 +25,14 @@ namespace GC
profiler->m_events.push_back(event);
}
/**
* This overload is only used with an AllocStart
* event.
*
* @param type The type of event to record.
*
* @param size The size of requested to alloc().
*/
void Profiler::record(GCEventType type, size_t size)
{
auto event = new GCEvent(type, size);
@ -27,6 +40,14 @@ namespace GC
profiler->m_events.push_back(event);
}
/**
* Records an event related to a chunk.
*
* @param type The type of event to record.
*
* @param chunk The chunk the event is connected
* to.
*/
void Profiler::record(GCEventType type, Chunk *chunk)
{
// Create a copy of chunk to store in the profiler
@ -39,6 +60,10 @@ namespace GC
profiler->m_events.push_back(event);
}
/**
* Prints the history of the recorded events
* to a log file in the /tests/logs folder.
*/
void Profiler::dump_trace()
{
auto profiler = Profiler::the();
@ -85,6 +110,12 @@ namespace GC
fstr << "--------------------------------" << std::endl;
}
/**
* Deletes the profiler singleton and all
* the events recorded after recording
* the ProfilerDispose event and dumping
* the history to a log file.
*/
void Profiler::dispose()
{
Profiler::record(ProfilerDispose);
@ -93,6 +124,13 @@ namespace GC
delete profiler;
}
/**
* Creates a filestream for the future
* log file to print the history to in
* dump_trace().
*
* @returns The output stream to the file.
*/
std::ofstream Profiler::create_file_stream()
{
// get current time
@ -114,6 +152,15 @@ namespace GC
return fstr;
}
/**
* This function retrieves the current path of the
* executable to use for log files.
*
* @returns The path to the logs folder.
*
* @throws A runtime error if the call
* to readlink() fails.
*/
std::string Profiler::get_log_folder()
{
char buffer[1024];