diff options
Diffstat (limited to 'tests/performance_tests')
-rw-r--r-- | tests/performance_tests/CMakeLists.txt | 5 | ||||
-rw-r--r-- | tests/performance_tests/bulletproof.h | 100 | ||||
-rw-r--r-- | tests/performance_tests/check_tx_signature.h | 84 | ||||
-rw-r--r-- | tests/performance_tests/construct_tx.h | 4 | ||||
-rw-r--r-- | tests/performance_tests/crypto_ops.h | 122 | ||||
-rw-r--r-- | tests/performance_tests/main.cpp | 532 | ||||
-rw-r--r-- | tests/performance_tests/multiexp.h | 94 | ||||
-rw-r--r-- | tests/performance_tests/performance_tests.h | 126 | ||||
-rw-r--r-- | tests/performance_tests/range_proof.h | 63 | ||||
-rw-r--r-- | tests/performance_tests/signature.h | 68 |
10 files changed, 1103 insertions, 95 deletions
diff --git a/tests/performance_tests/CMakeLists.txt b/tests/performance_tests/CMakeLists.txt index 8cbd71444..837d39bd3 100644 --- a/tests/performance_tests/CMakeLists.txt +++ b/tests/performance_tests/CMakeLists.txt @@ -40,8 +40,13 @@ set(performance_tests_headers generate_key_image.h generate_key_image_helper.h generate_keypair.h + signature.h is_out_to_acc.h subaddress_expand.h + range_proof.h + bulletproof.h + crypto_ops.h + multiexp.h multi_tx_test_base.h performance_tests.h performance_utils.h diff --git a/tests/performance_tests/bulletproof.h b/tests/performance_tests/bulletproof.h new file mode 100644 index 000000000..7bb702c3d --- /dev/null +++ b/tests/performance_tests/bulletproof.h @@ -0,0 +1,100 @@ +// Copyright (c) 2014-2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include "ringct/rctSigs.h" +#include "ringct/bulletproofs.h" + +template<bool a_verify, size_t n_amounts> +class test_bulletproof +{ +public: + static const size_t approx_loop_count = 100 / n_amounts; + static const size_t loop_count = (approx_loop_count >= 10 ? approx_loop_count : 10) / (a_verify ? 1 : 5); + static const bool verify = a_verify; + + bool init() + { + proof = rct::bulletproof_PROVE(std::vector<uint64_t>(n_amounts, 749327532984), rct::skvGen(n_amounts)); + return true; + } + + bool test() + { + bool ret = true; + if (verify) + ret = rct::bulletproof_VERIFY(proof); + else + rct::bulletproof_PROVE(std::vector<uint64_t>(n_amounts, 749327532984), rct::skvGen(n_amounts)); + return ret; + } + +private: + rct::Bulletproof proof; +}; + +template<bool batch, size_t start, size_t repeat, size_t mul, size_t add, size_t N> +class test_aggregated_bulletproof +{ +public: + static const size_t loop_count = 500 / (N * repeat); + + bool init() + { + size_t o = start; + for (size_t n = 0; n < N; ++n) + { + //printf("adding %zu times %zu\n", repeat, o); + for (size_t i = 0; i < repeat; ++i) + proofs.push_back(rct::bulletproof_PROVE(std::vector<uint64_t>(o, 749327532984), rct::skvGen(o))); + o = o * mul + add; + } + return true; + } + + bool test() + { + if (batch) + { + return rct::bulletproof_VERIFY(proofs); + } + else + { + for (const rct::Bulletproof &proof: proofs) + if (!rct::bulletproof_VERIFY(proof)) + return false; + return true; + } + } + +private: + std::vector<rct::Bulletproof> proofs; +}; diff --git a/tests/performance_tests/check_tx_signature.h b/tests/performance_tests/check_tx_signature.h index ec570e69d..ee382d9ad 100644 --- a/tests/performance_tests/check_tx_signature.h +++ b/tests/performance_tests/check_tx_signature.h @@ -40,14 +40,15 @@ #include "multi_tx_test_base.h" -template<size_t a_ring_size, bool a_rct> +template<size_t a_ring_size, size_t a_outputs, bool a_rct, rct::RangeProofType range_proof_type = rct::RangeProofBorromean> class test_check_tx_signature : private multi_tx_test_base<a_ring_size> { static_assert(0 < a_ring_size, "ring_size must be greater than 0"); public: - static const size_t loop_count = a_rct ? 10 : a_ring_size < 100 ? 100 : 10; + static const size_t loop_count = a_rct ? (a_ring_size <= 2 ? 50 : 10) : a_ring_size < 100 ? 100 : 10; static const size_t ring_size = a_ring_size; + static const size_t outputs = a_outputs; static const bool rct = a_rct; typedef multi_tx_test_base<a_ring_size> base_class; @@ -62,13 +63,15 @@ public: m_alice.generate(); std::vector<tx_destination_entry> destinations; - destinations.push_back(tx_destination_entry(this->m_source_amount, m_alice.get_keys().m_account_address, false)); + destinations.push_back(tx_destination_entry(this->m_source_amount - outputs + 1, m_alice.get_keys().m_account_address, false)); + for (size_t n = 1; n < outputs; ++n) + destinations.push_back(tx_destination_entry(1, m_alice.get_keys().m_account_address, false)); crypto::secret_key tx_key; std::vector<crypto::secret_key> additional_tx_keys; std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses; subaddresses[this->m_miners[this->real_source_idx].get_keys().m_account_address.m_spend_public_key] = {0,0}; - if (!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_tx, 0, tx_key, additional_tx_keys, rct)) + if (!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_tx, 0, tx_key, additional_tx_keys, rct, range_proof_type)) return false; get_transaction_prefix_hash(m_tx, m_tx_prefix_hash); @@ -80,7 +83,7 @@ public: { if (rct) { - if (m_tx.rct_signatures.type == rct::RCTTypeFull || m_tx.rct_signatures.type == rct::RCTTypeFullBulletproof) + if (m_tx.rct_signatures.type == rct::RCTTypeFull) return rct::verRct(m_tx.rct_signatures); else return rct::verRctSimple(m_tx.rct_signatures); @@ -97,3 +100,74 @@ private: cryptonote::transaction m_tx; crypto::hash m_tx_prefix_hash; }; + +template<size_t a_ring_size, size_t a_outputs, size_t a_num_txes, size_t extra_outs = 0> +class test_check_tx_signature_aggregated_bulletproofs : private multi_tx_test_base<a_ring_size> +{ + static_assert(0 < a_ring_size, "ring_size must be greater than 0"); + +public: + static const size_t loop_count = a_ring_size <= 2 ? 50 : 10; + static const size_t ring_size = a_ring_size; + static const size_t outputs = a_outputs; + + typedef multi_tx_test_base<a_ring_size> base_class; + + bool init() + { + using namespace cryptonote; + + if (!base_class::init()) + return false; + + m_alice.generate(); + + std::vector<tx_destination_entry> destinations; + destinations.push_back(tx_destination_entry(this->m_source_amount - outputs + 1, m_alice.get_keys().m_account_address, false)); + for (size_t n = 1; n < outputs; ++n) + destinations.push_back(tx_destination_entry(1, m_alice.get_keys().m_account_address, false)); + + crypto::secret_key tx_key; + std::vector<crypto::secret_key> additional_tx_keys; + std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses; + subaddresses[this->m_miners[this->real_source_idx].get_keys().m_account_address.m_spend_public_key] = {0,0}; + + m_txes.resize(a_num_txes + (extra_outs > 0 ? 1 : 0)); + for (size_t n = 0; n < a_num_txes; ++n) + { + if (!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_txes[n], 0, tx_key, additional_tx_keys, true, rct::RangeProofPaddedBulletproof)) + return false; + } + + if (extra_outs) + { + destinations.clear(); + destinations.push_back(tx_destination_entry(this->m_source_amount - extra_outs + 1, m_alice.get_keys().m_account_address, false)); + for (size_t n = 1; n < extra_outs; ++n) + destinations.push_back(tx_destination_entry(1, m_alice.get_keys().m_account_address, false)); + + if (!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_txes.back(), 0, tx_key, additional_tx_keys, true, rct::RangeProofMultiOutputBulletproof)) + return false; + } + + return true; + } + + bool test() + { + std::vector<const rct::rctSig*> rvv; + rvv.reserve(m_txes.size()); + for (size_t n = 0; n < m_txes.size(); ++n) + { + const rct::rctSig &rv = m_txes[n].rct_signatures; + if (!rct::verRctNonSemanticsSimple(rv)) + return false; + rvv.push_back(&rv); + } + return rct::verRctSemanticsSimple(rvv); + } + +private: + cryptonote::account_base m_alice; + std::vector<cryptonote::transaction> m_txes; +}; diff --git a/tests/performance_tests/construct_tx.h b/tests/performance_tests/construct_tx.h index 99c7f1b18..378065ddd 100644 --- a/tests/performance_tests/construct_tx.h +++ b/tests/performance_tests/construct_tx.h @@ -36,7 +36,7 @@ #include "multi_tx_test_base.h" -template<size_t a_in_count, size_t a_out_count, bool a_rct> +template<size_t a_in_count, size_t a_out_count, bool a_rct, rct::RangeProofType range_proof_type = rct::RangeProofBorromean> class test_construct_tx : private multi_tx_test_base<a_in_count> { static_assert(0 < a_in_count, "in_count must be greater than 0"); @@ -73,7 +73,7 @@ public: std::vector<crypto::secret_key> additional_tx_keys; std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses; subaddresses[this->m_miners[this->real_source_idx].get_keys().m_account_address.m_spend_public_key] = {0,0}; - return cryptonote::construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, m_destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_tx, 0, tx_key, additional_tx_keys, rct); + return cryptonote::construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, m_destinations, cryptonote::account_public_address{}, std::vector<uint8_t>(), m_tx, 0, tx_key, additional_tx_keys, rct, range_proof_type); } private: diff --git a/tests/performance_tests/crypto_ops.h b/tests/performance_tests/crypto_ops.h new file mode 100644 index 000000000..3c68583c5 --- /dev/null +++ b/tests/performance_tests/crypto_ops.h @@ -0,0 +1,122 @@ +// Copyright (c) 2014-2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include "crypto/crypto.h" +#include "ringct/rctOps.h" + +enum test_op +{ + op_sc_add, + op_sc_sub, + op_sc_mul, + op_ge_add_raw, + op_ge_add_p3_p3, + ops_fast, + + op_addKeys, + op_scalarmultBase, + op_scalarmultKey, + op_scalarmultH, + op_scalarmult8, + op_ge_double_scalarmult_base_vartime, + op_ge_double_scalarmult_precomp_vartime, + op_ge_double_scalarmult_precomp_vartime2, + op_addKeys2, + op_addKeys3, + op_addKeys3_2, + op_isInMainSubgroup, +}; + +template<test_op op> +class test_crypto_ops +{ +public: + static const size_t loop_count = op < ops_fast ? 10000000 : 1000; + + bool init() + { + scalar0 = rct::skGen(); + scalar1 = rct::skGen(); + point0 = rct::scalarmultBase(rct::skGen()); + point1 = rct::scalarmultBase(rct::skGen()); + if (ge_frombytes_vartime(&p3_0, point0.bytes) != 0) + return false; + if (ge_frombytes_vartime(&p3_1, point1.bytes) != 0) + return false; + ge_p3_to_cached(&cached, &p3_0); + rct::precomp(precomp0, point0); + rct::precomp(precomp1, point1); + return true; + } + + bool test() + { + rct::key key; + ge_cached tmp_cached; + ge_p1p1 tmp_p1p1; + ge_p2 tmp_p2; + switch (op) + { + case op_sc_add: sc_add(key.bytes, scalar0.bytes, scalar1.bytes); break; + case op_sc_sub: sc_sub(key.bytes, scalar0.bytes, scalar1.bytes); break; + case op_sc_mul: sc_mul(key.bytes, scalar0.bytes, scalar1.bytes); break; + case op_ge_add_p3_p3: { + ge_p3_to_cached(&tmp_cached, &p3_0); + ge_add(&tmp_p1p1, &p3_1, &tmp_cached); + ge_p1p1_to_p3(&p3_1, &tmp_p1p1); + break; + } + case op_ge_add_raw: ge_add(&tmp_p1p1, &p3_1, &cached); break; + case op_addKeys: rct::addKeys(key, point0, point1); break; + case op_scalarmultBase: rct::scalarmultBase(scalar0); break; + case op_scalarmultKey: rct::scalarmultKey(point0, scalar0); break; + case op_scalarmultH: rct::scalarmultH(scalar0); break; + case op_scalarmult8: rct::scalarmult8(point0); break; + case op_ge_double_scalarmult_base_vartime: ge_double_scalarmult_base_vartime(&tmp_p2, scalar0.bytes, &p3_0, scalar1.bytes); break; + case op_ge_double_scalarmult_precomp_vartime: ge_double_scalarmult_precomp_vartime(&tmp_p2, scalar0.bytes, &p3_0, scalar1.bytes, precomp0); break; + case op_ge_double_scalarmult_precomp_vartime2: ge_double_scalarmult_precomp_vartime2(&tmp_p2, scalar0.bytes, precomp0, scalar1.bytes, precomp1); break; + case op_addKeys2: rct::addKeys2(key, scalar0, scalar1, point0); break; + case op_addKeys3: rct::addKeys3(key, scalar0, point0, scalar1, precomp1); break; + case op_addKeys3_2: rct::addKeys3(key, scalar0, precomp0, scalar1, precomp1); break; + case op_isInMainSubgroup: rct::isInMainSubgroup(point0); break; + default: return false; + } + return true; + } + +private: + rct::key scalar0, scalar1; + rct::key point0, point1; + ge_p3 p3_0, p3_1; + ge_cached cached; + ge_dsmp precomp0, precomp1; +}; diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index 1733e3409..7c5135c65 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -46,12 +46,18 @@ #include "generate_key_image.h" #include "generate_key_image_helper.h" #include "generate_keypair.h" +#include "signature.h" #include "is_out_to_acc.h" #include "subaddress_expand.h" #include "sc_reduce32.h" #include "cn_fast_hash.h" #include "rct_mlsag.h" #include "equality.h" +#include "range_proof.h" +#include "rct_mlsag.h" +#include "bulletproof.h" +#include "crypto_ops.h" +#include "multiexp.h" namespace po = boost::program_options; @@ -63,11 +69,16 @@ int main(int argc, char** argv) set_thread_high_priority(); mlog_configure(mlog_get_default_log_path("performance_tests.log"), true); - mlog_set_log_level(0); po::options_description desc_options("Command line options"); const command_line::arg_descriptor<std::string> arg_filter = { "filter", "Regular expression filter for which tests to run" }; - command_line::add_arg(desc_options, arg_filter); + const command_line::arg_descriptor<bool> arg_verbose = { "verbose", "Verbose output", false }; + const command_line::arg_descriptor<bool> arg_stats = { "stats", "Including statistics (min/median)", false }; + const command_line::arg_descriptor<unsigned> arg_loop_multiplier = { "loop-multiplier", "Run for that many times more loops", 1 }; + command_line::add_arg(desc_options, arg_filter, ""); + command_line::add_arg(desc_options, arg_verbose, ""); + command_line::add_arg(desc_options, arg_stats, ""); + command_line::add_arg(desc_options, arg_loop_multiplier, ""); po::variables_map vm; bool r = command_line::handle_error_helper(desc_options, [&]() @@ -80,82 +91,455 @@ int main(int argc, char** argv) return 1; const std::string filter = tools::glob_to_regex(command_line::get_arg(vm, arg_filter)); + Params p; + p.verbose = command_line::get_arg(vm, arg_verbose); + p.stats = command_line::get_arg(vm, arg_stats); + p.loop_multiplier = command_line::get_arg(vm, arg_loop_multiplier); performance_timer timer; timer.start(); - TEST_PERFORMANCE3(filter, test_construct_tx, 1, 1, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 1, 2, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 1, 10, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 1, 100, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 1, 1000, false); - - TEST_PERFORMANCE3(filter, test_construct_tx, 2, 1, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 2, 2, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 2, 10, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 2, 100, false); - - TEST_PERFORMANCE3(filter, test_construct_tx, 10, 1, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 10, 2, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 10, 10, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 10, 100, false); - - TEST_PERFORMANCE3(filter, test_construct_tx, 100, 1, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 100, 2, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 100, 10, false); - TEST_PERFORMANCE3(filter, test_construct_tx, 100, 100, false); - - TEST_PERFORMANCE3(filter, test_construct_tx, 2, 1, true); - TEST_PERFORMANCE3(filter, test_construct_tx, 2, 2, true); - TEST_PERFORMANCE3(filter, test_construct_tx, 2, 10, true); - - TEST_PERFORMANCE3(filter, test_construct_tx, 10, 1, true); - TEST_PERFORMANCE3(filter, test_construct_tx, 10, 2, true); - TEST_PERFORMANCE3(filter, test_construct_tx, 10, 10, true); - - TEST_PERFORMANCE3(filter, test_construct_tx, 100, 1, true); - TEST_PERFORMANCE3(filter, test_construct_tx, 100, 2, true); - TEST_PERFORMANCE3(filter, test_construct_tx, 100, 10, true); - - TEST_PERFORMANCE2(filter, test_check_tx_signature, 1, false); - TEST_PERFORMANCE2(filter, test_check_tx_signature, 2, false); - TEST_PERFORMANCE2(filter, test_check_tx_signature, 10, false); - TEST_PERFORMANCE2(filter, test_check_tx_signature, 100, false); - - TEST_PERFORMANCE2(filter, test_check_tx_signature, 2, true); - TEST_PERFORMANCE2(filter, test_check_tx_signature, 10, true); - TEST_PERFORMANCE2(filter, test_check_tx_signature, 100, true); - - TEST_PERFORMANCE0(filter, test_is_out_to_acc); - TEST_PERFORMANCE0(filter, test_is_out_to_acc_precomp); - TEST_PERFORMANCE0(filter, test_generate_key_image_helper); - TEST_PERFORMANCE0(filter, test_generate_key_derivation); - TEST_PERFORMANCE0(filter, test_generate_key_image); - TEST_PERFORMANCE0(filter, test_derive_public_key); - TEST_PERFORMANCE0(filter, test_derive_secret_key); - TEST_PERFORMANCE0(filter, test_ge_frombytes_vartime); - TEST_PERFORMANCE0(filter, test_generate_keypair); - TEST_PERFORMANCE0(filter, test_sc_reduce32); - - TEST_PERFORMANCE2(filter, test_wallet2_expand_subaddresses, 50, 200); - - TEST_PERFORMANCE0(filter, test_cn_slow_hash); - TEST_PERFORMANCE1(filter, test_cn_fast_hash, 32); - TEST_PERFORMANCE1(filter, test_cn_fast_hash, 16384); - - TEST_PERFORMANCE3(filter, test_ringct_mlsag, 1, 3, false); - TEST_PERFORMANCE3(filter, test_ringct_mlsag, 1, 5, false); - TEST_PERFORMANCE3(filter, test_ringct_mlsag, 1, 10, false); - TEST_PERFORMANCE3(filter, test_ringct_mlsag, 1, 100, false); - TEST_PERFORMANCE3(filter, test_ringct_mlsag, 1, 3, true); - TEST_PERFORMANCE3(filter, test_ringct_mlsag, 1, 5, true); - TEST_PERFORMANCE3(filter, test_ringct_mlsag, 1, 10, true); - TEST_PERFORMANCE3(filter, test_ringct_mlsag, 1, 100, true); - - TEST_PERFORMANCE2(filter, test_equality, memcmp32, true); - TEST_PERFORMANCE2(filter, test_equality, memcmp32, false); - TEST_PERFORMANCE2(filter, test_equality, verify32, false); - TEST_PERFORMANCE2(filter, test_equality, verify32, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 1, 1, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 1, 2, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 1, 10, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 1, 100, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 1, 1000, false); + + TEST_PERFORMANCE3(filter, p, test_construct_tx, 2, 1, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 2, 2, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 2, 10, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 2, 100, false); + + TEST_PERFORMANCE3(filter, p, test_construct_tx, 10, 1, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 10, 2, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 10, 10, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 10, 100, false); + + TEST_PERFORMANCE3(filter, p, test_construct_tx, 100, 1, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 100, 2, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 100, 10, false); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 100, 100, false); + + TEST_PERFORMANCE3(filter, p, test_construct_tx, 2, 1, true); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 2, 2, true); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 2, 10, true); + + TEST_PERFORMANCE3(filter, p, test_construct_tx, 10, 1, true); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 10, 2, true); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 10, 10, true); + + TEST_PERFORMANCE3(filter, p, test_construct_tx, 100, 1, true); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 100, 2, true); + TEST_PERFORMANCE3(filter, p, test_construct_tx, 100, 10, true); + + TEST_PERFORMANCE4(filter, p, test_construct_tx, 2, 1, true, rct::RangeProofPaddedBulletproof); + TEST_PERFORMANCE4(filter, p, test_construct_tx, 2, 2, true, rct::RangeProofPaddedBulletproof); + TEST_PERFORMANCE4(filter, p, test_construct_tx, 2, 10, true, rct::RangeProofPaddedBulletproof); + + TEST_PERFORMANCE4(filter, p, test_construct_tx, 10, 1, true, rct::RangeProofPaddedBulletproof); + TEST_PERFORMANCE4(filter, p, test_construct_tx, 10, 2, true, rct::RangeProofPaddedBulletproof); + TEST_PERFORMANCE4(filter, p, test_construct_tx, 10, 10, true, rct::RangeProofPaddedBulletproof); + + TEST_PERFORMANCE4(filter, p, test_construct_tx, 100, 1, true, rct::RangeProofPaddedBulletproof); + TEST_PERFORMANCE4(filter, p, test_construct_tx, 100, 2, true, rct::RangeProofPaddedBulletproof); + TEST_PERFORMANCE4(filter, p, test_construct_tx, 100, 10, true, rct::RangeProofPaddedBulletproof); + + TEST_PERFORMANCE3(filter, p, test_check_tx_signature, 1, 2, false); + TEST_PERFORMANCE3(filter, p, test_check_tx_signature, 2, 2, false); + TEST_PERFORMANCE3(filter, p, test_check_tx_signature, 10, 2, false); + TEST_PERFORMANCE3(filter, p, test_check_tx_signature, 100, 2, false); + TEST_PERFORMANCE3(filter, p, test_check_tx_signature, 2, 10, false); + + TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 2, 2, true, rct::RangeProofBorromean); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 10, 2, true, rct::RangeProofBorromean); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 100, 2, true, rct::RangeProofBorromean); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 2, 10, true, rct::RangeProofBorromean); + + TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 2, 2, true, rct::RangeProofPaddedBulletproof); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 2, 2, true, rct::RangeProofMultiOutputBulletproof); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 10, 2, true, rct::RangeProofPaddedBulletproof); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 10, 2, true, rct::RangeProofMultiOutputBulletproof); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 100, 2, true, rct::RangeProofPaddedBulletproof); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 100, 2, true, rct::RangeProofMultiOutputBulletproof); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 2, 10, true, rct::RangeProofPaddedBulletproof); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature, 2, 10, true, rct::RangeProofMultiOutputBulletproof); + + TEST_PERFORMANCE3(filter, p, test_check_tx_signature_aggregated_bulletproofs, 2, 2, 64); + TEST_PERFORMANCE3(filter, p, test_check_tx_signature_aggregated_bulletproofs, 10, 2, 64); + TEST_PERFORMANCE3(filter, p, test_check_tx_signature_aggregated_bulletproofs, 100, 2, 64); + TEST_PERFORMANCE3(filter, p, test_check_tx_signature_aggregated_bulletproofs, 2, 10, 64); + + TEST_PERFORMANCE4(filter, p, test_check_tx_signature_aggregated_bulletproofs, 2, 2, 62, 4); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature_aggregated_bulletproofs, 10, 2, 62, 4); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature_aggregated_bulletproofs, 2, 2, 56, 16); + TEST_PERFORMANCE4(filter, p, test_check_tx_signature_aggregated_bulletproofs, 10, 2, 56, 16); + + TEST_PERFORMANCE0(filter, p, test_is_out_to_acc); + TEST_PERFORMANCE0(filter, p, test_is_out_to_acc_precomp); + TEST_PERFORMANCE0(filter, p, test_generate_key_image_helper); + TEST_PERFORMANCE0(filter, p, test_generate_key_derivation); + TEST_PERFORMANCE0(filter, p, test_generate_key_image); + TEST_PERFORMANCE0(filter, p, test_derive_public_key); + TEST_PERFORMANCE0(filter, p, test_derive_secret_key); + TEST_PERFORMANCE0(filter, p, test_ge_frombytes_vartime); + TEST_PERFORMANCE0(filter, p, test_generate_keypair); + TEST_PERFORMANCE0(filter, p, test_sc_reduce32); + TEST_PERFORMANCE1(filter, p, test_signature, false); + TEST_PERFORMANCE1(filter, p, test_signature, true); + + TEST_PERFORMANCE2(filter, p, test_wallet2_expand_subaddresses, 50, 200); + + TEST_PERFORMANCE0(filter, p, test_cn_slow_hash); + TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 32); + TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 16384); + + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 3, false); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 5, false); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 10, false); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 100, false); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 3, true); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 5, true); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 10, true); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 100, true); + + TEST_PERFORMANCE2(filter, p, test_equality, memcmp32, true); + TEST_PERFORMANCE2(filter, p, test_equality, memcmp32, false); + TEST_PERFORMANCE2(filter, p, test_equality, verify32, false); + TEST_PERFORMANCE2(filter, p, test_equality, verify32, false); + + TEST_PERFORMANCE1(filter, p, test_range_proof, true); + TEST_PERFORMANCE1(filter, p, test_range_proof, false); + + TEST_PERFORMANCE2(filter, p, test_bulletproof, true, 1); // 1 bulletproof with 1 amount + TEST_PERFORMANCE2(filter, p, test_bulletproof, false, 1); + + TEST_PERFORMANCE2(filter, p, test_bulletproof, true, 2); // 1 bulletproof with 2 amounts + TEST_PERFORMANCE2(filter, p, test_bulletproof, false, 2); + + TEST_PERFORMANCE2(filter, p, test_bulletproof, true, 15); // 1 bulletproof with 15 amounts + TEST_PERFORMANCE2(filter, p, test_bulletproof, false, 15); + + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof, false, 2, 1, 1, 0, 4); + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof, true, 2, 1, 1, 0, 4); // 4 proofs, each with 2 amounts + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof, false, 8, 1, 1, 0, 4); + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof, true, 8, 1, 1, 0, 4); // 4 proofs, each with 8 amounts + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof, false, 1, 1, 2, 0, 4); + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof, true, 1, 1, 2, 0, 4); // 4 proofs with 1, 2, 4, 8 amounts + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof, false, 1, 8, 1, 1, 4); + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof, true, 1, 8, 1, 1, 4); // 32 proofs, with 1, 2, 3, 4 amounts, 8 of each + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof, false, 2, 1, 1, 0, 64); + TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof, true, 2, 1, 1, 0, 64); // 64 proof, each with 2 amounts + + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 3, false); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 5, false); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 10, false); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 100, false); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 3, true); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 5, true); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 10, true); + TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 100, true); + + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_sc_add); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_sc_sub); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_sc_mul); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_add_raw); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_add_p3_p3); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmultBase); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmultKey); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmultH); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmult8); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_base_vartime); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_precomp_vartime); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_precomp_vartime2); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys2); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys3); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys3_2); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_isInMainSubgroup); + + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 2); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 4); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 8); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 16); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 32); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 64); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 128); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 256); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 512); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 1024); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 2048); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 4096); + + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus, 2); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus, 4); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus, 8); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus, 16); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus, 32); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus, 64); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus, 128); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus, 256); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus, 512); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus, 1024); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus, 2048); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus, 4096); + + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus_cached, 2); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus_cached, 4); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus_cached, 8); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus_cached, 16); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus_cached, 32); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus_cached, 64); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus_cached, 128); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus_cached, 256); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus_cached, 512); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus_cached, 1024); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus_cached, 2048); + TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_straus_cached, 4096); + +#if 1 + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 8, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 16, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 32, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 64, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 128, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 256, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 512, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 1024, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2048, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4096, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 8, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 16, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 32, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 64, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 128, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 256, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 512, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 1024, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2048, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4096, 9); +#else + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 8, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 8, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 8, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 8, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 8, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 8, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 8, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 8, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 8, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 16, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 16, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 16, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 16, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 16, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 16, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 16, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 16, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 16, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 32, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 32, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 32, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 32, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 32, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 32, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 32, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 32, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 32, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 64, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 64, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 64, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 64, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 64, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 64, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 64, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 64, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 64, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 128, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 128, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 128, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 128, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 128, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 128, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 128, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 128, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 128, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 256, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 256, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 256, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 256, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 256, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 256, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 256, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 256, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 256, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 512, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 512, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 512, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 512, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 512, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 512, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 512, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 512, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 512, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 1024, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 1024, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 1024, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 1024, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 1024, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 1024, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 1024, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 1024, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 1024, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2048, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2048, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2048, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2048, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2048, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2048, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2048, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2048, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 2048, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4096, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4096, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4096, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4096, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4096, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4096, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4096, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4096, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger_cached, 4096, 9); + + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 8, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 8, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 8, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 8, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 8, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 8, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 8, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 8, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 8, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 16, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 16, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 16, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 16, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 16, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 16, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 16, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 16, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 16, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 32, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 32, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 32, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 32, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 32, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 32, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 32, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 32, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 32, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 64, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 64, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 64, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 64, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 64, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 64, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 64, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 64, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 64, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 128, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 128, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 128, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 128, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 128, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 128, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 128, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 128, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 128, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 256, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 256, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 256, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 256, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 256, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 256, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 256, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 256, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 256, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 512, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 512, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 512, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 512, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 512, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 512, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 512, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 512, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 512, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 1024, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 1024, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 1024, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 1024, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 1024, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 1024, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 1024, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 1024, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 1024, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2048, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2048, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2048, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2048, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2048, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2048, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2048, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2048, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 2048, 9); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4096, 1); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4096, 2); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4096, 3); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4096, 4); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4096, 5); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4096, 6); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4096, 7); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4096, 8); + TEST_PERFORMANCE3(filter, p, test_multiexp, multiexp_pippenger, 4096, 9); +#endif std::cout << "Tests finished. Elapsed time: " << timer.elapsed_ms() / 1000 << " sec" << std::endl; diff --git a/tests/performance_tests/multiexp.h b/tests/performance_tests/multiexp.h new file mode 100644 index 000000000..b8b87b3a6 --- /dev/null +++ b/tests/performance_tests/multiexp.h @@ -0,0 +1,94 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include <vector> +#include "ringct/rctOps.h" +#include "ringct/multiexp.h" + +enum test_multiexp_algorithm +{ + multiexp_bos_coster, + multiexp_straus, + multiexp_straus_cached, + multiexp_pippenger, + multiexp_pippenger_cached, +}; + +template<test_multiexp_algorithm algorithm, size_t npoints, size_t c=0> +class test_multiexp +{ +public: + static const size_t loop_count = npoints >= 1024 ? 10 : npoints < 256 ? 1000 : 100; + + bool init() + { + data.resize(npoints); + res = rct::identity(); + for (size_t n = 0; n < npoints; ++n) + { + data[n].scalar = rct::skGen(); + rct::key point = rct::scalarmultBase(rct::skGen()); + if (ge_frombytes_vartime(&data[n].point, point.bytes)) + return false; + rct::key kn = rct::scalarmultKey(point, data[n].scalar); + res = rct::addKeys(res, kn); + } + straus_cache = rct::straus_init_cache(data); + pippenger_cache = rct::pippenger_init_cache(data); + return true; + } + + bool test() + { + switch (algorithm) + { + case multiexp_bos_coster: + return res == bos_coster_heap_conv_robust(data); + case multiexp_straus: + return res == straus(data); + case multiexp_straus_cached: + return res == straus(data, straus_cache); + case multiexp_pippenger: + return res == pippenger(data, NULL, c); + case multiexp_pippenger_cached: + return res == pippenger(data, pippenger_cache, c); + default: + return false; + } + } + +private: + std::vector<rct::MultiexpData> data; + std::shared_ptr<rct::straus_cached_data> straus_cache; + std::shared_ptr<rct::pippenger_cached_data> pippenger_cache; + rct::key res; +}; diff --git a/tests/performance_tests/performance_tests.h b/tests/performance_tests/performance_tests.h index 29d296571..d37dda729 100644 --- a/tests/performance_tests/performance_tests.h +++ b/tests/performance_tests/performance_tests.h @@ -36,6 +36,9 @@ #include <boost/chrono.hpp> #include <boost/regex.hpp> +#include "misc_language.h" +#include "common/perf_timer.h" + class performance_timer { public: @@ -62,13 +65,21 @@ private: clock::time_point m_start; }; +struct Params +{ + bool verbose; + bool stats; + unsigned loop_multiplier; +}; template <typename T> class test_runner { public: - test_runner() + test_runner(const Params ¶ms) : m_elapsed(0) + , m_params(params) + , m_per_call_timers(T::loop_count * params.loop_multiplier, {true}) { } @@ -81,13 +92,18 @@ public: performance_timer timer; timer.start(); warm_up(); - std::cout << "Warm up: " << timer.elapsed_ms() << " ms" << std::endl; + if (m_params.verbose) + std::cout << "Warm up: " << timer.elapsed_ms() << " ms" << std::endl; timer.start(); - for (size_t i = 0; i < T::loop_count; ++i) + for (size_t i = 0; i < T::loop_count * m_params.loop_multiplier; ++i) { + if (m_params.stats) + m_per_call_timers[i].resume(); if (!test.test()) return false; + if (m_params.stats) + m_per_call_timers[i].pause(); } m_elapsed = timer.elapsed_ms(); @@ -99,9 +115,62 @@ public: int time_per_call(int scale = 1) const { static_assert(0 < T::loop_count, "T::loop_count must be greater than 0"); - return m_elapsed * scale / T::loop_count; + return m_elapsed * scale / (T::loop_count * m_params.loop_multiplier); + } + + uint64_t per_call_min() const + { + uint64_t v = std::numeric_limits<uint64_t>::max(); + for (const auto &pt: m_per_call_timers) + v = std::min(v, pt.value()); + return v; + } + + uint64_t per_call_max() const + { + uint64_t v = std::numeric_limits<uint64_t>::min(); + for (const auto &pt: m_per_call_timers) + v = std::max(v, pt.value()); + return v; } + uint64_t per_call_mean() const + { + uint64_t v = 0; + for (const auto &pt: m_per_call_timers) + v += pt.value(); + return v / m_per_call_timers.size(); + } + + uint64_t per_call_median() const + { + std::vector<uint64_t> values; + values.reserve(m_per_call_timers.size()); + for (const auto &pt: m_per_call_timers) + values.push_back(pt.value()); + return epee::misc_utils::median(values); + } + + uint64_t per_call_stddev() const + { + if (m_per_call_timers.size() <= 1) + return 0; + const uint64_t mean = per_call_mean(); + uint64_t acc = 0; + for (const auto &pt: m_per_call_timers) + { + int64_t dv = pt.value() - mean; + acc += dv * dv; + } + acc /= m_per_call_timers.size () - 1; + return sqrt(acc); + } + + uint64_t min_time_ns() const { return tools::ticks_to_ns(per_call_min()); } + uint64_t max_time_ns() const { return tools::ticks_to_ns(per_call_max()); } + uint64_t median_time_ns() const { return tools::ticks_to_ns(per_call_median()); } + uint64_t standard_deviation_time_ns() const { return tools::ticks_to_ns(per_call_stddev()); } + private: /** * Warm up processor core, enabling turbo boost, etc. @@ -120,22 +189,39 @@ private: private: volatile uint64_t m_warm_up; ///<! This field is intended for preclude compiler optimizations int m_elapsed; + Params m_params; + std::vector<tools::PerformanceTimer> m_per_call_timers; }; template <typename T> -void run_test(const std::string &filter, const char* test_name) +void run_test(const std::string &filter, const Params ¶ms, const char* test_name) { boost::smatch match; if (!filter.empty() && !boost::regex_match(std::string(test_name), match, boost::regex(filter))) return; - test_runner<T> runner; + test_runner<T> runner(params); if (runner.run()) { - std::cout << test_name << " - OK:\n"; - std::cout << " loop count: " << T::loop_count << '\n'; - std::cout << " elapsed: " << runner.elapsed_time() << " ms\n"; + if (params.verbose) + { + std::cout << test_name << " - OK:\n"; + std::cout << " loop count: " << T::loop_count * params.loop_multiplier << '\n'; + std::cout << " elapsed: " << runner.elapsed_time() << " ms\n"; + if (params.stats) + { + std::cout << " min: " << runner.min_time_ns() << " ns\n"; + std::cout << " max: " << runner.max_time_ns() << " ns\n"; + std::cout << " median: " << runner.median_time_ns() << " ns\n"; + std::cout << " std dev: " << runner.standard_deviation_time_ns() << " ns\n"; + } + } + else + { + std::cout << test_name << " (" << T::loop_count * params.loop_multiplier << " calls) - OK:"; + } const char *unit = "ms"; + uint64_t scale = 1000000; int time_per_call = runner.time_per_call(); if (time_per_call < 30000) { time_per_call = runner.time_per_call(1000); @@ -144,8 +230,17 @@ void run_test(const std::string &filter, const char* test_name) #else unit = "µs"; #endif + scale = 1000; + } + std::cout << (params.verbose ? " time per call: " : " ") << time_per_call << " " << unit << "/call" << (params.verbose ? "\n" : ""); + if (params.stats) + { + uint64_t min_ns = runner.min_time_ns() / scale; + uint64_t med_ns = runner.median_time_ns() / scale; + uint64_t stddev_ns = runner.standard_deviation_time_ns() / scale; + std::cout << " (min " << min_ns << " " << unit << ", median " << med_ns << " " << unit << ", std dev " << stddev_ns << " " << unit << ")"; } - std::cout << " time per call: " << time_per_call << " " << unit << "/call\n" << std::endl; + std::cout << std::endl; } else { @@ -154,7 +249,10 @@ void run_test(const std::string &filter, const char* test_name) } #define QUOTEME(x) #x -#define TEST_PERFORMANCE0(filter, test_class) run_test< test_class >(filter, QUOTEME(test_class)) -#define TEST_PERFORMANCE1(filter, test_class, a0) run_test< test_class<a0> >(filter, QUOTEME(test_class<a0>)) -#define TEST_PERFORMANCE2(filter, test_class, a0, a1) run_test< test_class<a0, a1> >(filter, QUOTEME(test_class) "<" QUOTEME(a0) ", " QUOTEME(a1) ">") -#define TEST_PERFORMANCE3(filter, test_class, a0, a1, a2) run_test< test_class<a0, a1, a2> >(filter, QUOTEME(test_class) "<" QUOTEME(a0) ", " QUOTEME(a1) ", " QUOTEME(a2) ">") +#define TEST_PERFORMANCE0(filter, params, test_class) run_test< test_class >(filter, params, QUOTEME(test_class)) +#define TEST_PERFORMANCE1(filter, params, test_class, a0) run_test< test_class<a0> >(filter, params, QUOTEME(test_class<a0>)) +#define TEST_PERFORMANCE2(filter, params, test_class, a0, a1) run_test< test_class<a0, a1> >(filter, params, QUOTEME(test_class) "<" QUOTEME(a0) ", " QUOTEME(a1) ">") +#define TEST_PERFORMANCE3(filter, params, test_class, a0, a1, a2) run_test< test_class<a0, a1, a2> >(filter, params, QUOTEME(test_class) "<" QUOTEME(a0) ", " QUOTEME(a1) ", " QUOTEME(a2) ">") +#define TEST_PERFORMANCE4(filter, params, test_class, a0, a1, a2, a3) run_test< test_class<a0, a1, a2, a3> >(filter, params, QUOTEME(test_class) "<" QUOTEME(a0) ", " QUOTEME(a1) ", " QUOTEME(a2) ", " QUOTEME(a3) ">") +#define TEST_PERFORMANCE5(filter, params, test_class, a0, a1, a2, a3, a4) run_test< test_class<a0, a1, a2, a3, a4> >(filter, params, QUOTEME(test_class) "<" QUOTEME(a0) ", " QUOTEME(a1) ", " QUOTEME(a2) ", " QUOTEME(a3) ", " QUOTEME(a4) ">") +#define TEST_PERFORMANCE6(filter, params, test_class, a0, a1, a2, a3, a4, a5) run_test< test_class<a0, a1, a2, a3, a4, a5> >(filter, params, QUOTEME(test_class) "<" QUOTEME(a0) ", " QUOTEME(a1) ", " QUOTEME(a2) ", " QUOTEME(a3) ", " QUOTEME(a4) ", " QUOTEME(a5) ">") diff --git a/tests/performance_tests/range_proof.h b/tests/performance_tests/range_proof.h new file mode 100644 index 000000000..0ce962cd9 --- /dev/null +++ b/tests/performance_tests/range_proof.h @@ -0,0 +1,63 @@ +// Copyright (c) 2014-2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include "ringct/rctSigs.h" + +template<bool a_verify> +class test_range_proof +{ +public: + static const size_t loop_count = 50; + static const bool verify = a_verify; + + bool init() + { + rct::key mask; + sig = rct::proveRange(C, mask, 84932483243793); + return true; + } + + bool test() + { + bool ret = true; + rct::key mask; + if (verify) + ret = rct::verRange(C, sig); + else + rct::proveRange(C, mask, 84932483243793); + return ret; + } + +private: + rct::key C; + rct::rangeSig sig; +}; diff --git a/tests/performance_tests/signature.h b/tests/performance_tests/signature.h new file mode 100644 index 000000000..21110b525 --- /dev/null +++ b/tests/performance_tests/signature.h @@ -0,0 +1,68 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include "crypto/crypto.h" +#include "cryptonote_basic/cryptonote_basic.h" + +#include "single_tx_test_base.h" + +template<bool verify> +class test_signature : public single_tx_test_base +{ +public: + static const size_t loop_count = 10000; + + bool init() + { + if (!single_tx_test_base::init()) + return false; + + message = crypto::rand<crypto::hash>(); + keys = cryptonote::keypair::generate(hw::get_device("default")); + crypto::generate_signature(message, keys.pub, keys.sec, m_signature); + + return true; + } + + bool test() + { + if (verify) + return crypto::check_signature(message, keys.pub, m_signature); + crypto::generate_signature(message, keys.pub, keys.sec, m_signature); + return true; + } + +private: + cryptonote::keypair keys; + crypto::hash message; + crypto::signature m_signature; +}; |