Add benchmarks, change project structure
This commit is contained in:
42
bench/CMakeLists.txt
Normal file
42
bench/CMakeLists.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
# Project and C standard configuration
|
||||
project(bhunit LANGUAGES C)
|
||||
set(CMAKE_C_STANDARD 90)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
# Disable extensions
|
||||
set(CMAKE_C_EXTENSIONS OFF)
|
||||
|
||||
# Library code
|
||||
set(BHBENCH_SOURCE
|
||||
src/Bench.c
|
||||
)
|
||||
|
||||
set(BHBENCH_HEADER
|
||||
include/BH/Bench.h
|
||||
)
|
||||
|
||||
# Library
|
||||
add_library(BHBench STATIC ${BHBENCH_SOURCE} ${BHBENCH_HEADER})
|
||||
target_include_directories(BHBench PUBLIC include)
|
||||
target_link_libraries(BHBench BHLib)
|
||||
|
||||
# Enable testing
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
|
||||
# Search files
|
||||
file(GLOB TEST_FILES "tests/*.c")
|
||||
|
||||
foreach(TEST_FILENAME ${TEST_FILES})
|
||||
# Add test
|
||||
get_filename_component(TEST_NAME ${TEST_FILENAME} NAME_WE)
|
||||
add_executable("${TEST_NAME}" ${TEST_FILENAME})
|
||||
target_link_libraries("${TEST_NAME}" BHLib BHBench)
|
||||
add_test(NAME "${TEST_NAME}" COMMAND "${TEST_NAME}")
|
||||
|
||||
# Enable coverage
|
||||
if(ENABLE_COVERAGE)
|
||||
target_compile_options("${TEST_NAME}" PRIVATE -coverage)
|
||||
target_link_options("${TEST_NAME}" PRIVATE -coverage)
|
||||
endif()
|
||||
endforeach()
|
||||
25
bench/include/BH/Bench.h
Normal file
25
bench/include/BH/Bench.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef BH_BENCH_H
|
||||
#define BH_BENCH_H
|
||||
|
||||
typedef struct BH_Bench BH_Bench;
|
||||
typedef void (*BH_BenchCallback)(BH_Bench *);
|
||||
|
||||
|
||||
#define BH_BENCH_TEST(name) \
|
||||
static void bench##name(BH_Bench *state)
|
||||
|
||||
|
||||
#define BH_BENCH_ADD(name) \
|
||||
BH_BenchAdd(#name, bench##name)
|
||||
|
||||
|
||||
void BH_BenchAdd(const char *name,
|
||||
BH_BenchCallback cb);
|
||||
|
||||
|
||||
int BH_BenchIter(BH_Bench *state);
|
||||
|
||||
|
||||
int BH_BenchRun(void);
|
||||
|
||||
#endif /* BH_BENCH_H */
|
||||
112
bench/src/Bench.c
Normal file
112
bench/src/Bench.c
Normal file
@@ -0,0 +1,112 @@
|
||||
#include <BH/Bench.h>
|
||||
#include <BH/Timer.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
struct BH_Bench
|
||||
{
|
||||
struct BH_Bench *next;
|
||||
const char *name;
|
||||
BH_BenchCallback cb;
|
||||
int started;
|
||||
size_t iterations;
|
||||
};
|
||||
|
||||
|
||||
static BH_Bench *root = NULL;
|
||||
static BH_Timer *timer = NULL;
|
||||
|
||||
|
||||
static void cleanup(void)
|
||||
{
|
||||
BH_Bench *current;
|
||||
|
||||
current = root;
|
||||
while (current)
|
||||
{
|
||||
BH_Bench *next = current->next;
|
||||
|
||||
free(current);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BH_BenchAdd(const char *name,
|
||||
BH_BenchCallback cb)
|
||||
{
|
||||
BH_Bench *bench, *current;
|
||||
|
||||
/* Allocate and fill new benchmark entry */
|
||||
bench = malloc(sizeof(*bench));
|
||||
if (!bench)
|
||||
return;
|
||||
|
||||
bench->next = NULL;
|
||||
bench->name = name;
|
||||
bench->cb = cb;
|
||||
bench->started = 0;
|
||||
bench->iterations = 0;
|
||||
|
||||
/* Append benchmark entry */
|
||||
current = root;
|
||||
while (current && current->next)
|
||||
current = current->next;
|
||||
|
||||
if (current)
|
||||
current->next = bench;
|
||||
else
|
||||
root = bench;
|
||||
}
|
||||
|
||||
|
||||
int BH_BenchIter(BH_Bench *state)
|
||||
{
|
||||
if (state->started)
|
||||
{
|
||||
int64_t millis;
|
||||
|
||||
state->iterations++;
|
||||
millis = BH_TimerMilliseconds(timer);
|
||||
|
||||
if (millis > 1000 && state->iterations > 10)
|
||||
{
|
||||
printf("%s\t%f ips\n", state->name, state->iterations / (millis / 1000.0f));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state->started = 1;
|
||||
BH_TimerRestart(timer);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int BH_BenchRun(void)
|
||||
{
|
||||
BH_Bench *current;
|
||||
int result = 0;
|
||||
|
||||
timer = BH_TimerNew();
|
||||
if (!timer)
|
||||
{
|
||||
printf("ERROR: Can't create timer for benchmarks");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Running benchmarks...\n");
|
||||
current = root;
|
||||
while (current)
|
||||
{
|
||||
current->cb(current);
|
||||
current = current->next;
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
cleanup();
|
||||
return 0;
|
||||
}
|
||||
33
bench/tests/BenchVec3f.c
Normal file
33
bench/tests/BenchVec3f.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <BH/Bench.h>
|
||||
#include <BH/Math/Vec3f.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
BH_BENCH_TEST(Vec3f)
|
||||
{
|
||||
float a[3], b[3];
|
||||
|
||||
a[0] = (rand() % 100) / 200.0;
|
||||
a[1] = (rand() % 100) / 200.0;
|
||||
a[2] = (rand() % 100) / 200.0;
|
||||
|
||||
b[0] = (rand() % 100) / 200.0;
|
||||
b[1] = (rand() % 100) / 200.0;
|
||||
b[2] = (rand() % 100) / 200.0;
|
||||
|
||||
while (BH_BenchIter(state))
|
||||
{
|
||||
BH_Vec3fAdd(a, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
BH_UNUSED(argc);
|
||||
BH_UNUSED(argv);
|
||||
|
||||
BH_BENCH_ADD(Vec3f);
|
||||
|
||||
return BH_BenchRun();
|
||||
}
|
||||
Reference in New Issue
Block a user