diff --git a/Code/Bench/CMakeLists.txt b/Code/Bench/CMakeLists.txt new file mode 100644 index 000000000..8e1a0ad6b --- /dev/null +++ b/Code/Bench/CMakeLists.txt @@ -0,0 +1,18 @@ +add_executable(bench EXCLUDE_FROM_ALL smiles.cpp stereo.cpp) +target_link_libraries(bench rdkitCatch SmilesParse CIPLabeler) + +if(RDK_BUILD_CPP_TESTS) + # add a fast version of the benchmarks to the default unit tests + # to protect the benchmarks from bit-rot + add_test( + NAME quickbench + COMMAND bench --benchmark-samples 1 --benchmark-warmup-time 0 + ) + + # ctest does not automatically build test executables + # so, like with other unit tests in this repo, we need to manually + # build the target before running ctest. This usually gets done with + # an `all` or an `install` build. We re-add bench to he `all` group + # to keep it similar to the other unit tests + set_target_properties(bench PROPERTIES EXCLUDE_FROM_ALL FALSE) +endif(RDK_BUILD_CPP_TESTS) diff --git a/Code/Bench/README.md b/Code/Bench/README.md new file mode 100644 index 000000000..a43fd7620 --- /dev/null +++ b/Code/Bench/README.md @@ -0,0 +1,12 @@ +# RDKit Benchmarks + +To run: + +```bash +mkdir build +cd build +cmake .. +cmake --build . --target bench -j "$(nproc)" +# see `./Code/Bench/bench --help` for options +./Code/Bench/bench +``` diff --git a/Code/Bench/bench_common.hpp b/Code/Bench/bench_common.hpp new file mode 100644 index 000000000..62fc267f0 --- /dev/null +++ b/Code/Bench/bench_common.hpp @@ -0,0 +1,11 @@ +#pragma once + +namespace bench_common { +constexpr const char *CASES[] = { + "COC1/C=C/OC2(C)Oc3c(C)c(O)c4c(O)c(c(/C=N/OC(c5ccccc5)c5ccccc5)cc4c3C2=O)NC(=O)/C(C)=C\\C=C\\C(C)C(O)C(C)C(O)C(C)C(OC(C)=O)C1C", + "Cn1cnc2n(C)c(=O)n(C)c(=O)c12", + "c1ccc2c(c1)c3ccccc3c4ccccc24", + "F[C@@H](Cl)[C@H](Br)[C@](I)(O)[C@@](N)(C#N)C(=O)O", + "C[S+](C)(C)[O-]", +}; +} // namespace bench_common diff --git a/Code/Bench/smiles.cpp b/Code/Bench/smiles.cpp new file mode 100644 index 000000000..9ecd82a07 --- /dev/null +++ b/Code/Bench/smiles.cpp @@ -0,0 +1,30 @@ +#include +#include + +#include "bench_common.hpp" + +#include +#include +#include + +using namespace RDKit; + +TEST_CASE("SmilesToMol", "[smiles]") { + for (auto smiles : bench_common::CASES) { + BENCHMARK("SmilesToMol: " + std::string(smiles)) { + auto mol = v2::SmilesParse::MolFromSmiles(smiles); + REQUIRE(mol); + return mol; + }; + } +} + +TEST_CASE("MolToSmiles", "[smiles]") { + for (auto smiles : bench_common::CASES) { + auto mol = v2::SmilesParse::MolFromSmiles(smiles); + REQUIRE(mol); + BENCHMARK("MolToSmiles: " + std::string(smiles)) { + return MolToSmiles(*mol); + }; + } +} diff --git a/Code/Bench/stereo.cpp b/Code/Bench/stereo.cpp new file mode 100644 index 000000000..f2c71ae6f --- /dev/null +++ b/Code/Bench/stereo.cpp @@ -0,0 +1,33 @@ +#include +#include + +#include "bench_common.hpp" + +#include +#include +#include +#include + +using namespace RDKit; + +TEST_CASE("Chirality::findPotentialStereo", "[stereo]") { + for (auto smiles : bench_common::CASES) { + auto mol = v2::SmilesParse::MolFromSmiles(smiles); + REQUIRE(mol); + + BENCHMARK("Chirality::findPotentialStereo: " + std::string(smiles)) { + return Chirality::findPotentialStereo(*mol); + }; + } +} + +TEST_CASE("CIPLabeler::CIPLabeler", "[stereo]") { + for (auto smiles : bench_common::CASES) { + auto mol = v2::SmilesParse::MolFromSmiles(smiles); + REQUIRE(mol); + + BENCHMARK("CIPLabeler::assignCIPLabels: " + std::string(smiles)) { + return Chirality::findPotentialStereo(*mol); + }; + } +} diff --git a/Code/CMakeLists.txt b/Code/CMakeLists.txt index cda2c25ff..245a7a2b0 100644 --- a/Code/CMakeLists.txt +++ b/Code/CMakeLists.txt @@ -40,3 +40,5 @@ add_subdirectory(MinimalLib) if(RDK_BUILD_FUZZ_TARGETS) add_subdirectory(Fuzz) endif(RDK_BUILD_FUZZ_TARGETS) + +add_subdirectory(Bench)