Уже
задавал вопрос на StackOverflow, но тамошний коллективный разум ничего действенного не подсказал.
Дело вот в чем. Есть массив байтов (размер -- от нескольких байт до нескольких сотен килобайт). Нужно максимально быстро разбить его на куски. Критерий разбиения в моем случае -- по символу
\n (
0xA):
1, 2, 3, 10, 4, 10, 5, 6, 10, 7, 10 -> 1, 2, 3; 4; 5, 6; 7
По показаниям dotTrace:
"Наивная" версия -- 20 001 мс. на 2 312 вызовов:
public unsafe static Segment[] Split(this byte[] _src, byte value)
{
var _ln = _src.Length;
fixed(byte *src = _src)
{
if(_ln == 0) return new Segment[] { };
var segments = new LinkedList<Segment>();// Segment[c];
var l = 0;
var j = 0;
var last = 0;
var i = 0;
for(i = 0; i < _ln; i++)
{
l++;
if(src[i] != value) continue;
segments.AddLast(new Segment(_src, last, l));
l = 0;
last = i + 1;
} // for
if(last != i)
segments.AddLast(new Segment(_src, last, _ln - last));
return segments.ToArray();
}
}
Оптимизация, предложенная Euphoric -- 4 696 мс на 2 312 вызовов:
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();
}
}
Почти в 5 раз быстрее, но все равно ужасно медленно.
Возможно, у вас будут какие-то предложения? Или переписать все на Managed C++ (или как там его нынче называют)?