main.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file main.cpp
  15. * @author Gav Wood <i@gavwood.com>
  16. * @date 2014
  17. * RLP tool.
  18. */
  19. #include <clocale>
  20. #include <fstream>
  21. #include <iostream>
  22. #include <boost/algorithm/string.hpp>
  23. #include <boost/filesystem.hpp>
  24. #include <json_spirit/JsonSpiritHeaders.h>
  25. #include <libdevcore/CommonIO.h>
  26. #include <libdevcore/RLP.h>
  27. #include <libdevcore/SHA3.h>
  28. #include <libdevcore/MemoryDB.h>
  29. #include <libdevcore/TrieDB.h>
  30. #include <libdevcrypto/Common.h>
  31. #include <libdevcrypto/CryptoPP.h>
  32. using namespace std;
  33. using namespace dev;
  34. namespace js = json_spirit;
  35. void help()
  36. {
  37. cout
  38. << "Usage bench <mode> [OPTIONS]" << endl
  39. << "Modes:" << endl
  40. << " trie Trie benchmarks." << endl
  41. << endl
  42. << "General options:" << endl
  43. << " -h,--help Print this help message and exit." << endl
  44. << " -V,--version Show the version and exit." << endl
  45. ;
  46. exit(0);
  47. }
  48. void version()
  49. {
  50. cout << "bench part of dev suite version " << dev::Version << endl;
  51. exit(0);
  52. }
  53. /*
  54. The equivalent of setlocale(LC_ALL, “C”) is called before any user code is run.
  55. If the user has an invalid environment setting then it is possible for the call
  56. to set locale to fail, so there are only two possible actions, the first is to
  57. throw a runtime exception and cause the program to quit (default behaviour),
  58. or the second is to modify the environment to something sensible (least
  59. surprising behaviour).
  60. The follow code produces the least surprising behaviour. It will use the user
  61. specified default locale if it is valid, and if not then it will modify the
  62. environment the process is running in to use a sensible default. This also means
  63. that users do not need to install language packs for their OS.
  64. */
  65. void setDefaultOrCLocale()
  66. {
  67. #if __unix__
  68. if (!std::setlocale(LC_ALL, ""))
  69. {
  70. setenv("LC_ALL", "C", 1);
  71. }
  72. #endif
  73. }
  74. enum class Mode {
  75. Trie,
  76. SHA3
  77. };
  78. enum class Alphabet
  79. {
  80. Low, Mid, All
  81. };
  82. class StandardMap
  83. {
  84. public:
  85. StandardMap() = default;
  86. StandardMap(Alphabet _alphabet, unsigned _count, unsigned _minKey, unsigned _diffKey): m_alphabet(_alphabet), m_count(_count), m_minKey(_minKey), m_diffKey(_diffKey) {}
  87. vector<pair<bytes, bytes>> make() const
  88. {
  89. string const c_low = "abcdef";
  90. string const c_mid = "@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_";
  91. h256 seed;
  92. vector<pair<bytes, bytes>> input;
  93. for (unsigned j = 0; j < m_count; ++j)
  94. {
  95. bytes k = m_alphabet == Alphabet::All ? randomBytes(m_minKey, m_diffKey, &seed) : randomWord(m_alphabet == Alphabet::Low ? c_low : c_mid, m_minKey, m_diffKey, &seed);
  96. bytes v = randomValue(&seed);
  97. input.push_back(make_pair(k, v));
  98. }
  99. return input;
  100. }
  101. private:
  102. Alphabet m_alphabet;
  103. unsigned m_count;
  104. unsigned m_minKey;
  105. unsigned m_diffKey;
  106. static bytes randomWord(bytesConstRef _alphabet, unsigned _min, unsigned _diff, h256* _seed)
  107. {
  108. assert(_min + _diff < 33);
  109. *_seed = sha3(*_seed);
  110. unsigned l = _min + (*_seed)[31] % (_diff + 1);
  111. bytes ret;
  112. for (unsigned i = 0; i < l; ++i)
  113. ret.push_back(_alphabet[(*_seed)[i] % _alphabet.size()]);
  114. return ret;
  115. }
  116. static bytes randomBytes(unsigned _min, unsigned _diff, h256* _seed)
  117. {
  118. assert(_min + _diff < 33);
  119. *_seed = sha3(*_seed);
  120. unsigned l = _min + (*_seed)[31] % (_diff + 1);
  121. return _seed->ref().cropped(0, l).toBytes();
  122. }
  123. static bytes randomValue(h256* _seed)
  124. {
  125. *_seed = sha3(*_seed);
  126. if ((*_seed)[0] % 2)
  127. return bytes(1, (*_seed)[31]);
  128. else
  129. return _seed->asBytes();
  130. }
  131. };
  132. int main(int argc, char** argv)
  133. {
  134. setDefaultOrCLocale();
  135. Mode mode = Mode::Trie;
  136. for (int i = 1; i < argc; ++i)
  137. {
  138. string arg = argv[i];
  139. if (arg == "-h" || arg == "--help")
  140. help();
  141. else if (arg == "trie")
  142. mode = Mode::Trie;
  143. else if (arg == "sha3")
  144. mode = Mode::SHA3;
  145. else if (arg == "-V" || arg == "--version")
  146. version();
  147. }
  148. if (mode == Mode::Trie)
  149. {
  150. unordered_map<string, StandardMap> maps =
  151. {
  152. { "six-low", StandardMap(Alphabet::Low, 1000, 6, 0) },
  153. { "six-mid", StandardMap(Alphabet::Mid, 1000, 6, 0) },
  154. { "six-all", StandardMap(Alphabet::All, 1000, 6, 0) },
  155. { "mix-mid", StandardMap(Alphabet::Mid, 1000, 1, 5) },
  156. };
  157. unsigned trials = 50;
  158. for (auto const& sm: maps)
  159. {
  160. MemoryDB mdb;
  161. GenericTrieDB<MemoryDB> t(&mdb);
  162. t.init();
  163. auto map = sm.second.make();
  164. Timer timer;
  165. for (unsigned i = 0; i < trials; ++i)
  166. for (auto const& i: map)
  167. t.insert(&i.first, &i.second);
  168. auto e = timer.elapsed() / trials;
  169. cout << sm.first << ": " << e * 1000000 << " us, root=" << t.root() << endl;
  170. }
  171. }
  172. else if (mode == Mode::SHA3)
  173. {
  174. unsigned trials = 50;
  175. Timer t;
  176. for (unsigned trial = 0; trial < trials; ++trial)
  177. {
  178. h256 s;
  179. for (unsigned i = 0; i < 1000; ++i)
  180. s = sha3(s);
  181. }
  182. cout << "sha3 x 1000: " << t.elapsed() / trials * 1000000 << "us " << endl;
  183. }
  184. return 0;
  185. }