void CopyImage()
{
//start stopwatch
Stopwatch sw = new Stopwatch();
sw.Start();
//copy-past data 10 times
for (int i = 0; i < 10; i++)
{
System.Runtime.InteropServices.Marshal.Copy(bmpd.Scan0, buffer, 0, buffer.Length);
}
//stop stopwatch
sw.Stop();
//show measured time
MessageBox.Show(sw.ElapsedTicks.ToString());
}
这就是标准快速拷贝方法。其实一点也不复杂,我们使用了知名的 System.Runtime.InteropServices.Marshal.Copy 方法。
以及又一个“中间方法(middle-method)”以用于快速拷贝逻辑:
void FastCopyImage()
{
FastMemCopy.FastMemoryCopy(bmpd.Scan0, bmpd2.Scan0, buffer.Length);
}
现在,来实现FastMemCopy类。下面是类的声明以及我们将会在类中使用到的一些类型:
internal static class FastMemCopy
{
[Flags]
private enum AllocationTypes : uint
{
Commit = 0x1000, Reserve = 0x2000,
Reset = 0x80000, LargePages = 0x20000000,
Physical = 0x400000, TopDown = 0x100000,
WriteWatch = 0x200000
}
[Flags]
private enum MemoryProtections : uint
{
Execute = 0x10, ExecuteRead = 0x20,
ExecuteReadWrite = 0x40, ExecuteWriteCopy = 0x80,
NoAccess = 0x01, ReadOnly = 0x02,
ReadWrite = 0x04, WriteCopy = 0x08,
GuartModifierflag = 0x100, NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400
}
[Flags]
private enum FreeTypes : uint
{
Decommit = 0x4000, Release = 0x8000
}
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
private unsafe delegate void FastMemCopyDelegate();
private static class NativeMethods
{
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr VirtualAlloc(
IntPtr lpAddress,
UIntPtr dwSize,
AllocationTypes flAllocationType,
MemoryProtections flProtect);
[DllImport("kernel32")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool VirtualFree(
IntPtr lpAddress,
uint dwSize,
FreeTypes flFreeType);
}
现在声明方法本身:
public static unsafe void FastMemoryCopy(IntPtr src, IntPtr dst, int nBytes)
{
if (IntPtr.Size == 4)
{
//we are in 32 bit mode
//allocate memory for our asm method
IntPtr p = NativeMethods.VirtualAlloc(
IntPtr.Zero,
new UIntPtr((uint)x86_FastMemCopy_New.Length),
AllocationTypes.Commit | AllocationTypes.Reserve,
MemoryProtections.ExecuteReadWrite);
try
{
//copy our method bytes to allocated memory
Marshal.Copy(x86_FastMemCopy_New, 0, p, x86_FastMemCopy_New.Length);
//make a delegate to our method
FastMemCopyDelegate _fastmemcopy =
(FastMemCopyDelegate)Marshal.GetDelegateForFunctionPointer(p,
typeof(FastMemCopyDelegate));
//offset to the end of our method block
p += x86_FastMemCopy_New.Length;
//store length param
p -= 8;
Marshal.Copy(BitConverter.GetBytes((long)nBytes), 0, p, 4);
//store destination address param
p -= 8;
Marshal.Copy(BitConverter.GetBytes((long)dst), 0, p, 4);
//store source address param
p -= 8;
Marshal.Copy(BitConverter.GetBytes((long)src), 0, p, 4);
//Start stopwatch
Stopwatch sw = new Stopwatch();
sw.Start();
//copy-past all data 10 times
for (int i = 0; i < 10; i++)
_fastmemcopy();
//stop stopwatch
sw.Stop();
//get message with measured time
System.Windows.Forms.MessageBox.Show(sw.ElapsedTicks.ToString());
}
catch (Exception ex)
{
//if any exception
System.Windows.Forms.MessageBox.Show(ex.Message);
}
finally
{
//free allocated memory
NativeMethods.VirtualFree(p, (uint)(x86_FastMemCopy_New.Length),
FreeTypes.Release);
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
}
}
else if (IntPtr.Size == 8)
{
throw new ApplicationException("x64 is not supported yet!");
}
}
汇编代码被表示成带注释的字节数组: