implement basic logging system (timings + text)

This commit is contained in:
Dennis Eichhorn 2024-09-21 04:20:21 +02:00
parent f3cd6bb31f
commit 9374b5aa2c
7 changed files with 154 additions and 74 deletions

135
log/Log.h Normal file
View File

@ -0,0 +1,135 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_PLATFORM_WIN32_LOG_H
#define TOS_PLATFORM_WIN32_LOG_H
#include <stdio.h>
#include <string.h>
#include "../stdlib/Types.h"
#include "../platform/win32/UtilsWin32.h"
#include "../memory/RingMemory.h"
#ifndef LOG_LEVEL
#define LOG_LEVEL 0
#endif
#ifndef MAX_LOG_LENGTH
#define MAX_LOG_LENGTH 128
#endif
enum LogDataType {
LOG_DATA_VOID,
LOG_DATA_INT32,
LOG_DATA_UINT32,
LOG_DATA_INT64,
LOG_DATA_UINT64,
LOG_DATA_CHAR,
LOG_DATA_CHAR_STR,
LOG_DATA_FLOAT32,
LOG_DATA_FLOAT64
};
void log_to_file(RingMemory* logs, HANDLE fp)
{
// we don't log an empty log pool
if (logs->pos == 0 || !fp) {
return;
}
file_append(fp, (char *) logs->memory, logs->pos - 1);
memset(logs->memory, 0, logs->size);
// reset log position to start of memory pool
logs->pos = 0;
logs->start = 0;
}
void log(RingMemory* logs, const char* str, HANDLE fp = NULL, bool should_log = true, bool save = false)
{
if (!should_log) {
return;
}
size_t length = strlen(str);
ASSERT_SIMPLE(length < MAX_LOG_LENGTH);
char* temp = (char *) ring_get_memory(logs, length + 1);
strcpy(temp, str);
temp[length] = '\0';
if (fp != NULL && (save || logs->size - logs->pos < MAX_LOG_LENGTH)) {
log_to_file(logs, fp);
}
}
void log(RingMemory* logs, const char* format, LogDataType data_type, void* data, HANDLE fp = NULL, bool should_log = true, bool save = false)
{
if (!should_log) {
return;
}
if (data_type == LOG_DATA_VOID) {
log(logs, format, fp, true);
}
char* temp = (char *) ring_get_memory(logs, MAX_LOG_LENGTH);
switch (data_type) {
case LOG_DATA_INT32: {
sprintf(temp, format, *((int32 *) data));
} break;
case LOG_DATA_UINT32: {
sprintf(temp, format, *((uint32 *) data));
} break;
case LOG_DATA_INT64: {
sprintf(temp, format, *((int64 *) data));
} break;
case LOG_DATA_UINT64: {
sprintf(temp, format, *((uint64 *) data));
} break;
case LOG_DATA_CHAR: {
sprintf(temp, format, *((char *) data));
} break;
case LOG_DATA_CHAR_STR: {
sprintf(temp, format, *((char *) data));
} break;
case LOG_DATA_FLOAT32: {
sprintf(temp, format, *((f32 *) data));
} break;
case LOG_DATA_FLOAT64: {
sprintf(temp, format, *((f64 *) data));
} break;
}
if (fp != NULL && (save || logs->size - logs->pos < MAX_LOG_LENGTH)) {
log_to_file(logs, fp);
}
}
#if (LOG_LEVEL == 0)
// Don't perform any logging at log level 0
#define LOG(logs, str, fp, should_log, save) ((void) 0)
#define LOG_FORMAT(logs, format, data_type, data, fp, should_log, save) ((void) 0)
#define LOG_TO_FILE(logs, fp, should_log, save) ((void) 0)
#else
#define LOG(logs, str, fp, should_log, save) log((logs), (str), (fp), (should_log), (save))
#define LOG_FORMAT(logs, format, data_type, data, fp, should_log, save) log((logs), (format), (data_type), (data), (fp), (should_log), (save))
#define LOG_TO_FILE(logs, fp, should_log, save) log_to_file((logs), (fp), (should_log), (save))
#endif
#if DEBUG
#define DEBUG_LOG(logs, str, fp, should_log, save) log((logs), (str), (fp), (should_log), (save))
#define DEBUG_LOG_FORMAT(logs, format, data_type, data, fp, should_log, save) log((logs), (format), (data_type), (data), (fp), (should_log), (save))
#else
#define DEBUG_LOG(logs, str, fp, should_log, save) ((void) 0)
#define DEBUG_LOG_FORMAT(logs, format, data_type, data, fp, should_log, save) ((void) 0)
#endif
#endif

