// SPDX-License-Identifier: GPL-3.0-or-later // // This file is part of CProof. // See LICENSE for the full GPLv3 text and the special OpenSSL linking exception. #include "bench_common.h" #include #include #include #include #include #include #include #include #include double bench_now_ms(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (double)ts.tv_sec * 1000.0 + (double)ts.tv_nsec / 1.0e6; } char* bench_fmt_bytes(uint64_t bytes) { static const char* units[] = { "B", "KB", "MB", "GB", "TB" }; int u = 0; double v = (double)bytes; while (v >= 1024.0 && u < 4) { v /= 1024.0; u++; } if (u == 0) return g_strdup_printf("%" G_GUINT64_FORMAT " %s", bytes, units[u]); return g_strdup_printf("%.2f %s", v, units[u]); } char* bench_fmt_ms(double ms) { if (ms < 1.0) return g_strdup_printf("%.0f us", ms * 1000.0); if (ms < 1000.0) return g_strdup_printf("%.1f ms", ms); if (ms < 60000.0) return g_strdup_printf("%.2f s", ms / 1000.0); return g_strdup_printf("%.1f min", ms / 60000.0); } bench_volume_t bench_volume_from_env(void) { const char* v = getenv("BENCH_VOLUME"); if (!v || !v[0]) return BENCH_VOLUME_MEDIUM; if (g_ascii_strcasecmp(v, "small") == 0) return BENCH_VOLUME_SMALL; if (g_ascii_strcasecmp(v, "medium") == 0) return BENCH_VOLUME_MEDIUM; if (g_ascii_strcasecmp(v, "max") == 0) return BENCH_VOLUME_MAX; fprintf(stderr, "WARN: unknown BENCH_VOLUME='%s', defaulting to medium\n", v); return BENCH_VOLUME_MEDIUM; } const char* bench_volume_name(bench_volume_t v) { switch (v) { case BENCH_VOLUME_SMALL: return "small"; case BENCH_VOLUME_MEDIUM: return "medium"; case BENCH_VOLUME_MAX: return "max"; } return "?"; } gboolean bench_drop_page_cache(const char* path) { int fd = open(path, O_RDONLY); if (fd < 0) return FALSE; #ifdef POSIX_FADV_DONTNEED // Best-effort: kernel may ignore but typically honours. posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); #endif close(fd); return TRUE; } int64_t bench_fs_free_bytes(const char* path) { struct statvfs vfs; if (statvfs(path, &vfs) != 0) return -1; return (int64_t)vfs.f_bavail * (int64_t)vfs.f_frsize; } long bench_peak_rss_kb(void) { struct rusage ru; if (getrusage(RUSAGE_SELF, &ru) != 0) return -1; return ru.ru_maxrss; // already KB on Linux } double bench_run_best_of(int runs, bench_fn_t fn, void* arg, long* peak_rss_kb) { if (runs < 1) runs = 1; double best = 0.0; long max_rss = 0; for (int i = 0; i < runs; i++) { double t0 = bench_now_ms(); fn(arg); double dt = bench_now_ms() - t0; if (i == 0 || dt < best) best = dt; long rss = bench_peak_rss_kb(); if (rss > max_rss) max_rss = rss; } if (peak_rss_kb) *peak_rss_kb = max_rss; return best; }