memcmp in C#
-
I want to compare two byte buffer quickly. I used to do this with memcmp in C. I can't find a function to do that in C#. I'm sure there is one, but I can't find it. BRCKCC
There really isn't a way as fast as
memcmp
, so if you need that kind of performance, you can always P/Invoke it:using System;
using System.Runtime.InteropServices;class Test
{
static void Main()
{
byte[] b1 = new byte[10];
byte[] b2 = new byte[10];for (int i=0; iThis would print:
Equals: False
Object.Equals: False
memcmp: TrueBy doing this you sacrific portability, however. If you don't need that kind of performance, use a simple
for
(notforeach
, which is slower) loop and compare each byte using the==
equivalency operator.Microsoft MVP, Visual C#
My Articles -
There really isn't a way as fast as
memcmp
, so if you need that kind of performance, you can always P/Invoke it:using System;
using System.Runtime.InteropServices;class Test
{
static void Main()
{
byte[] b1 = new byte[10];
byte[] b2 = new byte[10];for (int i=0; iThis would print:
Equals: False
Object.Equals: False
memcmp: TrueBy doing this you sacrific portability, however. If you don't need that kind of performance, use a simple
for
(notforeach
, which is slower) loop and compare each byte using the==
equivalency operator.Microsoft MVP, Visual C#
My Articles -
I'm using the for loop and since I don't want to sacrifice portability, I'll stick with the for loop. Thanks. - Bruce BRCKCC
Also, if you'd be allowed to use unsafe code, it would be much faster. You'd be able to loop thru the array cast to array of ints and comparing 4 bytes at a time. Plus the CPU works better with int values than single byte values. Of course you'd have to have a special case for padding bytes.
-
Also, if you'd be allowed to use unsafe code, it would be much faster. You'd be able to loop thru the array cast to array of ints and comparing 4 bytes at a time. Plus the CPU works better with int values than single byte values. Of course you'd have to have a special case for padding bytes.
-
Here is a simple program that tests the comparison using safe and unsafe version. On my machine the unsafe version is about 4 times as fast as safe version. You have to make sure you allow unsafe code in project properties. Note, this will only work with arrays whose size is divisble by 4. You can easily change it to handle the last 1, 2 or 3 bytes specially, but i'll leave it as excercise.
using System; namespace Tester { class Class1 { [STAThread] static void Main(string[] args) { const int repeats = 200; byte[] bytes1 = randomBytes(4 * 1000000); byte[] bytes2 = new byte[bytes1.Length]; for (int i=0; i<bytes1.Length; i++) bytes1[i] = bytes2[i]; // unsafe version int start_t = System.Environment.TickCount; for (int r=1; r<=repeats; r++) { bool res = CompareUnsafe(bytes1, bytes2); if (r == repeats) Console.WriteLine("Result: " + res); } int end_t = System.Environment.TickCount; Console.WriteLine("CompareUnsafe: {0} ms.", (end_t-start_t)); // safe version start_t = System.Environment.TickCount; for (int r=1; r<=repeats; r++) { bool res = CompareSafe(bytes1, bytes2); if (r == repeats) Console.WriteLine("Result: " + res); } end_t = System.Environment.TickCount; Console.WriteLine("CompareSafe: {0} ms.", (end_t-start_t)); } public static bool CompareSafe(byte[] byteArray1, byte[] byteArray2) { if (byteArray1.Length != byteArray2.Length) return false; for (int i=0; i<byteArray1.Length; i++) if (byteArray1[i] != byteArray2[i]) return false; return true; } public unsafe static bool CompareUnsafe(byte[] byteArray1, byte[] byteArray2) { if (byteArray1.Length != byteArray2.Length) return false; if (byteArray1.Length % 4 != 0) throw new ArgumentException("Byte arrays have to be divisible by 4", "bytearray"); fixed (byte* bytes1 = &(byteArray1[0])) fixed (byte* bytes2 = &(byteArray2[0])) { int* ints1 = (int*)bytes1; int* ints2 = (int*)bytes2; int size = byteArray1.Length / 4; for (int i=0; i<size; i++) if (ints1[i] != ints2[i]) return false; } // all comparisons succeeded return true; } public static byte[] randomBytes(int size) { Random r = new Random(); byte[] bytes = new byte[size]; r.NextBytes(bytes); return bytes; } } }
-
Here is a simple program that tests the comparison using safe and unsafe version. On my machine the unsafe version is about 4 times as fast as safe version. You have to make sure you allow unsafe code in project properties. Note, this will only work with arrays whose size is divisble by 4. You can easily change it to handle the last 1, 2 or 3 bytes specially, but i'll leave it as excercise.
using System; namespace Tester { class Class1 { [STAThread] static void Main(string[] args) { const int repeats = 200; byte[] bytes1 = randomBytes(4 * 1000000); byte[] bytes2 = new byte[bytes1.Length]; for (int i=0; i<bytes1.Length; i++) bytes1[i] = bytes2[i]; // unsafe version int start_t = System.Environment.TickCount; for (int r=1; r<=repeats; r++) { bool res = CompareUnsafe(bytes1, bytes2); if (r == repeats) Console.WriteLine("Result: " + res); } int end_t = System.Environment.TickCount; Console.WriteLine("CompareUnsafe: {0} ms.", (end_t-start_t)); // safe version start_t = System.Environment.TickCount; for (int r=1; r<=repeats; r++) { bool res = CompareSafe(bytes1, bytes2); if (r == repeats) Console.WriteLine("Result: " + res); } end_t = System.Environment.TickCount; Console.WriteLine("CompareSafe: {0} ms.", (end_t-start_t)); } public static bool CompareSafe(byte[] byteArray1, byte[] byteArray2) { if (byteArray1.Length != byteArray2.Length) return false; for (int i=0; i<byteArray1.Length; i++) if (byteArray1[i] != byteArray2[i]) return false; return true; } public unsafe static bool CompareUnsafe(byte[] byteArray1, byte[] byteArray2) { if (byteArray1.Length != byteArray2.Length) return false; if (byteArray1.Length % 4 != 0) throw new ArgumentException("Byte arrays have to be divisible by 4", "bytearray"); fixed (byte* bytes1 = &(byteArray1[0])) fixed (byte* bytes2 = &(byteArray2[0])) { int* ints1 = (int*)bytes1; int* ints2 = (int*)bytes2; int size = byteArray1.Length / 4; for (int i=0; i<size; i++) if (ints1[i] != ints2[i]) return false; } // all comparisons succeeded return true; } public static byte[] randomBytes(int size) { Random r = new Random(); byte[] bytes = new byte[size]; r.NextBytes(bytes); return bytes; } } }