diff --git a/.gitignore b/.gitignore index 6525ba45..9b4bcdf2 100644 --- a/.gitignore +++ b/.gitignore @@ -13,8 +13,10 @@ build/CMakeFiles/* build/tests build/client build/core +build/benchmark build/i2pd build/i2pd-tests +build/i2pd-benchmark *.cmake *.a *.o diff --git a/CMakeLists.txt b/CMakeLists.txt index e03b0f9b..d0312076 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,8 @@ option(WITH_BINARY "Build binary" ON) option(WITH_STATIC "Static build" OFF) option(WITH_UPNP "Include support for UPnP client" OFF) option(WITH_TESTS "Build unit tests" OFF) +option(WITH_BENCHMARK "Build benchmarking code" OFF) +option(WITH_OPTIMIZE "Optmizeation flags" OFF) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake_modules") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) @@ -80,6 +82,9 @@ if(WITH_AESNI) add_definitions( "-maes -DAESNI") endif() +if(WITH_OPTIMIZE AND (NOT MSVC)) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") +endif() # Libraries # TODO: once CMake 3.1+ becomes mainstream, see e.g. @@ -163,6 +168,8 @@ message(STATUS " BINARY : ${WITH_BINARY}") message(STATUS " STATIC BUILD : ${WITH_STATIC}") message(STATUS " UPnP : ${WITH_UPNP}") message(STATUS " TESTS : ${WITH_TESTS}") +message(STATUS " BENCHMARKING : ${WITH_BENCHMARK}") +message(STATUS " OPTIMIZATION : ${WITH_OPTIMIZE}") message(STATUS "---------------------------------------") # Handle paths nicely @@ -171,6 +178,8 @@ include(GNUInstallDirs) set(CORE_NAME "${PROJECT_NAME}-core") set(CLIENT_NAME "${PROJECT_NAME}-client") set(TESTS_NAME "${PROJECT_NAME}-tests") +set(BENCHMARK_NAME "${PROJECT_NAME}-benchmark") add_subdirectory(core) add_subdirectory(client) add_subdirectory(tests) +add_subdirectory(benchmark) diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt new file mode 100644 index 00000000..25d4b12c --- /dev/null +++ b/benchmark/CMakeLists.txt @@ -0,0 +1,14 @@ +set(BENCHMARK_SRC + "main.cpp" +) + +if(WITH_BENCHMARK) + add_executable(${BENCHMARK_NAME} ${BENCHMARK_SRC}) + target_link_libraries( + ${BENCHMARK_NAME} ${CORE_NAME} ${DL_LIB} ${Boost_LIBRARIES} ${CRYPTO++_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ) + install(TARGETS + ${BENCHMARK_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ) +endif() diff --git a/benchmark/main.cpp b/benchmark/main.cpp new file mode 100644 index 00000000..387c505d --- /dev/null +++ b/benchmark/main.cpp @@ -0,0 +1,83 @@ +#include "crypto/Signature.h" +#include +#include +#include +#include + +typedef std::function KeyGenerator; + +template +void benchmark(std::size_t count, std::size_t public_key_size, std::size_t private_key_size, + std::size_t signature_size, KeyGenerator generator) +{ + typedef std::chrono::time_point TimePoint; + CryptoPP::AutoSeededRandomPool rng; + + uint8_t private_key[private_key_size] = {}; + uint8_t public_key[public_key_size] = {}; + + generator(rng, private_key, public_key); + + Verifier verifier(public_key); + Signer signer(private_key); + + uint8_t message[512] = {}; + uint8_t output[signature_size] = {}; + + std::chrono::nanoseconds sign_duration(0); + std::chrono::nanoseconds verify_duration(0); + + for(std::size_t i = 0; i < count; ++i) { + rng.GenerateBlock(message, 512); + TimePoint begin1 = std::chrono::high_resolution_clock::now(); + signer.Sign(rng, message, 512, output); + TimePoint end1 = std::chrono::high_resolution_clock::now(); + + sign_duration += std::chrono::duration_cast(end1 - begin1); + + TimePoint begin2 = std::chrono::high_resolution_clock::now(); + verifier.Verify(message, 512, output); + TimePoint end2 = std::chrono::high_resolution_clock::now(); + + verify_duration += std::chrono::duration_cast(end2 - begin2); + } + std::cout << "Conducted " << count << " experiments." << std::endl; + std::cout << "Total sign time: " << std::chrono::duration_cast(sign_duration).count() << std::endl; + std::cout << "Total verify time: " << std::chrono::duration_cast(verify_duration).count() << std::endl; +} + + +int main() +{ + using namespace i2p::crypto; + std::cout << "--------DSA---------" << std::endl; + benchmark( + 1000, DSA_PUBLIC_KEY_LENGTH, + DSA_PRIVATE_KEY_LENGTH, DSA_SIGNATURE_LENGTH, + &CreateDSARandomKeys + ); + std::cout << "-----ECDSAP256------" << std::endl; + benchmark( + 1000, ECDSAP256_KEY_LENGTH, + ECDSAP256_KEY_LENGTH, 64, + &CreateECDSAP256RandomKeys + ); + std::cout << "-----ECDSAP384------" << std::endl; + benchmark( + 1000, ECDSAP384_KEY_LENGTH, + ECDSAP384_KEY_LENGTH, 64, + &CreateECDSAP384RandomKeys + ); + std::cout << "-----ECDSAP521------" << std::endl; + benchmark( + 1000, ECDSAP521_KEY_LENGTH, + ECDSAP521_KEY_LENGTH, 64, + &CreateECDSAP521RandomKeys + ); + std::cout << "-----EDDSA25519-----" << std::endl; + benchmark( + 1000, EDDSA25519_PUBLIC_KEY_LENGTH, + EDDSA25519_PRIVATE_KEY_LENGTH, 64, + &CreateEDDSARandomKeys + ); +} diff --git a/build/BUILD_NOTES.md b/build/BUILD_NOTES.md index c688a839..874f27c9 100644 --- a/build/BUILD_NOTES.md +++ b/build/BUILD_NOTES.md @@ -6,6 +6,9 @@ Available cmake options: * CMAKE_BUILD_TYPE -- build profile (Debug/Release) * WITH_AESNI -- AES-NI support (ON/OFF) * WITH_HARDENING -- enable hardening features (ON/OFF) (gcc only) +* WITH_TESTS -- build tests (ON/OFF) +* WITH_BENCHMARK -- build bechmarking code (ON/OFF) +* WITH_OPTIMIZE -- enable optimization flags (ON/OFF) Debian ------