我实际上尝试了几种不同的方法将四个字节转换为 int:
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);
我在发布 (x86) 版本中运行了 10^9 次迭代,而不是在 2.5 GHz 的调试器下运行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 表明,在我的笔记本电脑上,很难让转换速度慢于 15ns,但我不想说这对任何人来说都足够快了。 (每秒调用次数是否需要超过60M次?)
- test2表明使用
uint
代替int
节省少量时间。我不知道为什么,但我认为它小到足以成为实验误差。
- test3 显示创建新字节数组的开销 (7ns) 与调用该函数几乎一样多,但仍然比从旧数组创建新数组要快。
- test4 表明,进行未对齐的数组访问
ToInt32
增加开销(3ns)
- test5 表明,从局部变量中提取 4 个字节并自行组合它们比调用快几倍
ToInt32
.
- test6 表明,从数组中提取 4 个字节实际上比从函数参数中提取要快一些!我怀疑这是由于 CPU 流水线或缓存效应造成的。
最快的 test6 的运行时间仅为空循环(未显示)的两倍。换句话说,执行每次转换所需的时间不到 1ns。祝你好运,任何有用的计算都比这更快!
这是我的测试程序:
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);
}
}
}