diff options
author | Roland Reichwein <mail@reichwein.it> | 2022-01-04 19:45:01 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2022-01-04 19:45:01 +0100 |
commit | d75cefda8a5ea08976d6bb512150d7c6891ac73e (patch) | |
tree | 47519da89eb2d4d833368fddf33bcd02b12da86c /src | |
parent | 037aab267c81f0bedff1ff21b2ff82217f6a9d59 (diff) |
Performance tests on deterministic data
Diffstat (limited to 'src')
-rw-r--r-- | src/test-performance.cpp | 80 |
1 files changed, 46 insertions, 34 deletions
diff --git a/src/test-performance.cpp b/src/test-performance.cpp index 629aadd..64535c6 100644 --- a/src/test-performance.cpp +++ b/src/test-performance.cpp @@ -19,7 +19,6 @@ #include <limits> #include <list> #include <locale> -#include <random> #include <string> #include <tuple> #include <type_traits> @@ -34,49 +33,68 @@ using namespace std::string_literals; typedef std::tuple<std::basic_string<utf8_t>, std::basic_string<char16_t>, std::basic_string<char32_t>> types_collection_type; -struct random_context { - random_context(int max_value = 0x10FFFF - 0x800): code_point_distribution(0, max_value) {} - std::random_device rd; // OS random number engine to seed RNG (below) - std::mt19937 gen{rd()}; - std::uniform_int_distribution<size_t> sequence_length{0, 100000}; // length of sequence: 0 ... 100000 code units - std::uniform_int_distribution<unsigned long> code_point_distribution; -}; +// LCG for generating deterministic mixed data, see also https://arxiv.org/pdf/2001.05304.pdf +uint8_t generate_byte() +{ + static uint64_t x{1}; + const static uint32_t a{0x915f77f5}; + const static uint32_t c{12345}; + const static uint32_t m_mask{0xFFFFFFFF}; + + x = (x * a + c) & m_mask; + + return (x >> 16) & 0xFF; +} + +// max is inclusive +template<typename T> +T generate_value(T max = std::numeric_limits<T>::max()) +{ + uint64_t max_modulo{ static_cast<uint64_t>(0x100000000ULL) - (0x100000000ULL % (max + 1))}; + + uint32_t value{}; + do { + for (int i = 0; i < sizeof(value); ++i) { + value = (value << 8) | generate_byte(); + } + } while (static_cast<uint64_t>(value) >= max_modulo); + + return static_cast<T>(value % (max + 1)); +} // generates valid and invalid strings of different type template<typename T> -T generate_random_invalid(random_context& rc, size_t length) +T generate_string_invalid(size_t length) { - // Using unsigned long for std::uniform_int_distribution<> because it needs to be basic type according to MSVC - std::uniform_int_distribution<unsigned long> code_unit{0, std::numeric_limits<typename T::value_type>::max()}; // code unit value T result; - std::generate_n(std::back_inserter(result), length, [&](){return static_cast<typename T::value_type>(code_unit(rc.gen));}); + std::generate_n(std::back_inserter(result), length, [&](){return generate_value<typename T::value_type>();}); return result; } -char32_t generate_random_char(random_context& rc) +char32_t generate_char(char32_t max = 0x10FFFF - 0x800) { - auto result {rc.code_point_distribution(rc.gen)}; + char32_t result {generate_value<char32_t>(max)}; if (result >= 0xD800) result += 0x800; return static_cast<char32_t>(result); } -std::u32string generate_random_string(random_context& rc, size_t length) +std::u32string generate_string(char32_t max, size_t length) { std::u32string result; - std::generate_n(std::back_inserter(result), length, [&](){return generate_random_char(rc);}); + std::generate_n(std::back_inserter(result), length, [&](){return generate_char(max);}); return result; } template<typename From, typename ToTypesCollectionType, size_t i = 0> -void test_random_invalid(random_context& rc, size_t length) +void test_string_invalid(size_t length) { //std::cerr << "LENGTH: " << length << std::endl; typedef typename std::tuple_element<i,ToTypesCollectionType>::type To; - From r {static_cast<From>(generate_random_invalid<From>(rc, length))}; + From r {static_cast<From>(generate_string_invalid<From>(length))}; // base type interface try { @@ -125,15 +143,13 @@ void test_random_invalid(random_context& rc, size_t length) // iterate over remaining To types if constexpr (i + 1 < std::tuple_size<ToTypesCollectionType>::value) - test_random_invalid<From, ToTypesCollectionType, i + 1>(rc, length); + test_string_invalid<From, ToTypesCollectionType, i + 1>(length); } -BOOST_AUTO_TEST_CASE_TEMPLATE(random_sequences_invalid, T, types_collection_type) +BOOST_AUTO_TEST_CASE_TEMPLATE(sequences_invalid, T, types_collection_type) { - random_context rc; - for (int i = 0; i < 10; i++) { - test_random_invalid<T,types_collection_type>(rc, rc.sequence_length(rc.gen)); + test_string_invalid<T,types_collection_type>(generate_value<size_t>(100000)); } } @@ -166,13 +182,13 @@ private: }; template<typename From, typename ToTypesCollectionType, size_t index = 0> -void test_random_valid(random_context& rc, size_t length, const std::string& description) +void test_string_valid(char32_t max, size_t length, const std::string& description) { typedef typename std::tuple_element<index,ToTypesCollectionType>::type To; // Fill UTF-32 data list: source for tests std::vector<std::u32string> u32list; - std::generate_n(std::back_inserter(u32list), 1000, [&](){return generate_random_string(rc, rc.sequence_length(rc.gen));}); + std::generate_n(std::back_inserter(u32list), 1000, [&](){return generate_string(max, generate_value<size_t>(100000));}); // Fill From data list std::vector<From> list; @@ -211,20 +227,16 @@ void test_random_valid(random_context& rc, size_t length, const std::string& des // iterate over remaining To types if constexpr (index + 1 < std::tuple_size<ToTypesCollectionType>::value) - test_random_valid<From, ToTypesCollectionType, index + 1>(rc, length, description); + test_string_valid<From, ToTypesCollectionType, index + 1>(max, length, description); } -BOOST_AUTO_TEST_CASE_TEMPLATE(random_sequences_valid_ascii, T, types_collection_type) +BOOST_AUTO_TEST_CASE_TEMPLATE(sequences_valid_ascii, T, types_collection_type) { - random_context rc{127}; - - test_random_valid<T,types_collection_type>(rc, rc.sequence_length(rc.gen), "ASCII only strings"); + test_string_valid<T,types_collection_type>(127, generate_value<size_t>(100000), "ASCII only strings"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(random_sequences_valid_all_unicode, T, types_collection_type) +BOOST_AUTO_TEST_CASE_TEMPLATE(sequences_valid_all_unicode, T, types_collection_type) { - random_context rc; - - test_random_valid<T,types_collection_type>(rc, rc.sequence_length(rc.gen), "All Unicode strings"); + test_string_valid<T,types_collection_type>(0x10FFFF - 0x800, generate_value<size_t>(100000), "All Unicode strings"); } |