A lightweight, high-performance profiling library for C applications with minimal overhead. Designed for measuring execution time of code blocks and functions with nanosecond precision using POSIX timers.
- High-Resolution Timing: Uses POSIX
clock_gettimewithCLOCK_MONOTONICfor nanosecond precision - Scoped Timers: Automatic timer cleanup using GCC
cleanupattribute - Aggregated Statistics: Collect min, max, average, and count across multiple measurements
- Optional File Logging: Automatic or manual logging to files
- Minimal Overhead: Efficient implementation with negligible performance impact
- Easy Integration: Simple macros for drop-in profiling
- Cross-Platform: Works on any POSIX-compliant system (Linux, macOS, BSD, etc.)
# Build static library and examples
make
# Build shared library
make shared
# Run all examples
make run
# Install to system (requires root)
sudo make install#include "profiler.h"
int main(void) {
profiler_init();
// Manual timer
profiler_timer_t timer;
profiler_timer_start(&timer, "my_operation");
// Your code here
profiler_timer_stop(&timer);
profiler_print_timer(&timer);
profiler_shutdown();
return 0;
}void profiler_init(void);
void profiler_shutdown(void);
void profiler_enable(bool enable);
void profiler_set_log_file(const char *filename);
void profiler_close_log_file(void);void profiler_timer_start(profiler_timer_t *timer, const char *name);
void profiler_timer_stop(profiler_timer_t *timer);
uint64_t profiler_timer_elapsed_ns(const profiler_timer_t *timer);
double profiler_timer_elapsed_us(const profiler_timer_t *timer);
double profiler_timer_elapsed_ms(const profiler_timer_t *timer);
double profiler_timer_elapsed_s(const profiler_timer_t *timer);void profiler_stats_init(profiler_stats_t *stats, const char *name);
void profiler_stats_add(profiler_stats_t *stats, uint64_t elapsed_ns);
void profiler_stats_print(const profiler_stats_t *stats);
void profiler_stats_log(const profiler_stats_t *stats, FILE *file);
void profiler_stats_reset(profiler_stats_t *stats);PROFILER_SCOPE(name) // Scoped timer (auto cleanup)
PROFILER_FUNCTION() // Profile entire function
PROFILER_START(timer, name) // Start manual timer
PROFILER_STOP(timer) // Stop manual timer
PROFILER_BLOCK_START(name) // Start profiled block
PROFILER_BLOCK_END(name) // End profiled block#include "profiler.h"
void my_function(void) {
PROFILER_FUNCTION(); // Automatically profiles entire function
// Function code
}
int main(void) {
profiler_init();
{
PROFILER_SCOPE(database_query);
// Code to profile
} // Timer automatically stops here
my_function();
profiler_shutdown();
return 0;
}#include "profiler.h"
int main(void) {
profiler_init();
profiler_stats_t stats;
profiler_stats_init(&stats, "operation");
for (int i = 0; i < 100; i++) {
profiler_timer_t timer;
profiler_timer_start(&timer, "iteration");
// Your code
profiler_timer_stop(&timer);
profiler_stats_add(&stats, profiler_timer_elapsed_ns(&timer));
}
profiler_stats_print(&stats); // Shows min, max, avg, count
profiler_shutdown();
return 0;
}#include "profiler.h"
int main(void) {
profiler_init();
// Enable automatic logging
profiler_set_log_file("profiler.log");
{
PROFILER_SCOPE(operation);
// Code automatically logged
}
profiler_shutdown(); // Closes log file
return 0;
}#include "profiler.h"
void algorithm_a(void) {
PROFILER_FUNCTION();
// Implementation A
}
void algorithm_b(void) {
PROFILER_FUNCTION();
// Implementation B
}
int main(void) {
profiler_init();
algorithm_a(); // Prints: [PROFILER] algorithm_a: X.XXX ms
algorithm_b(); // Prints: [PROFILER] algorithm_b: X.XXX ms
profiler_shutdown();
return 0;
}# Build static library (default)
make static
# Build shared library
make shared
# Build all examples
make examples
# Build specific example
make example1_basic
# Clean build artifacts
make clean
# Clean everything including logs
make distclean# Run individual examples
./example1_basic
./example2_scoped
./example3_stats
./example4_logging
./example5_comprehensive
# Run all examples
make run# Build the library
make static
# Compile your program
gcc -o myapp myapp.c libprofiler.a -lrt# Build the shared library
make shared
# Compile your program
gcc -o myapp myapp.c -L. -lprofiler -lrt# Include profiler.c directly in your build
gcc -o myapp myapp.c profiler.c -lrtThe profiler is designed for minimal overhead:
- Timer start/stop: ~50-100 nanoseconds (typical)
- Statistics update: ~10-20 nanoseconds (typical)
- Disabled profiler: near-zero overhead (checks single boolean flag)
You can disable profiling at runtime without recompiling:
profiler_enable(false); // Disable profiling
// ... code runs without profiling
profiler_enable(true); // Re-enable profiling- POSIX-compliant OS: Linux, macOS, BSD, Unix, etc.
- C11 compiler: GCC 4.7+, Clang 3.1+, or compatible
- librt: Required for
clock_gettimeon some platforms
profiler_timer_t timer;
profiler_timer_start(&timer, "operation");
// ... code ...
profiler_timer_stop(&timer);
printf("Time: %lu ns\n", profiler_timer_elapsed_ns(&timer));
printf("Time: %.3f us\n", profiler_timer_elapsed_us(&timer));
printf("Time: %.3f ms\n", profiler_timer_elapsed_ms(&timer));
printf("Time: %.3f s\n", profiler_timer_elapsed_s(&timer));#ifdef ENABLE_PROFILING
PROFILER_SCOPE(my_code);
#endif
// Your code herevoid outer_function(void) {
PROFILER_FUNCTION();
{
PROFILER_SCOPE(inner_operation_1);
// Code
}
{
PROFILER_SCOPE(inner_operation_2);
// Code
}
}- example1_basic.c: Basic timer usage
- example2_scoped.c: Scoped timers and automatic cleanup
- example3_stats.c: Statistics collection and aggregation
- example4_logging.c: File logging functionality
- example5_comprehensive.c: Real-world performance analysis
MIT License - Copyright (c) 2025 Max Base
See LICENSE file for details.
Contributions are welcome! Please feel free to submit issues or pull requests.
Max Base
- C11
- POSIX Timers (
clock_gettime) - CLOCK_MONOTONIC for high-resolution timing