Alchemy  1.0
A framework to robustly process network messages and structured data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
benchmark.cpp
Go to the documentation of this file.
1 /// @file benchmark.cpp
2 ///
3 /// Performs a basic set of benchmark tests for comparison with other implementations..
4 ///
5 /// The MIT License(MIT)
6 /// @copyright 2014 Paul M Watt
7 // ****************************************************************************
8 #include <benchmark_util.h>
9 #include <benchmark_formats.h>
10 #include <iostream>
11 #include <iomanip>
12 #include <string>
13 #include <vector>
14 
15 #include <using_Hg.h>
16 #include <using_memcpy.h>
17 
18 
19 // ****************************************************************************
20 typedef std::vector<double> TimeValues;
21 using std::cin;
22 using std::cout;
23 using std::endl;
24 
25 
26 namespace alchemy
27 {
28 namespace benchmark
29 {
30 
31 const size_t k_cycles = 0x20000000;
32 
33 enum TimeIndex
34 {
35  k_start_no_conv = 0,
36  k_end_no_conv,
37  k_start_basic,
38  k_end_basic,
39  k_start_packed,
40  k_end_packed,
41  k_start_unaligned,
42  k_end_unaligned,
43  k_start_complex,
44  k_end_complex,
45  k_start_array,
46  k_end_array
47 };
48 
49 
50 // ****************************************************************************
51 template <class T>
52 void RunTest(DataBuffer &data, TimeValues &times)
53 {
54  DataBuffer output(data.Size());
55  std::vector<int> X;
56 
57  times.clear();
58 
59  // Run and record the end of the NoConversion test.
60  data.Reset();
61  output.Restart();
62 
63  times.push_back(get_time());
64  T::test_no_conversion(data, output);
65  times.push_back(get_time());
66 
67  // Run and record the end of the Basic test.
68  data.Reset();
69  output.Restart();
70 
71  times.push_back(get_time());
72  T::test_basic(data, output);
73  times.push_back(get_time());
74 
75  // Run and record the end of the PackedBits test.
76  data.Reset();
77  output.Restart();
78 
79  times.push_back(get_time());
80  T::test_packed_bits(data, output);
81  times.push_back(get_time());
82 
83  // Run and record the end of the Unaligned test.
84  data.Reset();
85  output.Restart();
86 
87  times.push_back(get_time());
88  T::test_unaligned(data, output);
89  times.push_back(get_time());
90 
91  // Run and record the end of the Complex test.
92  data.Reset();
93  output.Restart();
94 
95  times.push_back(get_time());
96  T::test_complex(data, output);
97  times.push_back(get_time());
98 
99  // Run and record the end of the Array test.
100  data.Reset();
101  output.Restart();
102 
103  times.push_back(get_time());
104  T::test_array(data, output);
105  times.push_back(get_time());
106 }
107 
108 
109 // ****************************************************************************
110 void DisplayResults(const std::string &control_name,
111  const TimeValues &control_times,
112  const std::string &name,
113  const TimeValues &times)
114 {
115  using std::setw;
116  using std::left;
117 
118  double c_basic_len = control_times[k_end_basic] - control_times[k_start_basic];
119  double c_packed_len = control_times[k_end_packed] - control_times[k_start_packed];
120  double c_unaligned_len = control_times[k_end_unaligned] - control_times[k_start_unaligned];
121  double c_complex_len = control_times[k_end_complex] - control_times[k_start_complex];
122  double c_array_len = control_times[k_end_array] - control_times[k_start_array];
123  double c_total_len = c_basic_len + c_packed_len + c_unaligned_len + c_complex_len + c_array_len;
124 
125  double basic_len = times[k_end_basic] - times[k_start_basic];
126  double packed_len = times[k_end_packed] - times[k_start_packed];
127  double unaligned_len = times[k_end_unaligned] - times[k_start_unaligned];
128  double complex_len = times[k_end_complex] - times[k_start_complex];
129  double array_len = times[k_end_array] - times[k_start_array];
130  double total_len = basic_len + packed_len + unaligned_len + complex_len + array_len;
131 
132  cout << "-------------------------------------------------------------------------\n";
133  cout << "These scenarios are trivial to write by hand,\n"
134  << "and are currently outside of Alchemy's capabilities.\n"
135  << "Therefore, Alchemy woefully underperforms in these scenarios.\n\n";
136 
137  double c_no_conv_len = control_times[k_end_no_conv] - control_times[k_start_no_conv];
138  double no_conv_len = times[k_end_no_conv] - times[k_start_no_conv];
139  cout << "Scenario: " << control_name << "\t\t"<< name << "\tdiff\t\tpercent\n";
140  cout << "------------- ---------- ---------- ---------- ---------\n";
141  cout << "NoConversion: " << setw(10) << left << c_no_conv_len << "s\t" << setw(10) << left << no_conv_len << "s\t" << (no_conv_len - c_no_conv_len ) << "\t" << 100.0 - (no_conv_len / c_no_conv_len ) * 100.0 << "%\n\n\n";
142 
143 
144  cout << "-------------------------------------------------------------------------\n";
145  cout << "diff: Is time difference calculated as 'control' - 'Hg'\n";
146  cout << "percent: Value indicates 'Hg' performance (+ is better)\n\n";
147 
148  cout << "Test: " << control_name << "\t\t"<< name << "\tdiff\t\tpercent\n";
149  cout << "------------- ---------- ---------- ---------- ---------\n";
150  cout << "Basic: " << setw(10) << left << c_basic_len << "s\t" << setw(10) << basic_len << "s\t" << (basic_len - c_basic_len ) << "\t" << 100.0 - (basic_len / c_basic_len ) * 100.0 << "%\n"
151  << "Packed: " << setw(10) << left << c_packed_len << "s\t" << setw(10) << packed_len << "s\t" << (packed_len - c_packed_len ) << "\t" << 100.0 - (packed_len / c_packed_len ) * 100.0 << "%\n"
152  << "Unaligned: " << setw(10) << left << c_unaligned_len << "s\t" << setw(10) << unaligned_len << "s\t" << (unaligned_len - c_unaligned_len) << "\t" << 100.0 - (unaligned_len / c_unaligned_len) * 100.0 << "%\n"
153  << "Complex: " << setw(10) << left << c_complex_len << "s\t" << setw(10) << complex_len << "s\t" << (complex_len - c_complex_len ) << "\t" << 100.0 - (complex_len / c_complex_len ) * 100.0 << "%\n"
154  << "Array: " << setw(10) << left << c_array_len << "s\t" << setw(10) << array_len << "s\t" << (array_len - c_array_len ) << "\t" << 100.0 - (array_len / c_array_len ) * 100.0 << "%\n"
155  << "Total: " << setw(10) << left << c_total_len << "s\t" << setw(10) << total_len << "s\t" << (total_len - c_total_len ) << "\t" << 100.0 - (total_len / c_total_len ) * 100.0 << "%\n"
156  << "\n\n";
157  cout << "-------------------------------------------------------------------------\n\n";
158 }
159 
160 } // namespace benchmark
161 } // namespace alchemy
162 
163 // ****************************************************************************
164 int main(int argc, char* argv[])
165 {
166  using namespace alchemy::benchmark;
167 
168  cout << "Loading test data:" << endl;
169  // Pre-allocate memory for processing.
170  DataBuffer data;
171  data.Init(k_cycles);
172 
173  cout << "Hit enter when ready...:";
174  cin.ignore();
175 
176  // Run the test scenario for each type of implementation.
177  cout << "\nRunning control benchmark:"
178  << "\n--------------------------" << endl;
179 
180  TimeValues memcpyTime;
181  RunTest<UsingMemcpy>(data, memcpyTime);
182  cout << "Test completed\n" << endl;
183 
184  cout << "\nRunning Hg benchmark:"
185  << "\n--------------------------" << endl;
186 
187  TimeValues hgTime;
188  RunTest<UsingHg>(data, hgTime);
189  cout << "Test completed\n" << endl;
190 
191  // Display the tabulated results.
192  DisplayResults( "memcpy: ", memcpyTime,
193  "Hg: ", hgTime);
194 
195  cout << "Hit enter to exit.";
196  cin.ignore();
197 
198  return 0;
199 }
200 
201 
202