Следующий метод, в моем тесте, почти в 3 раза быстрее, чем принятый ответ. (Всегда быстрее для более чем 3 символов или шести байтов, немного медленнее для менее или равного трех символов или шести байтов.) ( Обратите внимание, что принятый ответ может считываться / записываться за пределами массива. )
(Обновление При наличии указателя нет необходимости вызывать свойство для получения длины. Использование этого указателя немного быстрее, но требует либо проверки во время выполнения, либо, как в следующем примере, конфигурации проекта для построения для каждой платформы Определите X86 и X64 для каждой конфигурации.)
static unsafe void SwapV2(byte[] source)
{
fixed (byte* psource = source)
{
#if X86
var length = *((uint*)(psource - 4)) & 0xFFFFFFFEU;
#elif X64
var length = *((uint*)(psource - 8)) & 0xFFFFFFFEU;
#else
var length = (source.Length & 0xFFFFFFFE);
#endif
while (length > 7)
{
length -= 8;
ulong* pulong = (ulong*)(psource + length);
*pulong = ( ((*pulong >> 8) & 0x00FF00FF00FF00FFUL)
| ((*pulong << 8) & 0xFF00FF00FF00FF00UL));
}
if(length > 3)
{
length -= 4;
uint* puint = (uint*)(psource + length);
*puint = ( ((*puint >> 8) & 0x00FF00FFU)
| ((*puint << 8) & 0xFF00FF00U));
}
if(length > 1)
{
ushort* pushort = (ushort*)psource;
*pushort = (ushort) ( (*pushort >> 8)
| (*pushort << 8));
}
}
}
Пять тестов с 300.000 раз 8192 байта
- SwapV2: 1055, 1051, 1043, 1041, 1044
- SwapX2: 2802, 2803, 2803, 2805, 2805
Пять тестов с 50.000.000 раз 6 байтов
- SwapV2: 1092, 1085, 1086, 1087, 1086
- SwapX2: 1018, 1019, 1015, 1017, 1018
Но если данные большие и производительность действительно имеет значение, вы можете использовать SSE или AVX. (В 13 раз быстрее.) https://pastebin.com/WaFk275U
Тест 5 раз, 100000 циклов с 8192 байтами или 4096 символами
- SwapX2: 226, 223, 225, 226, 227, мин: 223
- SwapV2: 113, 111, 112, 114, 112 Мин: 111
- SwapA2: 17, 17, 17, 17, 16 мин: 16