我正在编写一个完全托管的 Mercurial 库(用于完全托管的 Mercurial Server for Windows,即将推出),我遇到的最严重的性能问题之一是,奇怪的是,将数组拆分为零件。
想法如下:有一个字节数组,大小从几百字节到一兆字节不等,我需要用它做的就是将它分成几个部分,在我的具体情况下,\n
个字符。
现在 dotTrace 向我显示的是我的 "optimized" version Split
(代码 是正确的,我开始使用的 here's the naive 版本)在 2,300 次调用中占用了 11 秒(dotTrace 本身引入了明显的性能影响,但是一切都符合规模)。
这是数字:
不安全
版本:11 297
ms for2 312
calls- 托管(“原始”)版本:
20 001
ms for2 312
calls
所以这里是:在 C# 中拆分数组的最快方式(最好是可移植的,意味着同时支持 x86 和 x64)。
最佳答案
我认为问题在于,您在循环中执行了很多复杂的操作。这段代码去掉了循环内除了单次加法和比较之外的所有操作。其他复杂的事情只有在检测到拆分或在数组末尾时才会发生。
此外,很难说出您使用哪种数据运行测试,因此这只是猜测。
public static unsafe Segment[] Split2(byte[] _src, byte value)
{
var _ln = _src.Length;
if (_ln == 0) return new Segment[] { };
fixed (byte* src = _src)
{
var segments = new LinkedList<Segment>(); // Segment[c];
byte* last = src;
byte* end = src + _ln - 1;
byte lastValue = *end;
*end = value; // value-termination
var cur = src;
while (true)
{
if (*cur == value)
{
int begin = (int) (last - src);
int length = (int) (cur - last + 1);
segments.AddLast(new Segment(_src, begin, length));
last = cur + 1;
if (cur == end)
{
if (lastValue != value)
{
*end = lastValue;
}
break;
}
}
cur++;
}
return segments.ToArray();
}
}
编辑:修改代码,使其返回正确的结果。
关于c# - 在 C# 中拆分数组的最快(可移植)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12133163/