È possibile scrivere un front-end P/Invoke separato per ogni tipo di array che si desidera confrontare. So che non vuoi davvero specializzarti su T, ma penso che il sovraccarico non sia troppo grande.
Questo è un po 'un hack, perché sto definendo più metodi P/Invoke con firme diverse per la stessa funzione API, ma facendo questo posso sfruttare il supporto di marshalling P/Invoke.
(Si noti che il segno del valore restituito da memcmp è davvero significativo solo se i dati di origine sono effettivamente una matrice di byte.Se gli stai dando una serie di valori, dovresti solo confrontare il valore restituito con zero e ignorare il suo segno. L'ordinamento che essa implica non è significativo per interi)
Ad esempio, il seguente codice stampa la seguente per me (STAMPA costruire, non build di debug):.
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
Si noti che il byte [] prova sta usando i byte quindi confronta un quarto del numero di byte rispetto al test int [] utilizzato. Il codice gestito fa lo stesso numero di confronti, quindi è comparativamente molto più lento.
Non c'è davvero un'enorme differenza tra i tempi per il confronto di matrici di interi, ma c'è una grande differenza per il confronto di matrici di byte. Questo mi suggerisce che potrebbe esserci un'ottimizzazione gestita che utilizza fissa per ottenere un puntatore a ints da una matrice di byte per confrontare 4 byte alla volta (con qualche giochino per i byte eventualmente extra alla fine che don ' t adatto a un int).
Penso anche che potresti scrivere una versione gestita multithread (utilizzando l'ottimizzazione "int *" per confrontare gli array di byte) che sarebbe MOLTO PIÙ FACILE rispetto al memcmp non gestito(), che ovviamente non è multithread (per quanto mi riguarda conoscere).
In ogni caso, ecco il mio codice di prova. Ricorda, RILASCIARE costruire, non eseguire il debug!
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;
}
}
non è possibile chiamare 'memcpy' da C# –
Inoltre, hai provato' pubblica non sicura di override bool Equals (T [] x, T [] y) dove T: struct'? – Davio
perché stai cercando di ottimizzare il tuo codice? probabilmente stai creando più problemi di prestazioni tramite il marshalling verso il codice non gestito. –