Guest User

Untitled

a guest
Jan 22nd, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.72 KB | None | 0 0
  1. using System;
  2. using System.Diagnostics;
  3. using System.Runtime.CompilerServices;
  4.  
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. while (true)
  10. {
  11. // Uncomment one of the below depending on which one is being tested.
  12. uint value = 0xdeadbeef;
  13. // ushort value = 0xbeef;
  14. // ulong value = 0xdeadbeef12345678;
  15. RunTest(ref value);
  16. }
  17. }
  18.  
  19. [MethodImpl(MethodImplOptions.NoInlining)]
  20. public static void RunTest(ref uint /* or ushort or ulong depending on test */ value)
  21. {
  22. const int NUM_ITERS = 1_000_000_000;
  23.  
  24. Stopwatch sw = Stopwatch.StartNew();
  25. for (int j = 0; j < NUM_ITERS; j++)
  26. {
  27. value = ReverseEndiannessV1(value); // or V2 or V3 depending on test
  28. }
  29. Console.WriteLine(sw.ElapsedMilliseconds);
  30. }
  31.  
  32. // The V1 methods are based on the full framework's IPAddress.HostToNetworkOrder implementations.
  33.  
  34. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  35. public static ushort ReverseEndiannessV1(ushort value)
  36. {
  37. return (ushort)((((int)value & 0xFF) << 8) | (int)((value >> 8) & 0xFF));
  38. }
  39.  
  40. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  41. public static uint ReverseEndiannessV1(uint value)
  42. {
  43. return (((uint)ReverseEndiannessV1((ushort)value) & 0xFFFF) << 16)
  44. | ((uint)ReverseEndiannessV1((ushort)(value >> 16)) & 0xFFFF);
  45. }
  46.  
  47. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  48. public static ulong ReverseEndiannessV1(ulong value)
  49. {
  50. return (((ulong)ReverseEndiannessV1((uint)value) & 0xFFFFFFFF) << 32)
  51. | ((ulong)ReverseEndiannessV1((uint)(value >> 32)) & 0xFFFFFFFF);
  52. }
  53.  
  54. // The V2 methods are based on the core framework's BinaryPrimitives.ReverseEndianness implementations.
  55.  
  56. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  57. public static ushort ReverseEndiannessV2(ushort value)
  58. {
  59. return (ushort)((value & 0x00FFU) << 8 | (value & 0xFF00U) >> 8);
  60. }
  61.  
  62. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  63. public static uint ReverseEndiannessV2(uint value)
  64. {
  65. value = (value << 16) | (value >> 16);
  66. value = (value & 0x00FF00FF) << 8 | (value & 0xFF00FF00) >> 8;
  67. return value;
  68. }
  69.  
  70. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  71. public static ulong ReverseEndiannessV2(ulong value)
  72. {
  73. value = (value << 32) | (value >> 32);
  74. value = (value & 0x0000FFFF0000FFFF) << 16 | (value & 0xFFFF0000FFFF0000) >> 16;
  75. value = (value & 0x00FF00FF00FF00FF) << 8 | (value & 0xFF00FF00FF00FF00) >> 8;
  76. return value;
  77. }
  78.  
  79. // The V3 methods are the new more optimized proposals.
  80.  
  81. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  82. public static ushort ReverseEndiannessV3(ushort value)
  83. {
  84. // Don't need to AND with 0xFF00 or 0x00FF since the final
  85. // cast back to ushort will clear out all bits above [ 15 .. 00 ].
  86. // This is normally implemented via "movzx eax, ax" on the return.
  87. // Alternatively, the compiler could elide the movzx instruction
  88. // entirely if it knows the caller is only going to access "ax"
  89. // instead of "eax" / "rax" when the function returns.
  90.  
  91. return (ushort)((value >> 8) + (value << 8));
  92. }
  93.  
  94. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  95. public static uint ReverseEndiannessV3(uint value)
  96. {
  97. // This takes advantage of the fact that the JIT can detect
  98. // ROL32 / ROR32 patterns and output the correct intrinsic.
  99. //
  100. // Input: value = [ ww xx yy zz ]
  101. //
  102. // First line generates : [ ww xx yy zz ]
  103. // & [ 00 FF 00 FF ]
  104. // = [ 00 xx 00 zz ]
  105. // ROR32(8) = [ zz 00 xx 00 ]
  106. //
  107. // Second line generates: [ ww xx yy zz ]
  108. // & [ FF 00 FF 00 ]
  109. // = [ ww 00 yy 00 ]
  110. // ROL32(8) = [ 00 yy 00 ww ]
  111. //
  112. // (sum) = [ zz yy xx ww ]
  113. //
  114. // Testing shows that throughput increases if the AND
  115. // is performed before the ROL / ROR.
  116.  
  117. uint mask_xx_zz = (value & 0x00FF00FFU);
  118. uint mask_ww_yy = (value & 0xFF00FF00U);
  119. return ((mask_xx_zz >> 8) | (mask_xx_zz << 24))
  120. + ((mask_ww_yy << 8) | (mask_ww_yy >> 24));
  121. }
  122.  
  123. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  124. public static ulong ReverseEndiannessV3(ulong value)
  125. {
  126. // Operations on 32-bit values have higher throughput than
  127. // operations on 64-bit values, so decompose.
  128.  
  129. return ((ulong)ReverseEndiannessV3((uint)value) << 32)
  130. + ReverseEndiannessV3((uint)(value >> 32));
  131. }
  132. }
Add Comment
Please, Sign In to add comment