tags:

views:

438

answers:

3

There's got to be a faster and better way to swap bytes of 16bit words then this. Does anyone have an idea?

     public static void Swap(byte[] data)
 {
  for (int i = 0; i < data.Length; i += 2)
  {
   byte b = data[i];
   data[i] = data[i + 1];
   data[i + 1] = b;
  }
 }
+1  A: 

Well, you could use the XOR swapping trick, to avoid an intermediate byte. It won't be any faster, though, and I wouldn't be surprised if the IL is exactly the same.

for (int i = 0; i < data.Length; i += 2)
{
    data[i] ^= data[i + 1];
    data[i + 1] ^= data[i];
    data[i] ^= data[i + 1];
}
Michael Petrotta
Good one. But this is somewhat more confusing to read. And wikipedia claims "On modern (desktop) CPUs, the XOR technique is considerably slower than using a temporary variable to do swapping." Oh well. Thanks for the sexy solution.
initialZero
Yeah, I think all we can say about it is that it's neat. I just benchmarked it, and got results identical to your solution. So, one of the forms is likely optimized to the other.
Michael Petrotta
+3  A: 

This way appears to be slightly faster than the method in the original question:

private static byte[] _temp = new byte[0];
public static void Swap(byte[] data)
{
    if (data.Length > _temp.Length)
    {
        _temp = new byte[data.Length];
    }
    Buffer.BlockCopy(data, 1, _temp, 0, data.Length - 1);
    for (int i = 0; i < data.Length; i += 2)
    {
        _temp[i + 1] = data[i];
    }
    Buffer.BlockCopy(_temp, 0, data, 0, data.Length);
}

My benchmarking assumed that the method is called repeatedly, so that the resizing of the _temp array isn't a factor. This method relies on the fact that half of the byte-swapping can be done with the initial Buffer.BlockCopy(...) call (with the source position offset by 1).

Please benchmark this yourselves, in case I've completely lost my mind. In my tests, this method takes approximately 70% as long as the original method (which I modified to declare the byte b outside of the loop).

MusiGenesis
Uberhacker award! I would expect a large resize of temp to be more expensive than an in place swap. And it's sorta a memory-leak just having temp sit around.
initialZero
@initialZero: in my benchmark, I initially sized it to the same size as my test array, so there was no cost there. Temp variables like this in general buy speed at the expense of memory, which may or may not be a good decision.
MusiGenesis
@MusiGenesis you could always set temp = null at the end of swap to fix the leak. It's definitely a cool solution. Thanks.
initialZero
A: 

you may like John Skeet's approach - MiscUtil\Conversion

Nisus