Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Diagnostics;
- using System.Runtime.CompilerServices;
- class Program
- {
- static void Main(string[] args)
- {
- while (true)
- {
- // Uncomment one of the below depending on which one is being tested.
- uint value = 0xdeadbeef;
- // ushort value = 0xbeef;
- // ulong value = 0xdeadbeef12345678;
- RunTest(ref value);
- }
- }
- [MethodImpl(MethodImplOptions.NoInlining)]
- public static void RunTest(ref uint /* or ushort or ulong depending on test */ value)
- {
- const int NUM_ITERS = 1_000_000_000;
- Stopwatch sw = Stopwatch.StartNew();
- for (int j = 0; j < NUM_ITERS; j++)
- {
- value = ReverseEndiannessV1(value); // or V2 or V3 depending on test
- }
- Console.WriteLine(sw.ElapsedMilliseconds);
- }
- // The V1 methods are based on the full framework's IPAddress.HostToNetworkOrder implementations.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ushort ReverseEndiannessV1(ushort value)
- {
- return (ushort)((((int)value & 0xFF) << 8) | (int)((value >> 8) & 0xFF));
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static uint ReverseEndiannessV1(uint value)
- {
- return (((uint)ReverseEndiannessV1((ushort)value) & 0xFFFF) << 16)
- | ((uint)ReverseEndiannessV1((ushort)(value >> 16)) & 0xFFFF);
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ulong ReverseEndiannessV1(ulong value)
- {
- return (((ulong)ReverseEndiannessV1((uint)value) & 0xFFFFFFFF) << 32)
- | ((ulong)ReverseEndiannessV1((uint)(value >> 32)) & 0xFFFFFFFF);
- }
- // The V2 methods are based on the core framework's BinaryPrimitives.ReverseEndianness implementations.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ushort ReverseEndiannessV2(ushort value)
- {
- return (ushort)((value & 0x00FFU) << 8 | (value & 0xFF00U) >> 8);
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static uint ReverseEndiannessV2(uint value)
- {
- value = (value << 16) | (value >> 16);
- value = (value & 0x00FF00FF) << 8 | (value & 0xFF00FF00) >> 8;
- return value;
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ulong ReverseEndiannessV2(ulong value)
- {
- value = (value << 32) | (value >> 32);
- value = (value & 0x0000FFFF0000FFFF) << 16 | (value & 0xFFFF0000FFFF0000) >> 16;
- value = (value & 0x00FF00FF00FF00FF) << 8 | (value & 0xFF00FF00FF00FF00) >> 8;
- return value;
- }
- // The V3 methods are the new more optimized proposals.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ushort ReverseEndiannessV3(ushort value)
- {
- // Don't need to AND with 0xFF00 or 0x00FF since the final
- // cast back to ushort will clear out all bits above [ 15 .. 00 ].
- // This is normally implemented via "movzx eax, ax" on the return.
- // Alternatively, the compiler could elide the movzx instruction
- // entirely if it knows the caller is only going to access "ax"
- // instead of "eax" / "rax" when the function returns.
- return (ushort)((value >> 8) + (value << 8));
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static uint ReverseEndiannessV3(uint value)
- {
- // This takes advantage of the fact that the JIT can detect
- // ROL32 / ROR32 patterns and output the correct intrinsic.
- //
- // Input: value = [ ww xx yy zz ]
- //
- // First line generates : [ ww xx yy zz ]
- // & [ 00 FF 00 FF ]
- // = [ 00 xx 00 zz ]
- // ROR32(8) = [ zz 00 xx 00 ]
- //
- // Second line generates: [ ww xx yy zz ]
- // & [ FF 00 FF 00 ]
- // = [ ww 00 yy 00 ]
- // ROL32(8) = [ 00 yy 00 ww ]
- //
- // (sum) = [ zz yy xx ww ]
- //
- // Testing shows that throughput increases if the AND
- // is performed before the ROL / ROR.
- uint mask_xx_zz = (value & 0x00FF00FFU);
- uint mask_ww_yy = (value & 0xFF00FF00U);
- return ((mask_xx_zz >> 8) | (mask_xx_zz << 24))
- + ((mask_ww_yy << 8) | (mask_ww_yy >> 24));
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ulong ReverseEndiannessV3(ulong value)
- {
- // Operations on 32-bit values have higher throughput than
- // operations on 64-bit values, so decompose.
- return ((ulong)ReverseEndiannessV3((uint)value) << 32)
- + ReverseEndiannessV3((uint)(value >> 32));
- }
- }
Add Comment
Please, Sign In to add comment