#define _POSIX_C_SOURCE 199309L #include "benchmark.h" #include "resource_usage.h" #include #if defined(_WIN32) || defined(_WIN64) #include #else #include #endif /* ANSI color codes */ const char* COLOR_RED = "\033[31m"; const char* COLOR_GREEN = "\033[32m"; const char* COLOR_YELLOW = "\033[33m"; const char* COLOR_RESET = "\033[0m"; /* Maximum allowed average execution time per call in milliseconds */ const double MAX_ALLOWED_MS = 0.05; /* Default benchmark iteration counts */ const size_t DEFAULT_BENCHMARKS = 100; const size_t ITERATIONS_FAST = 1000; const size_t ITERATIONS_SLOW = 10; /* Volatile sink to prevent compiler optimizations removing the function call */ static volatile int sink; /** * @brief Cross-platform monotonic time in milliseconds */ static double now_ms(void) { #if defined(_WIN32) || defined(_WIN64) LARGE_INTEGER freq, counter; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&counter); return (double)counter.QuadPart * 1000.0 / (double)freq.QuadPart; #else struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec * 1000.0 + ts.tv_nsec / 1e6; #endif } double benchmark_func(const function_to_benchmark func, const char* arg, size_t benchmarks) { if (!func) return 0.0; if (benchmarks == 0) benchmarks = DEFAULT_BENCHMARKS; size_t warmup = benchmarks / 10; if (warmup > 1000) warmup = 1000; for (size_t i = 0; i < warmup; ++i) sink = func(arg); const double start = now_ms(); for (size_t i = 0; i < benchmarks; ++i) sink = func(arg); const double end = now_ms(); return (end - start) / benchmarks; } void report_result(const char* test_name, const int passed, const double avg_ms, const double max_allowed_ms) { const int is_pass = passed && (avg_ms <= max_allowed_ms); const char* status_color = is_pass ? COLOR_GREEN : COLOR_RED; const char* status_text = is_pass ? "PASS" : "FAIL"; if (!is_pass && avg_ms > max_allowed_ms) status_text = "SLOW"; printf("[avg %.6f ms] %s%s: %s%s\n", avg_ms, status_color, status_text, test_name, COLOR_RESET); if (!is_pass && avg_ms > max_allowed_ms) { printf(" %sReason:%s exceeded %.3f ms limit\n", COLOR_YELLOW, COLOR_RESET, max_allowed_ms); } } void benchmark_func_with_resources(const function_to_benchmark func, const char* arg, const size_t benchmarks, const char* label) { const double avg_ms = benchmark_func(func, arg, benchmarks); printf("[Benchmark] %s avg %.6f ms\n", label, avg_ms); print_resource_usage(label); }