Sie können ein separates P/Invoke-Front-End für jede Art von Array schreiben, das Sie vergleichen möchten. Ich weiß, dass du dich nicht wirklich auf T spezialisieren willst, aber der Overhead ist nicht so groß, denke ich.
Dies ist ein bisschen ein Hack, weil ich mehrere P/Invoke-Methoden mit verschiedenen Signaturen für die gleiche API-Funktion definieren, aber dadurch kann ich die P/Invoke Marshalling-Unterstützung nutzen.
(Beachten Sie, dass das Vorzeichen des Rückgabewerts von memcmp nur dann sinnvoll ist, wenn die Quelldaten tatsächlich ein Array von Bytes sind.Wenn Sie ihm ein Array von Ints geben, sollten Sie nur den Rückgabewert mit Null vergleichen und sein Vorzeichen ignorieren. Die Reihenfolge, die es bedeutet, ist nicht sinnvoll für ints)
Zum Beispiel der folgende Code gibt mir die folgende (RELEASE zu bauen, nicht Debug-Build).
MemCmp with ints took 00:00:08.0768666
ManagedMemCmp with ints took 00:00:10.3750453
MemCmp with bytes took 00:00:01.8740001
ManagedMemCmp with bytes took 00:00:09.2885763
Beachten Sie, dass die byte [] Test verwendet Bytes, vergleicht also ein Viertel der Anzahl der Bytes, die der int [] Test verwendet. Der verwaltete Code nimmt die gleiche Anzahl von Vergleichen vor, ist also vergleichsweise viel langsamer.
Es gibt nicht wirklich einen großen Unterschied zwischen den Zeiten für den Vergleich von Arrays von Ints, aber es gibt einen großen Unterschied für den Vergleich von Arrays von Bytes. Dies deutet darauf hin, dass es eine verwaltete Optimierung geben könnte, die fixed verwendet, um einen Zeiger auf Ints von einem Byte-Array zu erhalten, um 4 Bytes gleichzeitig zu vergleichen (mit etwas fummeln für die möglicherweise zusätzlichen Bytes am Ende, dass don ' t passen in einen int).
Ich denke auch, dass Sie eine multithreaded verwaltete Version (mit der "Int *" -Optimierung zum Vergleich von Byte-Arrays) schreiben könnte, die viel schneller als die nicht verwaltete Memcmp() wäre, die natürlich nicht Multithread ist (soweit ich kennt).
Wie auch immer, hier ist mein Testcode. Denken Sie daran, RELEASE bauen, nicht debuggen!
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Demo
{
public static class Program
{
private static void Main(string[] args)
{
int[] a1 = new int[1000000];
int[] a2 = new int[1000000];
for (int i = 0; i < a1.Length-1; ++i)
{
a1[i] = i;
a2[i] = i;
}
a1[a1.Length-1] = 1;
a2[a1.Length-1] = 2;
byte[] b1 = new byte[1000000];
byte[] b2 = new byte[1000000];
for (int i = 0; i < b1.Length-1; ++i)
{
b1[i] = (byte)i;
b2[i] = (byte)i;
}
b1[a1.Length-1] = 1;
b2[a1.Length-1] = 2;
Stopwatch sw = Stopwatch.StartNew();
testWithMemCmp(a1, a2);
sw.Stop();
Console.WriteLine("MemCmp with ints took " + sw.Elapsed);
sw.Restart();
testWithManagedMemCmp(a1, a2);
sw.Stop();
Console.WriteLine("ManagedMemCmp with ints took " + sw.Elapsed);
sw.Restart();
testWithMemCmp(b1, b2);
sw.Stop();
Console.WriteLine("MemCmp with bytes took " + sw.Elapsed);
sw.Restart();
testWithManagedMemCmp(b1, b2);
sw.Stop();
Console.WriteLine("ManagedMemCmp with bytes took " + sw.Elapsed);
}
private static void testWithMemCmp(int[] a1, int[] a2)
{
for (int j = 0; j < COUNT; ++j)
{
MemCmp(a1, a2);
}
}
private static void testWithMemCmp(byte[] a1, byte[] a2)
{
for (int j = 0; j < COUNT; ++j)
{
MemCmp(a1, a2);
}
}
private static void testWithManagedMemCmp(int[] a1, int[] a2)
{
for (int j = 0; j < COUNT; ++j)
{
ManagedMemCmp(a1, a2);
}
}
private static void testWithManagedMemCmp(byte[] a1, byte[] a2)
{
for (int j = 0; j < COUNT; ++j)
{
ManagedMemCmp(a1, a2);
}
}
public static bool ManagedMemCmp(int[] a1, int[] a2)
{
if (a1 == null || a2 == null || a1.Length != a2.Length)
{
throw new InvalidOperationException("Arrays are null or different lengths.");
}
for (int i = 0; i < a1.Length; ++i)
{
if (a1[i] != a2[i])
{
return false;
}
}
return true;
}
public static bool ManagedMemCmp(byte[] a1, byte[] a2)
{
if (a1 == null || a2 == null || a1.Length != a2.Length)
{
throw new InvalidOperationException("Arrays are null or different lengths.");
}
for (int i = 0; i < a1.Length; ++i)
{
if (a1[i] != a2[i])
{
return false;
}
}
return true;
}
public static bool MemCmp(byte[] a1, byte[] a2)
{
if (a1 == null || a2 == null || a1.Length != a2.Length)
{
throw new InvalidOperationException("Arrays are null or different lengths.");
}
return memcmp(a1, a2, new UIntPtr((uint)a1.Length)) == 0;
}
public static bool MemCmp(int[] a1, int[] a2)
{
if (a1 == null || a2 == null || a1.Length != a2.Length)
{
throw new InvalidOperationException("Arrays are null or different lengths.");
}
return memcmp(a1, a2, new UIntPtr((uint)(a1.Length * sizeof(int)))) == 0;
}
[DllImport("msvcrt.dll")]
private static extern int memcmp(byte[] a1, byte[] a2, UIntPtr count);
[DllImport("msvcrt.dll")]
private static extern int memcmp(int[] a1, int[] a2, UIntPtr count);
private const int COUNT = 10000;
}
}
Sie nicht nennen kann 'memcpy' von C# –
Darüber hinaus haben Sie versucht,' öffentlich unsichere Überschreibung bool Equals (T [] x, T [] y) where T: struct'? – Davio
Warum versuchen Sie, Ihren Code zu optimieren? Sie erstellen wahrscheinlich mehr Leistungsprobleme durch Marshalling auf nicht verwalteten Code. –