libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
unordered_tuple_performance.cpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2017 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 #include "stdafx.h"
20 
21 #define BOOST_TEST_MODULE libjmmcg_tests
22 #include <boost/test/included/unit_test.hpp>
23 
24 #include "core/ave_deviation_meter.hpp"
25 #include "core/stats_output.hpp"
26 #include "core/unordered_tuple.hpp"
27 
28 #include <chrono>
29 #include <memory>
30 #include <unordered_map>
31 
32 using namespace libjmmcg;
33 
34 using timed_results_t=ave_deviation_meter<unsigned long long>;
35 
36 struct base {
37  using key_type=std::int32_t;
38 
39  struct hasher {
40  constexpr key_type operator()(key_type k) const noexcept(true) {
41  return k;
42  }
43  constexpr key_type operator()(key_type k, std::size_t) const noexcept(true) {
44  return k;
45  }
46  };
47 
48  virtual ~base()=default;
49 
50  virtual unsigned long fn(unsigned long j) const=0;
51 };
52 struct derived1 final : base {
53  static constexpr base::key_type hash=0;
54 
55  const unsigned long i_;
56 
57  explicit derived1(unsigned long i)
58  : i_(i) {}
59 
60  unsigned long fn(unsigned long j) const override {
61  return i_*j;
62  }
63 };
64 constexpr base::key_type derived1::hash;
65 struct derived2 final : base {
66  static constexpr base::key_type hash=1;
67 
68  const unsigned long i_;
69 
70  explicit derived2(unsigned long i)
71  : i_(i) {}
72 
73  unsigned long fn(unsigned long j) const override {
74  return i_+j;
75  }
76 };
77 constexpr base::key_type derived2::hash;
78 
79 template<class T>
80 struct extract {
81  static constexpr const typename T::key_type value=T::hash;
82 };
83 
84 BOOST_AUTO_TEST_SUITE(unordered_tuple_tests)
85 
86 BOOST_AUTO_TEST_SUITE(performance, *stats_to_csv::make_fixture("unordered_tuple_performance.csv"))
87 
88 /**
89  \test <a href="./examples/unordered_tuple_performance.svg">Graph</a> of performance results for operations on an unordered_tuple & unordered_map.
90  ==========================================================================================
91  Call a pure-virtual member-function in a base class of a class found in an unordered collection.
92 */
93 BOOST_AUTO_TEST_CASE(unordered_tuple_perf) {
94  using collection_type=unordered_tuple<base::key_type, base, base::hasher, extract, derived1, derived2>;
95 
96  collection_type colln(derived1(667), derived2(42));
97  unsigned long res=0;
98 #ifdef JMMCG_PERFORMANCE_TESTS
99  const unsigned long test_size=2<<22;
100 #else
101  const unsigned long test_size=2<<2;
102 #endif
103  const unsigned short loops_for_conv=1000;
104  const double perc_conv_estimate=2.0;
105 
106  const std::pair<timed_results_t, bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
107  perc_conv_estimate,
108  loops_for_conv,
109  [&colln, &res]() {
110  const auto t1=std::chrono::high_resolution_clock::now();
111  for (unsigned long i=0; i<test_size; ++i) {
112  res+=colln[i%2].fn(i);
113  }
114  const auto t2=std::chrono::high_resolution_clock::now();
115  return timed_results_t::value_type(static_cast<double>(test_size)*1000000/std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count());
116  }
117  ));
118  BOOST_CHECK_GT(res, 0);
119  std::cout<<typeid(collection_type).name()<<" operations/sec="<<timed_results.first<<std::endl;
120 #ifdef JMMCG_PERFORMANCE_TESTS
121  stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
122  BOOST_CHECK(!timed_results.second);
123 #endif
124 }
125 
126 /**
127  \test <a href="./examples/unordered_tuple_performance.svg">Graph</a> of performance results for operations on an unordered_map.
128  ==========================================================================================
129  Call a pure-virtual member-function in a base class of a class found in a std::unordered_map.
130 */
131 BOOST_AUTO_TEST_CASE(unordered_map_perf) {
132  using base_t=std::shared_ptr<base>;
133  using collection_type=std::unordered_map<base::key_type, base_t>;
134 
135  collection_type colln;
136  colln.emplace(derived1::hash, std::make_shared<derived1>(667));
137  colln.emplace(derived2::hash, std::make_shared<derived2>(42));
138  unsigned long res=0;
139 #ifdef JMMCG_PERFORMANCE_TESTS
140  const unsigned long test_size=2<<22;
141 #else
142  const unsigned long test_size=2<<2;
143 #endif
144  const unsigned short loops_for_conv=1000;
145  const double perc_conv_estimate=2.0;
146 
147  const std::pair<timed_results_t, bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
148  perc_conv_estimate,
149  loops_for_conv,
150  [&colln, &res]() {
151  const auto t1=std::chrono::high_resolution_clock::now();
152  for (unsigned long i=0; i<test_size; ++i) {
153  res+=colln[i%2]->fn(i);
154  }
155  const auto t2=std::chrono::high_resolution_clock::now();
156  return timed_results_t::value_type(static_cast<double>(test_size)*1000000/std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count());
157  }
158  ));
159  BOOST_CHECK_GT(res, 0);
160  std::cout<<typeid(collection_type).name()<<" operations/sec="<<timed_results.first<<std::endl;
161 #ifdef JMMCG_PERFORMANCE_TESTS
162  stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
163  BOOST_CHECK(!timed_results.second);
164 #endif
165 }
166 
167 BOOST_AUTO_TEST_SUITE_END()
168 
169 BOOST_AUTO_TEST_SUITE_END()