Alchemy  1.0
A framework to robustly process network messages and structured data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
using_memcpy.cpp
Go to the documentation of this file.
1 /// @file using_memcpy.cpp
2 ///
3 /// Implements message parsing by using memcpy when possible.
4 ///
5 /// The MIT License(MIT)
6 /// @copyright 2014 Paul M Watt
7 // ****************************************************************************
8 // Includes *******************************************************************
9 #include <using_memcpy.h>
10 #include <Hg.h>
11 #include <iostream>
12 
13 using std::cout;
14 using std::endl;
15 
16 // ****************************************************************************
17 void ReadNoConversion(alchemy::benchmark::DataBuffer &data,
18  alchemy::benchmark::NoConversion &msg)
19 {
20  // Read the basic field data in.
21  ::memcpy(&msg.ch_0, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
22  ::memcpy(&msg.ch_1, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
23  ::memcpy(&msg.ch_2, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
24  ::memcpy(&msg.ch_3, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
25  ::memcpy(&msg.ch_4, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
26  ::memcpy(&msg.ch_5, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
27  ::memcpy(&msg.ch_6, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
28  ::memcpy(&msg.ch_7, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
29  ::memcpy(&msg.ch_8, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
30  ::memcpy(&msg.ch_9, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
31  ::memcpy(&msg.ch_10, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
32  ::memcpy(&msg.ch_11, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
33  ::memcpy(&msg.ch_12, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
34  ::memcpy(&msg.ch_13, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
35  ::memcpy(&msg.ch_14, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
36  ::memcpy(&msg.ch_15, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
37  // ::memcpy(&msg, data.GetBytes(sizeof(alchemy::benchmark::NoConversion)), sizeof(alchemy::benchmark::NoConversion));
38 }
39 
40 // ****************************************************************************
41 void WriteNoConversion( alchemy::benchmark::DataBuffer &data,
42  alchemy::benchmark::NoConversion &msg)
43 {
44  // Read the basic field data in.
45  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_0, sizeof(uint32_t));
46  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_1, sizeof(uint32_t));
47  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_2, sizeof(uint32_t));
48  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_3, sizeof(uint32_t));
49  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_4, sizeof(uint32_t));
50  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_5, sizeof(uint32_t));
51  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_6, sizeof(uint32_t));
52  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_7, sizeof(uint32_t));
53  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_8, sizeof(uint32_t));
54  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_9, sizeof(uint32_t));
55  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_10, sizeof(uint32_t));
56  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_11, sizeof(uint32_t));
57  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_12, sizeof(uint32_t));
58  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_13, sizeof(uint32_t));
59  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_14, sizeof(uint32_t));
60  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.ch_15, sizeof(uint32_t));
61 // ::memcpy(data.GetBytes(sizeof(alchemy::benchmark::NoConversion)), &msg, sizeof(alchemy::benchmark::NoConversion));
62 }
63 
64 // ****************************************************************************
65 void NoConversionToNetwork( const alchemy::benchmark::NoConversion &host,
66  alchemy::benchmark::NoConversion &net)
67 {
68  // Read the basic field data in.
69  ::memcpy(&net.ch_0, &host.ch_0, sizeof(uint32_t));
70  ::memcpy(&net.ch_1, &host.ch_1, sizeof(uint32_t));
71  ::memcpy(&net.ch_2, &host.ch_2, sizeof(uint32_t));
72  ::memcpy(&net.ch_3, &host.ch_3, sizeof(uint32_t));
73  ::memcpy(&net.ch_4, &host.ch_4, sizeof(uint32_t));
74  ::memcpy(&net.ch_5, &host.ch_5, sizeof(uint32_t));
75  ::memcpy(&net.ch_6, &host.ch_6, sizeof(uint32_t));
76  ::memcpy(&net.ch_7, &host.ch_7, sizeof(uint32_t));
77  ::memcpy(&net.ch_8, &host.ch_8, sizeof(uint32_t));
78  ::memcpy(&net.ch_9, &host.ch_9, sizeof(uint32_t));
79  ::memcpy(&net.ch_10, &host.ch_10, sizeof(uint32_t));
80  ::memcpy(&net.ch_11, &host.ch_11, sizeof(uint32_t));
81  ::memcpy(&net.ch_12, &host.ch_12, sizeof(uint32_t));
82  ::memcpy(&net.ch_13, &host.ch_13, sizeof(uint32_t));
83  ::memcpy(&net.ch_14, &host.ch_14, sizeof(uint32_t));
84  ::memcpy(&net.ch_15, &host.ch_15, sizeof(uint32_t));
85  //::memcpy(&net, &host, sizeof(alchemy::benchmark::NoConversion));
86 }
87 
88 // ****************************************************************************
89 void ReadBasic( alchemy::benchmark::DataBuffer &data,
90  alchemy::benchmark::Basic &msg)
91 {
92  // Read the basic field data in.
93  ::memcpy(&msg.i32, data.GetBytes(sizeof(int32_t)), sizeof(int32_t));
94  ::memcpy(&msg.u32, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
95  ::memcpy(&msg.i16, data.GetBytes(sizeof(int16_t)), sizeof(int16_t));
96  ::memcpy(&msg.u16, data.GetBytes(sizeof(uint16_t)), sizeof(uint16_t));
97  ::memcpy(&msg.ch, data.GetBytes(sizeof(char)), sizeof(char));
98  ::memcpy(&msg.u8, data.GetBytes(sizeof(uint8_t)), sizeof(uint8_t));
99 }
100 
101 // ****************************************************************************
102 void WriteBasic(alchemy::benchmark::DataBuffer &data,
103  alchemy::benchmark::Basic &msg)
104 {
105  // Read the basic field data in.
106  ::memcpy(data.GetBytes(sizeof(int32_t)), &msg.i32, sizeof(int32_t));
107  ::memcpy(data.GetBytes(sizeof(uint32_t)),&msg.u32, sizeof(uint32_t));
108  ::memcpy(data.GetBytes(sizeof(int16_t)), &msg.i16, sizeof(int16_t));
109  ::memcpy(data.GetBytes(sizeof(uint16_t)),&msg.u16, sizeof(uint16_t));
110  ::memcpy(data.GetBytes(sizeof(char)), &msg.ch, sizeof(char));
111  ::memcpy(data.GetBytes(sizeof(uint8_t)), &msg.u8, sizeof(uint8_t));
112 }
113 
114 // ****************************************************************************
115 void BasicToNetwork(const alchemy::benchmark::Basic &host,
116  alchemy::benchmark::Basic &net)
117 {
118  // Convert the necessary terms to network byte order.
119  net.i32 = htonl(host.i32);
120  net.u32 = htonl(host.u32);
121  net.i16 = htons(host.i16);
122  net.u16 = htons(host.u16);
123  net.ch = host.ch;
124  net.u8 = host.u8;
125 }
126 
127 // ****************************************************************************
128 void ReadPacked(alchemy::benchmark::DataBuffer &data,
129  alchemy::benchmark::Packed &msg)
130 {
131  // Read the basic field data in.
132  ::memcpy(&msg.set_a, data.GetBytes(sizeof(int32_t)), sizeof(int32_t));
133  ::memcpy(&msg.set_b, data.GetBytes(sizeof(uint16_t)), sizeof(uint16_t));
134  ::memcpy(&msg.set_c, data.GetBytes(sizeof(uint8_t)), sizeof(uint8_t));
135 }
136 
137 // ****************************************************************************
138 void WritePacked( alchemy::benchmark::DataBuffer &data,
139  alchemy::benchmark::Packed &msg)
140 {
141  // Read the basic field data in.
142  ::memcpy(data.GetBytes(sizeof(uint32_t)),&msg.set_a, sizeof(uint32_t));
143  ::memcpy(data.GetBytes(sizeof(uint16_t)),&msg.set_b, sizeof(uint16_t));
144  ::memcpy(data.GetBytes(sizeof(uint8_t)), &msg.set_c, sizeof(uint8_t));
145 }
146 
147 // ****************************************************************************
148 void PackedToNetwork(const alchemy::benchmark::Packed &host,
149  alchemy::benchmark::Packed &net)
150 {
151  // Convert the necessary terms to network byte order.
152  net.set_a = htonl(host.set_a);
153  net.set_b = htons(host.set_b);
154  net.set_c = host.set_c;
155 }
156 
157 // ****************************************************************************
158 void ReadUnaligned( alchemy::benchmark::DataBuffer &data,
159  alchemy::benchmark::Unaligned &msg)
160 {
161  // Read the basic field data in.
162  ::memcpy(&msg.ch, data.GetBytes(sizeof(char )), sizeof(char ));
163  ::memcpy(&msg.u32_a, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
164  ::memcpy(&msg.u32_b, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
165  ::memcpy(&msg.u32_c, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
166  ::memcpy(&msg.i16_a, data.GetBytes(sizeof(int16_t )), sizeof(int16_t ));
167  ::memcpy(&msg.i16_b, data.GetBytes(sizeof(int16_t )), sizeof(int16_t ));
168  ::memcpy(&msg.i16_c, data.GetBytes(sizeof(int16_t )), sizeof(int16_t ));
169 }
170 
171 // ****************************************************************************
172 void WriteUnaligned(alchemy::benchmark::DataBuffer &data,
173  alchemy::benchmark::Unaligned &msg)
174 {
175  // Read the basic field data in.
176  ::memcpy(data.GetBytes(sizeof(char )), &msg.ch, sizeof(char ));
177  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.u32_a, sizeof(uint32_t));
178  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.u32_b, sizeof(uint32_t));
179  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.u32_c, sizeof(uint32_t));
180  ::memcpy(data.GetBytes(sizeof(int16_t )), &msg.i16_a, sizeof(int16_t ));
181  ::memcpy(data.GetBytes(sizeof(int16_t )), &msg.i16_b, sizeof(int16_t ));
182  ::memcpy(data.GetBytes(sizeof(int16_t )), &msg.i16_c, sizeof(int16_t ));
183 }
184 
185 // ****************************************************************************
186 void UnalignedToNetwork(const alchemy::benchmark::Unaligned &host,
187  alchemy::benchmark::Unaligned &net)
188 {
189  // Convert the necessary terms to network byte order.
190  net.ch = host.ch;
191  net.u32_a = htonl(host.u32_a);
192  net.u32_b = htonl(host.u32_b);
193  net.u32_c = htonl(host.u32_c);
194  net.i16_a = htons(host.i16_a);
195  net.i16_b = htons(host.i16_b);
196  net.i16_c = htons(host.i16_c);
197 }
198 
199 // ****************************************************************************
200 void ReadComplex( alchemy::benchmark::DataBuffer &data,
201  alchemy::benchmark::Complex &msg)
202 {
203  // Read the basic field data in.
204  ::memcpy(&msg.seq, data.GetBytes(sizeof(uint32_t)), sizeof(uint32_t));
205  for (size_t i = 0; i < alchemy::benchmark::k_complex_basic_count; ++i)
206  {
207  ReadBasic(data, msg.basic[i]);
208  }
209 
210  ReadPacked(data, msg.bits);
211 
212  ReadUnaligned(data, msg.unaligned);
213 }
214 
215 // ****************************************************************************
216 void WriteComplex(alchemy::benchmark::DataBuffer &data,
217  alchemy::benchmark::Complex &msg)
218 {
219  // Read the basic field data in.
220  ::memcpy(data.GetBytes(sizeof(uint32_t)), &msg.seq, sizeof(uint32_t));
221 
222  for (size_t i = 0; i < alchemy::benchmark::k_complex_basic_count; ++i)
223  {
224  WriteBasic(data, msg.basic[i]);
225  }
226 
227  WritePacked(data, msg.bits);
228 
229  WriteUnaligned(data, msg.unaligned);
230 }
231 
232 // ****************************************************************************
233 void ComplexToNetwork(const alchemy::benchmark::Complex &host,
234  alchemy::benchmark::Complex &net)
235 {
236  // Convert the necessary terms to network byte order.
237  net.seq = htonl(host.seq);
238 
239  for (size_t i = 0; i < alchemy::benchmark::k_complex_basic_count; ++i)
240  {
241  BasicToNetwork(host.basic[i], net.basic[i]);
242  }
243 
244  PackedToNetwork(host.bits, net.bits);
245 
246  UnalignedToNetwork(host.unaligned, net.unaligned);
247 }
248 
249 
250 // ****************************************************************************
251 void ReadArray (alchemy::benchmark::DataBuffer &data,
252  alchemy::benchmark::Array &msg)
253 {
254  for (size_t index = 0; index < alchemy::benchmark::k_array_test_count; ++index)
255  {
256  ::memcpy(&msg.items[index], data.GetBytes(sizeof(int32_t)), sizeof(int32_t));
257  }
258 }
259 
260 // ****************************************************************************
261 void WriteArray ( alchemy::benchmark::DataBuffer &data,
262  alchemy::benchmark::Array &msg)
263 {
264  for (size_t index = 0; index < alchemy::benchmark::k_array_test_count; ++index)
265  {
266  ::memcpy(data.GetBytes(sizeof(uint32_t)),&msg.items[index], sizeof(uint32_t));
267  }
268 }
269 
270 // ****************************************************************************
271 void ArrayToNetwork (const alchemy::benchmark::Array &host,
272  alchemy::benchmark::Array &net)
273 {
274  // Convert the necessary terms to network byte order.
275  for (size_t index = 0; index < alchemy::benchmark::k_array_test_count; ++index)
276  {
277  net.items[index] = htonl(host.items[index]);
278  }
279 }
280 
281 
282 
283 namespace alchemy
284 {
285 namespace benchmark
286 {
287 
288 // ****************************************************************************
289 void UsingMemcpy::test_no_conversion( DataBuffer &data,
290  DataBuffer &out)
291 {
292  using alchemy::benchmark::DataBuffer;
293  using alchemy::benchmark::NoConversion;
294 
296  size_t count = data.Size() / len;
297 
298  cout << "no_conversion size: " << len << "\t\tcount: " << count << endl;
299  for (size_t index = 0; index < count; ++index)
300  {
301  alchemy::benchmark::NoConversion host;
302  ReadNoConversion(data, host);
303 
304  alchemy::benchmark::NoConversion net;
305  NoConversionToNetwork(host, net);
306 
307  WriteNoConversion(out, net);
308  }
309 }
310 
311 // ****************************************************************************
312 void UsingMemcpy::test_basic( DataBuffer &data,
313  DataBuffer &out)
314 {
315  using alchemy::benchmark::DataBuffer;
316  using alchemy::benchmark::Basic;
317 
319  size_t count = data.Size() / len;
320 
321  cout << " basic size: " << len << "\t\tcount: " << count << endl;
322  for (size_t index = 0; index < count; ++index)
323  {
324  Basic host;
325  ReadBasic(data, host);
326 
327  Basic net;
328  BasicToNetwork(host, net);
329 
330  WriteBasic(out, net);
331  }
332 }
333 
334 // ****************************************************************************
335 void UsingMemcpy::test_packed_bits(DataBuffer &data,
336  DataBuffer &out)
337 {
338  using alchemy::benchmark::DataBuffer;
339  using alchemy::benchmark::Packed;
340 
342  size_t count = data.Size() / len;
343 
344  cout << " packed size: " << len << "\t\tcount: " << count << endl;
345  for (size_t index = 0; index < count; ++index)
346  {
347  Packed host;
348  ReadPacked(data, host);
349 
350  Packed net;
351  PackedToNetwork(host, net);
352 
353  WritePacked(out, net);
354  }
355 
356 }
357 
358 // ****************************************************************************
359 void UsingMemcpy::test_unaligned( DataBuffer &data,
360  DataBuffer &out)
361 {
362  using alchemy::benchmark::DataBuffer;
363  using alchemy::benchmark::Unaligned;
364 
366  size_t count = data.Size() / len;
367 
368  cout << " unaligned size: " << len << "\t\tcount: " << count << endl;
369  for (size_t index = 0; index < count; ++index)
370  {
371  Unaligned host;
372  ReadUnaligned(data, host);
373 
374  Unaligned net;
375  UnalignedToNetwork(host, net);
376 
377  WriteUnaligned(out, net);
378  }
379 }
380 
381 // ****************************************************************************
382 void UsingMemcpy::test_complex(DataBuffer &data,
383  DataBuffer &out)
384 {
385  using alchemy::benchmark::DataBuffer;
386  using alchemy::benchmark::Complex;
387 
389  size_t count = data.Size() / len;
390  cout << " complex size: " << len << "\t\tcount: " << count << endl;
391  for (size_t index = 0; index < count; ++index)
392  {
393  Complex host;
394  ReadComplex(data, host);
395 
396  Complex net;
397  ComplexToNetwork(host, net);
398 
399  WriteComplex(out, net);
400  }
401 }
402 
403 // ****************************************************************************
404 void UsingMemcpy::test_array (DataBuffer &data,
405  DataBuffer &out)
406 {
407  using alchemy::benchmark::DataBuffer;
408  using alchemy::benchmark::Array;
409 
411  size_t count = data.Size() / len;
412  cout << " array size: " << len << "\tcount: " << count << endl;
413  for (size_t index = 0; index < count; ++index)
414  {
415  Array host;
416  ReadArray(data, host);
417 
418  Array net;
419  ArrayToNetwork(host, net);
420 
421  WriteArray(out, net);
422  }
423 
424 }
425 
426 } // benchmark
427 } // alchemy
428