Bạn có thể viết một giao diện P/Invoke riêng cho mỗi loại mảng mà bạn muốn so sánh. Tôi biết bạn không thực sự muốn chuyên về T, nhưng chi phí không quá lớn tôi nghĩ.
Đây là một chút hack, bởi vì tôi định nghĩa nhiều phương thức P/Invoke với các chữ ký khác nhau cho cùng một hàm API, nhưng bằng cách làm điều này tôi có thể tận dụng sự hỗ trợ marshalling P/Invoke.
(Lưu ý rằng dấu của giá trị trả về từ memcmp thực sự chỉ có ý nghĩa nếu dữ liệu nguồn thực sự là một mảng byte.Nếu bạn đang cho nó một mảng ints, bạn chỉ nên so sánh giá trị trả về bằng 0 và bỏ qua dấu của nó. Trật tự đó nó ngụ ý là không có ý nghĩa cho ints)
Ví dụ, đoạn mã sau in sau cho tôi (CHÍ xây dựng, không phải debug xây dựng):.
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
Lưu ý rằng các byte [] thử nghiệm đang sử dụng byte để so sánh một phần tư số byte so với phép thử int [] sử dụng. Mã được quản lý tạo ra cùng một số lượng so sánh, vì vậy nó tương đối chậm hơn rất nhiều.
Không có sự khác biệt lớn giữa thời gian so sánh các mảng ints, nhưng có sự khác biệt lớn khi so sánh các mảng byte. Điều này gợi ý với tôi rằng có thể có tối ưu hóa được quản lý sử dụng cố định để đưa con trỏ đến ints từ mảng byte để so sánh 4 byte tại một thời điểm (với một số fiddling cho các byte có thể thêm vào cuối mà don ' t phù hợp với một int). Tôi cũng nghĩ rằng bạn có thể viết một phiên bản được quản lý đa luồng (sử dụng "int *" tối ưu hóa để so sánh các mảng byte) sẽ là MUCH FASTER nhanh hơn memcmp không được quản lý(), tất nhiên là không đa luồng (theo như tôi đã đọc). biết).
Dù sao, đây là mã thử nghiệm của tôi. Hãy nhớ, RELEASE xây dựng, không gỡ lỗi!
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;
}
}
bạn không thể gọi 'memcpy' từ C# –
Bên cạnh đó, bạn đã thử' công cộng không an toàn ghi đè bool Equals (T [] x, T [] y) trong đó T: struct'? – Davio
tại sao bạn đang cố tối ưu hóa mã của mình? bạn có thể tạo ra nhiều vấn đề về hiệu suất hơn bằng cách marshaling thành mã không được quản lý. –