| using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication17
{
class Program
{
static void Main(string[] args)
{
int arraySize = 1000 * 1000;
int repeatCount = 4000;
byte[] array = new byte[arraySize];
new Random(0).NextBytes(array);
/*
var src = new byte[] { 1, 2, 10, 3, 4, 10, 4, 5, 10, 7, 8, 10, 9, 10, 1 };
var refRes = SplitNaive(src, 10);
foreach (var r in refRes)
{
Console.WriteLine("{0} {1}", r.Start, r.Length);
}
Console.WriteLine();
var res = Split5(src, 10);
foreach (var r in res)
{
Console.WriteLine("{0} {1}", r.Start, r.Length);
}
return;
*/
// warmup
var buf = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var result = Split1(buf, 10);
result = Split2(buf, 10);
result = Split3(buf, 10);
result = Split4(buf, 10);
result = Split5(buf, 10);
result = Split5(buf, 10);
result = Split6(buf, 10);
result = Split5L(buf, 10);
var split1 = true;
var split2 = true;
var split3 = true;
var split4 = true;
var split5 = true;
var split6 = true;
var split5l = true;
var sw = new Stopwatch();
if (split1)
{
sw.Start();
for (int i = 0; i < repeatCount; i++)
{
result = Split1(array, 10);
}
sw.Stop();
Console.WriteLine(" Split1: {0}\t{1}", sw.ElapsedMilliseconds, result.Length);
}
sw.Reset();
if (split2)
{
sw.Start();
for (int i = 0; i < repeatCount; i++)
{
result = Split2(array, 10);
}
sw.Stop();
Console.WriteLine(" Split2: {0}\t{1}", sw.ElapsedMilliseconds, result.Length);
}
sw.Reset();
if (split3)
{
sw.Start();
for (int i = 0; i < repeatCount; i++)
{
result = Split3(array, 10);
}
sw.Stop();
Console.WriteLine(" Split3: {0}\t{1}", sw.ElapsedMilliseconds, result.Length);
}
sw.Reset();
if (split4)
{
sw.Start();
for (int i = 0; i < repeatCount; i++)
{
result = Split4(array, 10);
}
sw.Stop();
Console.WriteLine(" Split4: {0}\t{1}", sw.ElapsedMilliseconds, result.Length);
}
sw.Reset();
if (split5)
{
sw.Start();
for (int i = 0; i < repeatCount; i++)
{
result = Split5(array, 10);
}
sw.Stop();
Console.WriteLine(" Split5: {0}\t{1}", sw.ElapsedMilliseconds, result.Length);
}
sw.Reset();
if (split6)
{
sw.Start();
for (int i = 0; i < repeatCount; i++)
{
result = Split6(array, 10);
}
sw.Stop();
Console.WriteLine(" Split6: {0}\t{1}", sw.ElapsedMilliseconds, result.Length);
}
sw.Reset();
if (split5l)
{
sw.Start();
for (int i = 0; i < repeatCount; i++)
{
result = Split5L(array, 10);
}
sw.Stop();
Console.WriteLine("Split5L: {0}\t{1}", sw.ElapsedMilliseconds, result.Length);
}
sw.Reset();
Console.WriteLine("Press any enter... :)");
Console.ReadLine();
}
public static unsafe Segment[] Split1(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();
}
}
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();
}
}
public static Segment[] Split3(byte[] buffer, byte value)
{
if (buffer.Length == 0)
{
return new Segment[0];
}
List<Segment> list = null;
int start = 0;
int length = 0;
for (int i = 0; i < buffer.Length; i++)
{
if (buffer[i] == value)
{
if (length != 0)
{
if (list == null)
{
list = new List<Segment>(16);
}
list.Add(new Segment(buffer, start, length));
}
start = i + 1;
length = 0;
}
else
{
length++;
}
}
if (length != 0)
{
if (list == null)
{
list = new List<Segment>(16);
}
list.Add(new Segment(buffer, start, length));
}
return list.ToArray();
}
public static Segment[] Split4(byte[] buffer, byte value)
{
var list = new LinkedList<Segment>();
int start = 0;
for (int i = 0; i < buffer.Length; i++)
{
if (buffer[i] == value)
{
//if (start < i)
//{
list.AddLast(new Segment(buffer, start, i - start));
//}
start = i + 1;
}
}
//if (start < buffer.Length)
//{
list.AddLast(new Segment(buffer, start, buffer.Length - start));
//}
return list.ToArray();
}
public static unsafe Segment[] Split5(byte[] buffer, byte value)
{
var result = new LinkedList<Segment>();
var length = buffer.Length;
fixed (byte* bbuf = buffer)
{
var qbuf = (uint*)bbuf;
var qlen = length / sizeof(uint);
var qrem = length % sizeof(uint);
int start = 0;
while (qlen > 0)
{
uint q = *qbuf;
if ((q & 0x000000FF) == (uint)0x0A)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 1;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0x0000FF00) == (uint)0x0A00)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 2;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0x00FF0000) == (uint)0x0A0000)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 3;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0xFF000000) == (uint)0x0A000000)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 4;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
qbuf++;
qlen--;
}
// хвост
if (qrem > 0)
{
for (byte* rbuf = (byte*)qbuf; qrem > 0; rbuf++, qrem--)
{
if (*rbuf == 10)
{
var offset = (int)((byte*)qbuf - (byte*)rbuf) + 1;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
}
}
}
return result.ToArray();
}
public static unsafe Segment[] Split6(byte[] buffer, byte value)
{
var result = new LinkedList<Segment>();
var length = buffer.Length;
fixed (byte* bbuf = buffer)
{
var qbuf = (ulong*)bbuf;
var qlen = length / sizeof(ulong);
var qrem = length % sizeof(ulong);
int start = 0;
while (qlen > 0)
{
ulong q = *qbuf;
if ((q & 0x000000FF) == (ulong)0x0A)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 1;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0x0000FF00) == (ulong)0x0A00)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 2;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0x00FF0000) == (ulong)0x000A0000)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 3;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0xFF000000) == (ulong)0x0A000000)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 4;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0xFF00000000) == (ulong)0x0A00000000)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 5;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0xFF0000000000) == (ulong)0x0A0000000000)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 6;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0xFF000000000000) == (ulong)0x0A000000000000)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 7;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0xFF00000000000000) == (ulong)0x0A00000000000000)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 8;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
qbuf++;
qlen--;
}
// хвост
if (qrem > 0)
{
for (byte* rbuf = (byte*)qbuf; qrem > 0; qrem--)
{
if (*rbuf == 10)
{
var offset = (int)((byte*)qbuf - (byte*)rbuf) + 1;
result.AddLast(new Segment(buffer, start, offset - start));
start = offset;
}
}
}
}
return result.ToArray();
}
public static unsafe Segment[] Split5L(byte[] buffer, byte value)
{
var result = new List<Segment>();
var length = buffer.Length;
fixed (byte* bbuf = buffer)
{
var qbuf = (uint*)bbuf;
var qlen = length / sizeof(uint);
var qrem = length % sizeof(uint);
int start = 0;
while (qlen > 0)
{
uint q = *qbuf;
if ((q & 0x000000FF) == (uint)0x0A)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 1;
result.Add(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0x0000FF00) == (uint)0x0A00)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 2;
result.Add(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0x00FF0000) == (uint)0x0A0000)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 3;
result.Add(new Segment(buffer, start, offset - start));
start = offset;
}
if ((q & 0xFF000000) == (uint)0x0A000000)
{
var offset = (int)((byte*)qbuf - (byte*)bbuf) + 4;
result.Add(new Segment(buffer, start, offset - start));
start = offset;
}
qbuf++;
qlen--;
}
// хвост
if (qrem > 0)
{
for (byte* rbuf = (byte*)qbuf; qrem > 0; qrem--)
{
if (*rbuf == 10)
{
var offset = (int)((byte*)qbuf - (byte*)rbuf) + 1;
result.Add(new Segment(buffer, start, offset - start));
start = offset;
}
}
}
}
return result.ToArray();
}
public unsafe static Segment[] SplitNaive(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();
}
}
}
public struct Segment
{
public Segment(byte[] buffer, int start, int length)
{
Buffer = buffer;
Start = start;
Length = length;
}
public readonly byte[] Buffer;
public readonly int Start;
public readonly int Length;
}
}
|