View File

@ -25,8 +25,6 @@ struct BufferMemory {
int alignment; int alignment;
}; };
// @todo implement memory usage visualization
inline inline
void buffer_alloc(BufferMemory* buf, uint64 size, int alignment = 1) void buffer_alloc(BufferMemory* buf, uint64 size, int alignment = 1)
{ {

View File

@ -29,8 +29,6 @@ struct ChunkMemory {
uint64* free; uint64* free;
}; };
// @todo implement memory usage visualization
inline inline
void chunk_alloc(ChunkMemory* buf, uint64 count, uint64 chunk_size, int alignment = 1) void chunk_alloc(ChunkMemory* buf, uint64 count, uint64 chunk_size, int alignment = 1)
{ {

View File

@ -33,9 +33,9 @@ struct DebugMemory {
#define DEBUG_MEMORY_RESET(mem) debug_memory_reset((mem)) #define DEBUG_MEMORY_RESET(mem) debug_memory_reset((mem))
#define DEBUG_MEMORY_FREE(mem, start, end) debug_memory_add_range((mem), (start), (end)) #define DEBUG_MEMORY_FREE(mem, start, end) debug_memory_add_range((mem), (start), (end))
#else #else
#define DEBUG_MEMORY(mem, start, end) ((void)0) #define DEBUG_MEMORY(mem, start, end) ((void) 0)
#define DEBUG_MEMORY_RESET(mem) ((void)0) #define DEBUG_MEMORY_RESET(mem) ((void) 0)
#define DEBUG_MEMORY_FREE(mem, start, end) ((void)0) #define DEBUG_MEMORY_FREE(mem, start, end) ((void) 0)
#endif #endif
void debug_memory_resize(DebugMemory* mem) void debug_memory_resize(DebugMemory* mem)

View File

@ -10,9 +10,11 @@
#define TOS_MEMORY_RING_MEMORY_H #define TOS_MEMORY_RING_MEMORY_H
#include <string.h> #include <string.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../utils/MathUtils.h" #include "../utils/MathUtils.h"
#include "../utils/TestUtils.h" #include "../utils/TestUtils.h"
#include "Allocation.h" #include "Allocation.h"
#include "BufferMemory.h" #include "BufferMemory.h"
#include "DebugMemory.h" #include "DebugMemory.h"
@ -37,8 +39,6 @@ struct RingMemory {
uint64 end; uint64 end;
}; };
// @todo implement memory usage visualization
inline inline
void ring_alloc(RingMemory* ring, uint64 size, int alignment = 1) void ring_alloc(RingMemory* ring, uint64 size, int alignment = 1)
{ {

View File

@ -299,6 +299,11 @@ file_copy(const char* src, const char* dst)
{ {
CopyFileA((LPCSTR) src, (LPCSTR) dst, false); CopyFileA((LPCSTR) src, (LPCSTR) dst, false);
} }
inline
void close_handle(HANDLE fp)
{
CloseHandle(fp);
}
inline inline
HANDLE get_append_handle(const char* path) HANDLE get_append_handle(const char* path)
@ -312,7 +317,7 @@ HANDLE get_append_handle(const char* path)
FILE_APPEND_DATA, FILE_APPEND_DATA,
0, 0,
NULL, NULL,
OPEN_EXISTING, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL,
NULL NULL
); );
@ -321,7 +326,7 @@ HANDLE get_append_handle(const char* path)
FILE_APPEND_DATA, FILE_APPEND_DATA,
0, 0,
NULL, NULL,
OPEN_EXISTING, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL,
NULL NULL
); );
@ -410,7 +415,6 @@ file_append(HANDLE fp, const char* file, size_t length)
return false; return false;
} }
CloseHandle(fp);
return true; return true;
} }
@ -490,43 +494,4 @@ inline void self_path(char* path)
GetModuleFileNameA(NULL, (LPSTR) path, MAX_PATH); GetModuleFileNameA(NULL, (LPSTR) path, MAX_PATH);
} }
void log_to_file(RingMemory* logs, HANDLE fp)
{
// we don't log an empty log pool
if (logs->pos == 0) {
return;
}
file_append(fp, (char *) logs->memory, logs->size);
memset(logs->memory, 0, logs->size);
// reset log position to start of memory pool
logs->pos = 0;
logs->start = 0;
}
// snprintf(logs->memory + logs->pos * MAX_LOG_LENGTH, MAX_LOG_LENGTH, "My text %s", str1);
void log(RingMemory* logs, const char* str, HANDLE fp = NULL)
{
size_t length = strlen(str);
ASSERT_SIMPLE(length < MAX_LOG_LENGTH);
char* temp = (char *) ring_get_memory(logs, length + 1);
strcpy(temp, str);
temp[length] = '\0';
if (fp != NULL && logs->size - logs->pos < MAX_LOG_LENGTH) {
log_to_file(logs, fp);
}
}
#if (LOG_LEVEL == 0)
// Don't perform any logging at log level 0
#define LOG(logs, str, fp) ((void)0)
#define LOG_TO_FILE(logs, fp) ((void)0)
#else
#define LOG(logs, str, fp) log(logs, str, fp);
#define LOG_TO_FILE(logs, fp) log_to_file(logs, fp);
#endif
#endif #endif

