Per Split, la gestione ulong sulla macchina a 32 bit è molto lenta, quindi riduci decisamente a uint. Se si desidera veramente ulong, implementare due versioni, una per 32 bit, una per 64 bit.
È inoltre necessario misurare se il byte di gestione alla volta è più veloce.
È necessario definire il costo dell'allocazione di memoria. Se è abbastanza grande, prova a riutilizzare la memoria attraverso più chiamate.
Altro:
ToString: è più veloce da usare "(" + Offset.ToString() + "" + Length.ToString() + ")";
GetHashCode: provare fisso (byte * b = & tampone [offset])
Questa versione dovrebbe essere molto veloce, se utilizzato più volte. Punto chiave: nessuna nuova allocazione di memoria dopo che l'array interno si è espanso alle dimensioni corrette, copia minima dei dati.
class ArraySplitter
{
private byte[] m_data;
private int m_count;
private int[] m_stops;
private void AddRange(int start, int stop)
{
// Skip empty range
if (start > stop)
{
return;
}
// Grow array if needed
if ((m_stops == null) || (m_stops.Length < (m_count + 2)))
{
int[] old = m_stops;
m_stops = new int[m_count * 3/2 + 4];
if (old != null)
{
old.CopyTo(m_stops, 0);
}
}
m_stops[m_count++] = start;
m_stops[m_count++] = stop;
}
public int Split(byte[] data, byte sep)
{
m_data = data;
m_count = 0; // reuse m_stops
int last = 0;
for (int i = 0; i < data.Length; i ++)
{
if (data[i] == sep)
{
AddRange(last, i - 1);
last = i + 1;
}
}
AddRange(last, data.Length - 1);
return m_count/2;
}
public ArraySegment<byte> this[int index]
{
get
{
index *= 2;
int start = m_stops[index];
return new ArraySegment<byte>(m_data, start, m_stops[index + 1] - start + 1);
}
}
}
programma di test:
static void Main(string[] args)
{
int count = 1000 * 1000;
byte[] data = new byte[count];
for (int i = 0; i < count; i++)
{
data[i] = (byte) i;
}
Stopwatch watch = new Stopwatch();
for (int r = 0; r < 10; r++)
{
watch.Reset();
watch.Start();
int len = 0;
foreach (var seg in data.MySplit(13))
{
len += seg.Count;
}
watch.Stop();
Console.WriteLine("MySplit : {0} {1,8:N3} ms", len, watch.Elapsed.TotalMilliseconds);
watch.Reset();
watch.Start();
ArraySplitter splitter = new ArraySplitter();
int parts = splitter.Split(data, 13);
len = 0;
for (int i = 0; i < parts; i++)
{
len += splitter[i].Count;
}
watch.Stop();
Console.WriteLine("ArraySplitter: {0} {1,8:N3} ms", len, watch.Elapsed.TotalMilliseconds);
}
}
Risultato:
MySplit : 996093 9.514 ms
ArraySplitter: 996093 4.754 ms
MySplit : 996093 7.760 ms
ArraySplitter: 996093 2.710 ms
MySplit : 996093 8.391 ms
ArraySplitter: 996093 3.510 ms
MySplit : 996093 9.677 ms
ArraySplitter: 996093 3.468 ms
MySplit : 996093 9.685 ms
ArraySplitter: 996093 3.370 ms
MySplit : 996093 9.700 ms
ArraySplitter: 996093 3.425 ms
MySplit : 996093 9.669 ms
ArraySplitter: 996093 3.519 ms
MySplit : 996093 9.844 ms
ArraySplitter: 996093 3.416 ms
MySplit : 996093 9.721 ms
ArraySplitter: 996093 3.685 ms
MySplit : 996093 9.703 ms
ArraySplitter: 996093 3.470 ms
Possiamo vedere il tuo * versione "ottimizzata" di Spalato * in modo che possiamo pensare a come migliorarlo? –
Portatile nel senso di una libreria di classi portatile come descritto qui: http://msdn.microsoft.com/en-us/library/gg597391.aspx? –
Puoi trovare il suo codice nel link "versione ottimizzata". –