我写了以下代码将字节数组
问题是,尽管生成的文件不到20MB,但需要数分钟才能完成。因此我试图进行优化,并想出了以下方法:
data
转换为字符串数组hex
,每个条目包含32个字节的十六进制字符串,以便将它们写入文件。byte[] data = new byte[4*1024*1024];
string[] hex = data.Select((b) => b.ToString("X2")).ToArray();
hex = Enumerable.Range(0, data.Length / 32).Select((r) => String.Join(" ", hex.Skip(r * 32).Take(32))).ToArray(); // <= This line takes forever
问题是,尽管生成的文件不到20MB,但需要数分钟才能完成。因此我试图进行优化,并想出了以下方法:
byte[] data = new byte[4*1024*1024];
string[] hex = new string[4*1024*1024/32];
for (var i = 0; i <= hex.Length - 1; i++)
{
var sb = new System.Text.StringBuilder();
sb.Append(data[i * 32].ToString("X2"));
for (var k = 1; k <= 32 - 1; k++)
{
sb.Append(' ');
sb.Append(data[i * 32 + k].ToString("X2"));
}
hex[i] = sb.ToString();
}
这个版本做同样的事情,但速度快了几个数量级(133毫秒对比8分钟)。
我的问题是我真的不明白为什么原始版本这么慢。我查看了 String.Join()
的源代码,它看起来与我的改进版非常相似。
我喜欢为这些类型的事情使用LINQ,因为你可以轻松地解决各种问题,并且我认为由于其延迟评估,大多数情况下它是有效的。因此,我想知道我在这里缺少了什么,以改进我的LINQ的未来使用。
顺便说一句,我知道它可能还可以更快地编写,但这确实不是重点,因为第二个版本已经足够快,而且只用于调试目的。
Skip().Take()
将会一遍又一遍地迭代data
。另外,我想你可能是想使用hex
。一个替代方法是使用包含索引的Select
并根据索引除以 32 进行分组,然后迭代这些结果并使用字符串生成器。 - juharrString.Join()
上,但我不知道为什么在这种情况下它如此缓慢。 这对我很重要,因为我经常使用String.Join()
,想知道何时避免使用它。 - Karsten