View File

@ -9,8 +9,8 @@
#ifndef TOS_UTILS_TEST_UTILS_H #ifndef TOS_UTILS_TEST_UTILS_H
#define TOS_UTILS_TEST_UTILS_H #define TOS_UTILS_TEST_UTILS_H
#include <time.h>
#include <stdio.h> #include <stdio.h>
#include <time.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#if _WIN32 #if _WIN32
@ -19,12 +19,9 @@
#include <x86intrin.h> #include <x86intrin.h>
#endif #endif
#define MAX_LOG_LENGTH 128
global_persist uint64 performance_count_frequency; global_persist uint64 performance_count_frequency;
struct TimingStat { struct TimingStat {
uint64 old_tick_count; uint64 old_tick_count;
uint64 new_tick_count;
uint64 delta_tick; uint64 delta_tick;
double delta_time; double delta_time;
@ -35,12 +32,12 @@ struct TimingStat {
inline inline
void update_timing_stat(TimingStat *stat) void update_timing_stat(TimingStat *stat)
{ {
stat->new_tick_count = __rdtsc(); uint64 new_tick_count = __rdtsc();
stat->delta_tick = stat->new_tick_count - stat->old_tick_count; stat->delta_tick = new_tick_count - stat->old_tick_count;
stat->delta_time = (double) stat->delta_tick / (double) performance_count_frequency; stat->delta_time = (double) stat->delta_tick / (double) performance_count_frequency;
stat->old_tick_count = stat->new_tick_count; stat->old_tick_count = new_tick_count;
} }
// Sometimes we want to only do logging in debug mode. // Sometimes we want to only do logging in debug mode.
@ -49,23 +46,10 @@ void update_timing_stat(TimingStat *stat)
#define UPDATE_TIMING_STAT(stat) update_timing_stat(stat) #define UPDATE_TIMING_STAT(stat) update_timing_stat(stat)
#define DEBUG_OUTPUT(str) OutputDebugStringA(str) #define DEBUG_OUTPUT(str) OutputDebugStringA(str)
#else #else
#define UPDATE_TIMING_STAT(stat) ((void)0) #define UPDATE_TIMING_STAT(stat) ((void) 0)
#define DEBUG_OUTPUT(str) ((void)0) #define DEBUG_OUTPUT(str) ((void) 0)
#endif #endif
void profile_function(const char* func_name, void (*func)(void*), void* data, int iterations)
{
clock_t start = clock();
for (int i = 0; i < iterations; ++i) {
func(data);
}
clock_t end = clock();
double elapsed_time = (double)(end - start) / CLOCKS_PER_SEC;
printf("Time taken by %s: %f seconds\n", func_name, elapsed_time);
}
#define ASSERT_EQUALS(a, b, t1, t2) \ #define ASSERT_EQUALS(a, b, t1, t2) \
({ \ ({ \
if ((a) == (b)) { \ if ((a) == (b)) { \
@ -132,7 +116,7 @@ void profile_function(const char* func_name, void (*func)(void*), void* data, in
*(volatile int *)0 = 0; \ *(volatile int *)0 = 0; \
} }
#else #else
#define ASSERT_SIMPLE(a) ((void)0) #define ASSERT_SIMPLE(a) ((void) 0)
#endif #endif
#define ASSERT_TRUE(a) \ #define ASSERT_TRUE(a) \