namespace Microshaoft { using System; using System.Collections.Generic; using System.Runtime.InteropServices; class Program { static int[] bufsizes = { 256, 320 * 240 * 3, 1024 * 768 * 3 }; static int bufsize; const long duration = 10 * 1000 * 1000 * 10; // 10 seconds static void Main(string[] args) { foreach (var b in bufsizes) { bufsize = b; Console.WriteLine("allocs of size " + bufsize); newbyte(); marshallallochglobal(); marshallAllocCoTaskMem(); stackallocate(); sharedmem(); Console.WriteLine("memcopies of size " + bufsize); arraycopy(); BufferBlockCopy(); marshalcopy(); kernelcopy(); OwnMemCopyInt(); OwnMemCopyLong(); Console.WriteLine(); } Console.WriteLine("done"); Console.ReadLine(); } private static void BufferBlockCopy() { byte[] buf1 = new byte[bufsize]; byte[] buf2 = new byte[bufsize]; long start = DateTime.UtcNow.Ticks; int i = 0; while ((start + duration) > DateTime.UtcNow.Ticks) { Buffer.BlockCopy(buf1, 0, buf2, 0, bufsize); i++; } Console.WriteLine("Buffer.BlockCopy: " + i); } unsafe private static void marshalcopy() { byte[] buf1 = new byte[bufsize]; byte[] buf2 = new byte[bufsize]; long start = DateTime.UtcNow.Ticks; int i = 0; fixed (byte* b1 = &buf1[0]) fixed (byte* b2 = &buf2[0]) { IntPtr ab2 = new IntPtr(b2); while ((start + duration) > DateTime.UtcNow.Ticks) { Marshal.Copy(buf1, 0, ab2, buf1.Length); i++; } } Console.WriteLine("Marshal.Copy: " + i); } [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")] public unsafe static extern void CopyMemory(byte* Destination, byte* Source, [MarshalAs(UnmanagedType.U4)] uint Length); unsafe private static void kernelcopy() { Console.Write("Kernel32NativeMethods.CopyMemory: "); byte[] buf1 = new byte[bufsize]; byte[] buf2 = new byte[bufsize]; long start = DateTime.UtcNow.Ticks; int i = 0; fixed (byte* b1 = &buf1[0]) fixed (byte* b2 = &buf2[0]) { while ((start + duration) > DateTime.UtcNow.Ticks) { CopyMemory(b2, b1, (uint)buf1.Length); i++; } } Console.WriteLine(i); } unsafe private static void OwnMemCopyInt() { Console.Write("OwnMemCopyInt: "); byte[] buf1 = new byte[bufsize]; byte[] buf2 = new byte[bufsize]; long start = DateTime.UtcNow.Ticks; int i = 0; fixed (byte* b1 = &buf1[0]) fixed (byte* b2 = &buf2[0]) { IntPtr ab1 = new IntPtr(b1); IntPtr ab2 = new IntPtr(b2); while ((start + duration) > DateTime.UtcNow.Ticks) { MemCopyInt(ab1, ab2, buf1.Length); i++; } } Console.WriteLine(i); } unsafe private static void OwnMemCopyLong() { Console.Write("OwnMemCopyLong: "); byte[] buf1 = new byte[bufsize]; byte[] buf2 = new byte[bufsize]; long start = DateTime.UtcNow.Ticks; int i = 0; fixed (byte * b1 = &buf1[0]) fixed (byte * b2 = &buf2[0]) { IntPtr ab1 = new IntPtr(b1); IntPtr ab2 = new IntPtr(b2); while ((start + duration) > DateTime.UtcNow.Ticks) { MemCopyLong(ab1, ab2, buf1.Length); i++; } } Console.WriteLine(i); } private static void arraycopy() { Console.Write("Array.Copy: "); byte[] buf1 = new byte[bufsize]; byte[] buf2 = new byte[bufsize]; long start = DateTime.UtcNow.Ticks; int i = 0; while ((start + duration) > DateTime.UtcNow.Ticks) { Array.Copy(buf1, buf2, buf1.Length); i++; } Console.WriteLine(i); } private static void newbyte() { Console.Write("new byte[]: "); long start = DateTime.UtcNow.Ticks; int i = 0; while ((start + duration) > DateTime.UtcNow.Ticks) { byte[] buf = new byte[bufsize]; i++; } //GC.Collect(); Console.WriteLine(i); } private static void marshallallochglobal() { Console.Write("Marshal.AllocHGlobal: "); long start = DateTime.UtcNow.Ticks; int i = 0; while ((start + duration) > DateTime.UtcNow.Ticks) { IntPtr p = Marshal.AllocHGlobal(bufsize); Marshal.FreeHGlobal(p); i++; } Console.WriteLine(i); } private static void marshallAllocCoTaskMem() { Console.Write("Marshal.AllocCoTaskMem: "); long start = DateTime.UtcNow.Ticks; int i = 0; while ((start + duration) > DateTime.UtcNow.Ticks) { IntPtr p = Marshal.AllocCoTaskMem(bufsize); Marshal.FreeCoTaskMem(p); i++; } Console.WriteLine(i); } private static void sharedmem() { try { Console.Write("SharedMemory: "); long start = DateTime.UtcNow.Ticks; int i = 0; while ((start + duration) > DateTime.UtcNow.Ticks) { using (SharedMemory m = new SharedMemory("abc", bufsize, true)) { i++; } } Console.WriteLine(i); } catch (Exception ex) { Console.WriteLine(ex.Message); } } private static void stackallocate() { Console.Write("stackalloc: "); long start = DateTime.UtcNow.Ticks; int i = 0; while ((start + duration) > DateTime.UtcNow.Ticks) { stack(); i++; } Console.WriteLine(i); } unsafe static void stack() { byte* buf = stackalloc byte[bufsize]; } static public unsafe void MemCopyInt(IntPtr pSource, IntPtr pDest, int Len) { unchecked { int count = Len / Marshal.SizeOf(typeof(int)); int rest = Len % count; int* ps = (int*) pSource.ToPointer(), pd = (int*) pDest.ToPointer(); // Loop over the cnt in blocks of 4 bytes, copying an integer (4 bytes) at a time: for (int n = 0; n < count; n++) { * pd++ = * ps++; } // Complete the copy by moving any bytes that weren't moved in blocks of 4: if (rest > 0) { byte * ps1 = (byte*)ps; byte * pd1 = (byte*)pd; for (int n = 0; n < rest; n++) { *pd1++ = *ps1++; } } } } static public unsafe void MemCopyLong(IntPtr pSource, IntPtr pDest, int Len) { unchecked { int count = Len / Marshal.SizeOf(typeof(long)); int rest = Len % count; long* ps = (long*)pSource.ToPointer(), pd = (long*)pDest.ToPointer(); // Loop over the cnt in blocks of n bytes, copying an long (n bytes) at a time: for (int n = 0; n < count; n++) { *pd++ = *ps++; } // Complete the copy by moving any bytes that weren't moved in blocks of n: if (rest > 0) { byte* ps1 = (byte*) ps; byte* pd1 = (byte*) pd; for (int n = 0; n < rest; n++) { * pd1 = * ps1; pd1++; ps1++; } } } } } unsafe public class SharedMemory : IDisposable { [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpFileMappingAttributes, PageProtection flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool CloseHandle(IntPtr hObject); [DllImport("kernel32.dll", SetLastError = true)] static extern bool UnmapViewOfFile(IntPtr lpBaseAddress); [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, IntPtr dwNumberOfBytesToMap); [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr OpenFileMapping(uint dwDesiredAccess, bool bInheritHandle, string lpName); const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000; const UInt32 SECTION_QUERY = 0x0001; const UInt32 SECTION_MAP_WRITE = 0x0002; const UInt32 SECTION_MAP_READ = 0x0004; const UInt32 SECTION_MAP_EXECUTE = 0x0008; const UInt32 SECTION_EXTEND_SIZE = 0x0010; const UInt32 SECTION_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_EXTEND_SIZE); const UInt32 FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS; [Flags] enum PageProtection : uint { NoAccess = 0x01, Readonly = 0x02, ReadWrite = 0x04, WriteCopy = 0x08, Execute = 0x10, ExecuteRead = 0x20, ExecuteReadWrite = 0x40, ExecuteWriteCopy = 0x80, Guard = 0x100, NoCache = 0x200, WriteCombine = 0x400, } private IntPtr hHandle; public void * Buffer { get; private set; } public int Length { get; private set; } public SharedMemory(string name, int size, bool create) { if (create) { Create(name, size); } else { Attach(name); } } ~SharedMemory() { Detach(); } private void Create(string SharedMemoryName, int NumBytes) { hHandle = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, PageProtection.ReadWrite, 0, (uint)NumBytes, SharedMemoryName); if (IntPtr.Zero == hHandle) { throw new InvalidOperationException(String.Format("Failed to create FileMapping with given name '{0}'.", SharedMemoryName)); } Buffer = MapViewOfFile(hHandle, FILE_MAP_ALL_ACCESS, 0, 0, IntPtr.Zero).ToPointer(); Length = NumBytes; } private void Attach(string SharedMemoryName) { hHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, SharedMemoryName); if (IntPtr.Zero == hHandle) { throw new InvalidOperationException(String.Format("Failed to open FileMapping with given name '{0}'.", SharedMemoryName)); } Buffer = MapViewOfFile(hHandle, FILE_MAP_ALL_ACCESS, 0, 0, IntPtr.Zero).ToPointer(); } private void Detach() { if (IntPtr.Zero != hHandle) { UnmapViewOfFile(new IntPtr(Buffer)); CloseHandle(hHandle); //fair to leak if can't close hHandle = IntPtr.Zero; } Buffer = IntPtr.Zero.ToPointer(); } #region IDisposable Members public void Dispose() { Detach(); } #endregion } }