/tests/neo.UnitTests/UT_UIntBenchmarks.cs

https://github.com/neo-project/neo · C# · 330 lines · 281 code · 41 blank · 8 comment · 35 complexity · 1998d251b4f42ed253d1b301ebdbfdb7 MD5 · raw file

  1. using FluentAssertions;
  2. using Microsoft.VisualStudio.TestTools.UnitTesting;
  3. using System;
  4. using System.Diagnostics;
  5. namespace Neo.UnitTests
  6. {
  7. [TestClass]
  8. public class UT_UIntBenchmarks
  9. {
  10. private const int MAX_TESTS = 1000;
  11. byte[][] base_32_1;
  12. byte[][] base_32_2;
  13. byte[][] base_20_1;
  14. byte[][] base_20_2;
  15. private Random random;
  16. [TestInitialize]
  17. public void TestSetup()
  18. {
  19. int SEED = 123456789;
  20. random = new Random(SEED);
  21. base_32_1 = new byte[MAX_TESTS][];
  22. base_32_2 = new byte[MAX_TESTS][];
  23. base_20_1 = new byte[MAX_TESTS][];
  24. base_20_2 = new byte[MAX_TESTS][];
  25. for (var i = 0; i < MAX_TESTS; i++)
  26. {
  27. base_32_1[i] = RandomBytes(32);
  28. base_20_1[i] = RandomBytes(20);
  29. if (i % 2 == 0)
  30. {
  31. base_32_2[i] = RandomBytes(32);
  32. base_20_2[i] = RandomBytes(20);
  33. }
  34. else
  35. {
  36. base_32_2[i] = new byte[32];
  37. Buffer.BlockCopy(base_32_1[i], 0, base_32_2[i], 0, 32);
  38. base_20_2[i] = new byte[20];
  39. Buffer.BlockCopy(base_20_1[i], 0, base_20_2[i], 0, 20);
  40. }
  41. }
  42. }
  43. [TestMethod]
  44. public void Test_UInt160_Parse()
  45. {
  46. string uint160strbig = "0x0001020304050607080900010203040506070809";
  47. UInt160 num1 = UInt160.Parse(uint160strbig);
  48. num1.ToString().Should().Be("0x0001020304050607080900010203040506070809");
  49. string uint160strbig2 = "0X0001020304050607080900010203040506070809";
  50. UInt160 num2 = UInt160.Parse(uint160strbig2);
  51. num2.ToString().Should().Be("0x0001020304050607080900010203040506070809");
  52. }
  53. private byte[] RandomBytes(int count)
  54. {
  55. byte[] randomBytes = new byte[count];
  56. random.NextBytes(randomBytes);
  57. return randomBytes;
  58. }
  59. public delegate object BenchmarkMethod();
  60. public (TimeSpan, object) Benchmark(BenchmarkMethod method)
  61. {
  62. Stopwatch sw0 = new Stopwatch();
  63. sw0.Start();
  64. var result = method();
  65. sw0.Stop();
  66. TimeSpan elapsed = sw0.Elapsed;
  67. Console.WriteLine($"Elapsed={elapsed} Sum={result}");
  68. return (elapsed, result);
  69. }
  70. [TestMethod]
  71. public void Benchmark_CompareTo_UInt256()
  72. {
  73. // testing "official UInt256 version"
  74. UInt256[] uut_32_1 = new UInt256[MAX_TESTS];
  75. UInt256[] uut_32_2 = new UInt256[MAX_TESTS];
  76. for (var i = 0; i < MAX_TESTS; i++)
  77. {
  78. uut_32_1[i] = new UInt256(base_32_1[i]);
  79. uut_32_2[i] = new UInt256(base_32_2[i]);
  80. }
  81. var checksum0 = Benchmark(() =>
  82. {
  83. var checksum = 0;
  84. for (var i = 0; i < MAX_TESTS; i++)
  85. {
  86. checksum += uut_32_1[i].CompareTo(uut_32_2[i]);
  87. }
  88. return checksum;
  89. }).Item2;
  90. var checksum1 = Benchmark(() =>
  91. {
  92. var checksum = 0;
  93. for (var i = 0; i < MAX_TESTS; i++)
  94. {
  95. checksum += code1_UInt256CompareTo(base_32_1[i], base_32_2[i]);
  96. }
  97. return checksum;
  98. }).Item2;
  99. var checksum2 = Benchmark(() =>
  100. {
  101. var checksum = 0;
  102. for (var i = 0; i < MAX_TESTS; i++)
  103. {
  104. checksum += code2_UInt256CompareTo(base_32_1[i], base_32_2[i]);
  105. }
  106. return checksum;
  107. }).Item2;
  108. var checksum3 = Benchmark(() =>
  109. {
  110. var checksum = 0;
  111. for (var i = 0; i < MAX_TESTS; i++)
  112. {
  113. checksum += code3_UInt256CompareTo(base_32_1[i], base_32_2[i]);
  114. }
  115. return checksum;
  116. }).Item2;
  117. checksum0.Should().Be(checksum1);
  118. checksum0.Should().Be(checksum2);
  119. checksum0.Should().Be(checksum3);
  120. }
  121. [TestMethod]
  122. public void Benchmark_CompareTo_UInt160()
  123. {
  124. // testing "official UInt160 version"
  125. UInt160[] uut_20_1 = new UInt160[MAX_TESTS];
  126. UInt160[] uut_20_2 = new UInt160[MAX_TESTS];
  127. for (var i = 0; i < MAX_TESTS; i++)
  128. {
  129. uut_20_1[i] = new UInt160(base_20_1[i]);
  130. uut_20_2[i] = new UInt160(base_20_2[i]);
  131. }
  132. var checksum0 = Benchmark(() =>
  133. {
  134. var checksum = 0;
  135. for (var i = 0; i < MAX_TESTS; i++)
  136. {
  137. checksum += uut_20_1[i].CompareTo(uut_20_2[i]);
  138. }
  139. return checksum;
  140. }).Item2;
  141. var checksum1 = Benchmark(() =>
  142. {
  143. var checksum = 0;
  144. for (var i = 0; i < MAX_TESTS; i++)
  145. {
  146. checksum += code1_UInt160CompareTo(base_20_1[i], base_20_2[i]);
  147. }
  148. return checksum;
  149. }).Item2;
  150. var checksum2 = Benchmark(() =>
  151. {
  152. var checksum = 0;
  153. for (var i = 0; i < MAX_TESTS; i++)
  154. {
  155. checksum += code2_UInt160CompareTo(base_20_1[i], base_20_2[i]);
  156. }
  157. return checksum;
  158. }).Item2;
  159. var checksum3 = Benchmark(() =>
  160. {
  161. var checksum = 0;
  162. for (var i = 0; i < MAX_TESTS; i++)
  163. {
  164. checksum += code3_UInt160CompareTo(base_20_1[i], base_20_2[i]);
  165. }
  166. return checksum;
  167. }).Item2;
  168. checksum0.Should().Be(checksum1);
  169. checksum0.Should().Be(checksum2);
  170. checksum0.Should().Be(checksum3);
  171. }
  172. [TestMethod]
  173. public void Benchmark_UInt_IsCorrect_Self_CompareTo()
  174. {
  175. for (var i = 0; i < MAX_TESTS; i++)
  176. {
  177. code1_UInt160CompareTo(base_20_1[i], base_20_1[i]).Should().Be(0);
  178. code2_UInt160CompareTo(base_20_1[i], base_20_1[i]).Should().Be(0);
  179. code3_UInt160CompareTo(base_20_1[i], base_20_1[i]).Should().Be(0);
  180. code1_UInt256CompareTo(base_32_1[i], base_32_1[i]).Should().Be(0);
  181. code2_UInt256CompareTo(base_32_1[i], base_32_1[i]).Should().Be(0);
  182. code3_UInt256CompareTo(base_32_1[i], base_32_1[i]).Should().Be(0);
  183. }
  184. }
  185. private int code1_UInt256CompareTo(byte[] b1, byte[] b2)
  186. {
  187. byte[] x = b1;
  188. byte[] y = b2;
  189. for (int i = x.Length - 1; i >= 0; i--)
  190. {
  191. if (x[i] > y[i])
  192. return 1;
  193. if (x[i] < y[i])
  194. return -1;
  195. }
  196. return 0;
  197. }
  198. private unsafe int code2_UInt256CompareTo(byte[] b1, byte[] b2)
  199. {
  200. fixed (byte* px = b1, py = b2)
  201. {
  202. uint* lpx = (uint*)px;
  203. uint* lpy = (uint*)py;
  204. for (int i = 256 / 32 - 1; i >= 0; i--)
  205. {
  206. if (lpx[i] > lpy[i])
  207. return 1;
  208. if (lpx[i] < lpy[i])
  209. return -1;
  210. }
  211. }
  212. return 0;
  213. }
  214. private unsafe int code3_UInt256CompareTo(byte[] b1, byte[] b2)
  215. {
  216. fixed (byte* px = b1, py = b2)
  217. {
  218. ulong* lpx = (ulong*)px;
  219. ulong* lpy = (ulong*)py;
  220. for (int i = 256 / 64 - 1; i >= 0; i--)
  221. {
  222. if (lpx[i] > lpy[i])
  223. return 1;
  224. if (lpx[i] < lpy[i])
  225. return -1;
  226. }
  227. }
  228. return 0;
  229. }
  230. private int code1_UInt160CompareTo(byte[] b1, byte[] b2)
  231. {
  232. byte[] x = b1;
  233. byte[] y = b2;
  234. for (int i = x.Length - 1; i >= 0; i--)
  235. {
  236. if (x[i] > y[i])
  237. return 1;
  238. if (x[i] < y[i])
  239. return -1;
  240. }
  241. return 0;
  242. }
  243. private unsafe int code2_UInt160CompareTo(byte[] b1, byte[] b2)
  244. {
  245. fixed (byte* px = b1, py = b2)
  246. {
  247. uint* lpx = (uint*)px;
  248. uint* lpy = (uint*)py;
  249. for (int i = 160 / 32 - 1; i >= 0; i--)
  250. {
  251. if (lpx[i] > lpy[i])
  252. return 1;
  253. if (lpx[i] < lpy[i])
  254. return -1;
  255. }
  256. }
  257. return 0;
  258. }
  259. private unsafe int code3_UInt160CompareTo(byte[] b1, byte[] b2)
  260. {
  261. // LSB -----------------> MSB
  262. // --------------------------
  263. // | 8B | 8B | 4B |
  264. // --------------------------
  265. // 0l 1l 4i
  266. // --------------------------
  267. fixed (byte* px = b1, py = b2)
  268. {
  269. uint* ipx = (uint*)px;
  270. uint* ipy = (uint*)py;
  271. if (ipx[4] > ipy[4])
  272. return 1;
  273. if (ipx[4] < ipy[4])
  274. return -1;
  275. ulong* lpx = (ulong*)px;
  276. ulong* lpy = (ulong*)py;
  277. if (lpx[1] > lpy[1])
  278. return 1;
  279. if (lpx[1] < lpy[1])
  280. return -1;
  281. if (lpx[0] > lpy[0])
  282. return 1;
  283. if (lpx[0] < lpy[0])
  284. return -1;
  285. }
  286. return 0;
  287. }
  288. }
  289. }