Я на самом деле пробовал несколько разных способов преобразовать четыре байта в целое:
BitConverter.ToInt32(new byte[] { w, x, y, z }, 0);
BitConverter.ToUInt32(new byte[] { w, x, y, z }, 0);
b = new byte[] { w, x, y, z };
BitConverter.ToInt32(b, 0);
b = new byte[] { 1, 2, 3, 4, 5, 6, 7, w, x, y, z };
BitConverter.ToInt32(b, 7);
w | (x << 8) | (y << 16) | (z << 24);
b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
Я выполнил 10 ^ 9 итераций каждой из них в сборке выпуска (x86), а не под отладчиком на ноутбуке с тактовой частотой 2,5 ГГц Core i7 . Вот мои результаты (обратите внимание, что методы, которые не используют BitConverter
, существенно быстрее):
test1: 00:00:15.5287282 67305985
test2: 00:00:15.1334457 67305985
test3: 00:00:08.0648586 67305985
test4: 00:00:11.2307059 67305985
test5: 00:00:02.0219417 67305985
test6: 00:00:01.6275684 67305985
Некоторые выводы, которые вы можете сделать:
- test1 показывает, что на моем ноутбуке преобразование происходит медленнее, чем 15 нс, что, как я ненавижу, должно быть достаточно быстрым для всех. (Вам нужно вызывать его более 60 миллионов раз в секунду?)
- test2 показывает, что использование
uint
вместо int
экономит небольшое количество времени. Я не уверен, почему, но я думаю, что он достаточно мал, чтобы быть экспериментальной ошибкой.
- test3 показывает, что накладные расходы на создание нового байтового массива (7 нс) почти равны вызову функции, но все же быстрее, чем создание нового массива из старого массива.
- test4 показывает, что при доступе к невыровненному массиву из
ToInt32
добавляются издержки (3 нс)
- test5 показывает, что вытащить 4 байта из локальных переменных и объединить их самостоятельно в несколько раз быстрее, чем вызвать
ToInt32
.
- test6 показывает, что на самом деле немного быстрее извлечь 4 байта из массива, чем из аргументов функции! Я подозреваю, что это связано с конвейерной обработкой процессора или эффектами кэша.
Самый быстрый, test6, выполнялся всего в два раза дольше, чем пустой цикл (не показан). Другими словами, для каждого преобразования потребовалось менее 1 нс. Удачи в получении любого полезного вычисления, чтобы идти быстрее этого!
Вот моя тестовая программа:
using System;
namespace BitConverterTest
{
class Program
{
const int iters = 1000000000;
static void Main(string[] args)
{
test1(1, 2, 3, 4);
test2(1, 2, 3, 4);
test3(1, 2, 3, 4);
test4(1, 2, 3, 4);
test5(1, 2, 3, 4);
test6(1, 2, 3, 4);
}
static void test1(byte w, byte x, byte y, byte z)
{
int res = 0;
var timer = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < iters; i++)
res = BitConverter.ToInt32(new byte[] { w, x, y, z }, 0);
Console.WriteLine("test1: " + timer.Elapsed + " " + res);
}
static void test2(byte w, byte x, byte y, byte z)
{
uint res = 0;
var timer = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < iters; i++)
res = BitConverter.ToUInt32(new byte[] { w, x, y, z }, 0);
Console.WriteLine("test2: " + timer.Elapsed + " " + res);
}
static void test3(byte w, byte x, byte y, byte z)
{
int res = 0;
var timer = System.Diagnostics.Stopwatch.StartNew();
var b = new byte[] { w, x, y, z };
for (int i = 0; i < iters; i++)
res = BitConverter.ToInt32(b, 0);
Console.WriteLine("test3: " + timer.Elapsed + " " + res);
}
static void test4(byte w, byte x, byte y, byte z)
{
int res = 0;
var timer = System.Diagnostics.Stopwatch.StartNew();
var b = new byte[] { 1, 2, 3, 4, 5, 6, 7, w, x, y, z };
for (int i = 0; i < iters; i++)
res = BitConverter.ToInt32(b, 7);
Console.WriteLine("test4: " + timer.Elapsed + " " + res);
}
static void test5(byte w, byte x, byte y, byte z)
{
int res = 0;
var timer = System.Diagnostics.Stopwatch.StartNew();
var b = new byte[] { w, x, y, z };
for (int i = 0; i < iters; i++)
res = w | (x << 8) | (y << 16) | (z << 24);
Console.WriteLine("test5: " + timer.Elapsed + " " + res);
}
static void test6(byte w, byte x, byte y, byte z)
{
int res = 0;
var timer = System.Diagnostics.Stopwatch.StartNew();
var b = new byte[] { w, x, y, z };
for (int i = 0; i < iters; i++)
res = b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
Console.WriteLine("test6: " + timer.Elapsed + " " + res);
}
}
}