mirror of
https://github.com/libgit2/libgit2.git
synced 2026-01-25 02:56:17 +00:00
microbenchmarks: benchmark the oid code
At present, the library's oid manipulation functions are slower when built in SHA256 mode than when not. Add some microbenchmarks around the oid compare and copy functions to understand this better.
This commit is contained in:
@@ -20,7 +20,8 @@ option(EXPERIMENTAL_SHA256 "Enable experimental SHA256 support (for R&D/test
|
||||
|
||||
# Optional subsystems
|
||||
option(BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON)
|
||||
option(BUILD_TESTS "Build Tests using the Clar suite" ON)
|
||||
option(BUILD_TESTS "Build the test suite" ON)
|
||||
option(BUILD_BENCHMARKS "Build the benchmark suite" OFF)
|
||||
option(BUILD_CLI "Build the command-line interface" ON)
|
||||
option(BUILD_EXAMPLES "Build library usage example apps" OFF)
|
||||
option(BUILD_FUZZERS "Build the fuzz targets" OFF)
|
||||
@@ -112,6 +113,10 @@ if(BUILD_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
if(BUILD_BENCHMARKS)
|
||||
add_subdirectory(benchmarks)
|
||||
endif()
|
||||
|
||||
if(BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
1
benchmarks/CMakeLists.txt
Normal file
1
benchmarks/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
add_subdirectory(libgit2)
|
||||
78
benchmarks/libgit2/CMakeLists.txt
Normal file
78
benchmarks/libgit2/CMakeLists.txt
Normal file
@@ -0,0 +1,78 @@
|
||||
# util: the unit tests for libgit2's utility library
|
||||
|
||||
if(NOT "${CMAKE_VERSION}" VERSION_LESS 3.27)
|
||||
cmake_policy(SET CMP0148 OLD)
|
||||
endif()
|
||||
|
||||
set(Python_ADDITIONAL_VERSIONS 3 2.7)
|
||||
find_package(PythonInterp)
|
||||
|
||||
if(NOT PYTHONINTERP_FOUND)
|
||||
message(FATAL_ERROR "Could not find a python interpeter, which is needed to build the tests. "
|
||||
"Make sure python is available, or pass -DBUILD_TESTS=OFF to skip building the tests")
|
||||
endif()
|
||||
|
||||
set(CLAR_PATH "${PROJECT_SOURCE_DIR}/deps/clar")
|
||||
set(BENCHMARK_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
add_definitions(-DCLAR_TMPDIR=\"libgit2_bench\")
|
||||
add_definitions(-DCLAR_WIN32_LONGPATHS)
|
||||
add_definitions(-DCLAR_HAS_REALPATH)
|
||||
add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||
|
||||
file(GLOB BENCHMARK_SRC *.c *.h)
|
||||
list(SORT BENCHMARK_SRC)
|
||||
|
||||
set(CLAR_SRC
|
||||
"${CLAR_PATH}/clar.c"
|
||||
"${CLAR_PATH}/clar.h"
|
||||
"${CLAR_PATH}/clar/fixtures.h"
|
||||
"${CLAR_PATH}/clar/print.h"
|
||||
"${CLAR_PATH}/clar/summary.h"
|
||||
"${CLAR_PATH}/clar/sandbox.h"
|
||||
"${CLAR_PATH}/clar/fs.h")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/clar.suite ${CMAKE_CURRENT_BINARY_DIR}/clar_suite.h
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CLAR_PATH}/generate.py -p benchmark -o "${CMAKE_CURRENT_BINARY_DIR}" -f .
|
||||
DEPENDS ${BENCHMARK_SRC}
|
||||
WORKING_DIRECTORY ${BENCHMARK_PATH}
|
||||
)
|
||||
|
||||
set_source_files_properties(
|
||||
${CLAR_PATH}/clar.c
|
||||
PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clar.suite)
|
||||
|
||||
add_executable(libgit2_benchmarks ${CLAR_SRC}
|
||||
${BENCHMARK_SRC}
|
||||
$<TARGET_OBJECTS:util>
|
||||
${LIBGIT2_DEPENDENCY_OBJECTS})
|
||||
|
||||
target_link_libraries(libgit2_benchmarks libgit2package ${LIBGIT2_SYSTEM_LIBS})
|
||||
if(NOT MSVC_IDE)
|
||||
target_link_libraries(libgit2_benchmarks m)
|
||||
endif()
|
||||
|
||||
ide_split_sources(libgit2_benchmarks)
|
||||
|
||||
target_include_directories(libgit2_benchmarks PRIVATE
|
||||
"${CLAR_PATH}"
|
||||
"${libgit2_BINARY_DIR}/src/util"
|
||||
"${libgit2_BINARY_DIR}/include"
|
||||
"${libgit2_SOURCE_DIR}/src/util"
|
||||
"${libgit2_SOURCE_DIR}/include"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"${LIBGIT2_DEPENDENCY_INCLUDES}"
|
||||
"${LIBGIT2_SYSTEM_INCLUDES}")
|
||||
|
||||
#
|
||||
# Old versions of gcc require us to declare our test functions; don't do
|
||||
# this on newer compilers to avoid unnecessary recompilation.
|
||||
#
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
|
||||
target_compile_options(libgit2_benchmarks PRIVATE -include "clar_suite.h")
|
||||
endif()
|
||||
|
||||
if(MSVC_IDE)
|
||||
set_target_properties(libgit2_benchmarks PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
|
||||
set_source_files_properties("precompiled.c" COMPILE_FLAGS "/Ycprecompiled.h")
|
||||
endif()
|
||||
31
benchmarks/libgit2/main.c
Normal file
31
benchmarks/libgit2/main.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "clar.h"
|
||||
#include <git2.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
int __cdecl main(int argc, char *argv[])
|
||||
#else
|
||||
int main(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
int res;
|
||||
|
||||
clar_test_set_mode(CL_TEST_BENCHMARK);
|
||||
clar_test_init(argc, argv);
|
||||
|
||||
res = git_libgit2_init();
|
||||
if (res < 0) {
|
||||
const git_error *err = git_error_last();
|
||||
const char *msg = err ? err->message : "unknown failure";
|
||||
fprintf(stderr, "failed to init libgit2: %s\n", msg);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Run the test suite */
|
||||
res = clar_test_run();
|
||||
|
||||
clar_test_shutdown();
|
||||
|
||||
return res;
|
||||
}
|
||||
151
benchmarks/libgit2/oid.c
Normal file
151
benchmarks/libgit2/oid.c
Normal file
@@ -0,0 +1,151 @@
|
||||
#include "clar.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <git2.h>
|
||||
|
||||
#define BENCHMARK_OID_COUNT 256
|
||||
|
||||
static git_oid sha1_one[BENCHMARK_OID_COUNT];
|
||||
static git_oid *sha1_two;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
static git_oid sha256_one[BENCHMARK_OID_COUNT];
|
||||
static git_oid *sha256_two;
|
||||
#endif
|
||||
|
||||
static void update_data_to_val(git_oid *out, git_oid_t type, uint32_t val)
|
||||
{
|
||||
unsigned char data[GIT_OID_MAX_SIZE] = {0};
|
||||
size_t size;
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
size = (type == GIT_OID_SHA256) ? GIT_OID_SHA256_SIZE : GIT_OID_SHA1_SIZE;
|
||||
#else
|
||||
size = GIT_OID_SHA1_SIZE;
|
||||
|
||||
((void)(type));
|
||||
#endif
|
||||
|
||||
memset(data, 0, GIT_OID_MAX_SIZE);
|
||||
|
||||
data[size - 1] = (unsigned char)(val & 0x000000ff);
|
||||
data[size - 2] = (unsigned char)((val & 0x0000ff00) >> 8);
|
||||
data[size - 3] = (unsigned char)((val & 0x00ff0000) >> 16);
|
||||
data[size - 4] = (unsigned char)((val & 0x00ff0000) >> 24);
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
cl_assert(git_oid_from_raw(out, data, type) == 0);
|
||||
#else
|
||||
cl_assert(git_oid_fromraw(out, data) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void benchmark_oid__initialize(void)
|
||||
{
|
||||
uint32_t accum = 0;
|
||||
size_t i;
|
||||
|
||||
sha1_two = calloc(BENCHMARK_OID_COUNT, sizeof(git_oid));
|
||||
cl_assert(sha1_two != NULL);
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
sha256_two = calloc(BENCHMARK_OID_COUNT, sizeof(git_oid));
|
||||
cl_assert(sha256_two != NULL);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < BENCHMARK_OID_COUNT; i++) {
|
||||
update_data_to_val(&sha1_one[i], GIT_OID_SHA1, accum++);
|
||||
update_data_to_val(&sha1_two[i], GIT_OID_SHA1, accum++);
|
||||
}
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
for (i = 0; i < BENCHMARK_OID_COUNT; i++) {
|
||||
update_data_to_val(&sha256_one[i], GIT_OID_SHA256, accum++);
|
||||
update_data_to_val(&sha256_two[i], GIT_OID_SHA256, accum++);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void benchmark_oid__reset(void)
|
||||
{
|
||||
}
|
||||
|
||||
void benchmark_oid__cleanup(void)
|
||||
{
|
||||
free(sha1_two);
|
||||
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
free(sha256_two);
|
||||
#endif
|
||||
}
|
||||
|
||||
void benchmark_oid__cmp_sha1(void)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; i < 1024 * 16; i++)
|
||||
for (j = 0; j < BENCHMARK_OID_COUNT; j++)
|
||||
git_oid_cmp(&sha1_one[j], &sha1_two[j]);
|
||||
}
|
||||
|
||||
void benchmark_oid__cmp_sha256(void)
|
||||
{
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; i < 1024 * 16; i++)
|
||||
for (j = 0; j < BENCHMARK_OID_COUNT; j++)
|
||||
git_oid_cmp(&sha256_one[j], &sha256_two[j]);
|
||||
#else
|
||||
clar__skip();
|
||||
#endif
|
||||
}
|
||||
|
||||
void benchmark_oid__cpy_sha1(void)
|
||||
{
|
||||
git_oid dest;
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; i < 1024 * 16; i++)
|
||||
for (j = 0; j < BENCHMARK_OID_COUNT; j++)
|
||||
git_oid_cpy(&dest, &sha1_one[j]);
|
||||
}
|
||||
|
||||
void benchmark_oid__cpy_sha256(void)
|
||||
{
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
git_oid dest;
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; i < 1024 * 16; i++)
|
||||
for (j = 0; j < BENCHMARK_OID_COUNT; j++)
|
||||
git_oid_cpy(&dest, &sha256_one[j]);
|
||||
#else
|
||||
clar__skip();
|
||||
#endif
|
||||
}
|
||||
|
||||
void benchmark_oid__zero_sha1(void)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; i < 1024 * 16; i++)
|
||||
for (j = 0; j < BENCHMARK_OID_COUNT; j++)
|
||||
git_oid_is_zero(&sha1_one[j]);
|
||||
}
|
||||
|
||||
void benchmark_oid__zero_sha256(void)
|
||||
{
|
||||
#ifdef GIT_EXPERIMENTAL_SHA256
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; i < 1024 * 16; i++)
|
||||
for (j = 0; j < BENCHMARK_OID_COUNT; j++)
|
||||
git_oid_is_zero(&sha256_one[j]);
|
||||
#else
|
||||
clar__skip();
|
||||
#endif
|
||||
}
|
||||
1
benchmarks/libgit2/precompiled.c
Normal file
1
benchmarks/libgit2/precompiled.c
Normal file
@@ -0,0 +1 @@
|
||||
#include "precompiled.h"
|
||||
2
benchmarks/libgit2/precompiled.h
Normal file
2
benchmarks/libgit2/precompiled.h
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "git2.h"
|
||||
#include "clar.h"
|
||||
@@ -10,7 +10,7 @@ find_package(PythonInterp)
|
||||
if(NOT PYTHONINTERP_FOUND)
|
||||
message(FATAL_ERROR "Could not find a python interpreter, which is needed to build the tests. "
|
||||
"Make sure python is available, or pass -DBUILD_TESTS=OFF to skip building the tests")
|
||||
ENDIF()
|
||||
endif()
|
||||
|
||||
set(CLAR_PATH "${PROJECT_SOURCE_DIR}/deps/clar")
|
||||
set(CLAR_FIXTURES "${PROJECT_SOURCE_DIR}/tests/resources/")
|
||||
@@ -48,7 +48,11 @@ add_executable(libgit2_tests ${SRC_CLAR} ${SRC_TEST} ${LIBGIT2_OBJECTS})
|
||||
set_target_properties(libgit2_tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
target_include_directories(libgit2_tests PRIVATE ${TEST_INCLUDES} ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES})
|
||||
target_include_directories(libgit2_tests SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
|
||||
|
||||
target_link_libraries(libgit2_tests ${LIBGIT2_SYSTEM_LIBS})
|
||||
if(NOT MSVC_IDE)
|
||||
target_link_libraries(libgit2_tests m)
|
||||
endif()
|
||||
|
||||
ide_split_sources(libgit2_tests)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ find_package(PythonInterp)
|
||||
if(NOT PYTHONINTERP_FOUND)
|
||||
message(FATAL_ERROR "Could not find a python interpeter, which is needed to build the tests. "
|
||||
"Make sure python is available, or pass -DBUILD_TESTS=OFF to skip building the tests")
|
||||
ENDIF()
|
||||
endif()
|
||||
|
||||
set(CLAR_PATH "${libgit2_SOURCE_DIR}/deps/clar")
|
||||
set(CLAR_FIXTURES "${libgit2_SOURCE_DIR}/tests/resources/")
|
||||
@@ -48,7 +48,11 @@ set_target_properties(util_tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${libgit2_B
|
||||
|
||||
target_include_directories(util_tests PRIVATE ${TEST_INCLUDES} ${LIBGIT2_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES})
|
||||
target_include_directories(util_tests SYSTEM PRIVATE ${LIBGIT2_SYSTEM_INCLUDES})
|
||||
|
||||
target_link_libraries(util_tests ${LIBGIT2_SYSTEM_LIBS})
|
||||
if(NOT MSVC_IDE)
|
||||
target_link_libraries(util_tests m)
|
||||
endif()
|
||||
|
||||
ide_split_sources(util_tests)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user