Skip to content

Instantly share code, notes, and snippets.

@harujoh
Created July 24, 2019 09:05
Show Gist options
  • Save harujoh/628e84de36f0d430ceabdcdc5a8be591 to your computer and use it in GitHub Desktop.
Save harujoh/628e84de36f0d430ceabdcdc5a8be591 to your computer and use it in GitHub Desktop.
ネイティブからネイティブへのコピー速度比較
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace ConsoleApp75
{
class Program
{
[DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")]
private static extern void CopyMemory(IntPtr Destination, IntPtr Source, [MarshalAs(UnmanagedType.U4)] int Length);
static unsafe void Main(string[] args)
{
const int size = 1073741824;
const int count = 100;
IntPtr ptr = Marshal.AllocCoTaskMem(size);
IntPtr ptr2 = Marshal.AllocCoTaskMem(size);
byte[] bytes = Enumerable.Repeat((byte)128, size).ToArray();
using (MemoryStream streamSrc = new MemoryStream(bytes))
using (UnmanagedMemoryStream streamDst = new UnmanagedMemoryStream((byte*)ptr, size, size, FileAccess.Write))
streamSrc.CopyTo(streamDst);
Console.WriteLine("Performing tests on copying {0} megabytes of memory.", size / (double)1024 / 1024);
GC.Collect();
Stopwatch watch = new Stopwatch();
// make sure methods are JIT’d (they probably are, since there
// should be native images of the standard library, but just to be safe..)
watch.Reset();
watch.Start();
watch.Stop();
double averageTime = 0;
{
watch.Reset();
watch.Start();
{
using (UnmanagedMemoryStream streamSrc = new UnmanagedMemoryStream((byte*)ptr, size, size, FileAccess.Read))
using (UnmanagedMemoryStream streamDst = new UnmanagedMemoryStream((byte*)ptr2, size, size, FileAccess.Write))
{
for (int i = 0; i < count; i++)
{
streamSrc.Position = 0;
streamDst.Position = 0;
streamSrc.CopyTo(streamDst);
}
}
}
watch.Stop();
averageTime = watch.ElapsedMilliseconds / (double)count;
Console.WriteLine("Average time for Stream is {0} ms.", averageTime);
}
{
watch.Reset();
watch.Start();
for (int i = 0; i < count; i++)
{
CopyMemory(ptr2, ptr, size);
}
watch.Stop();
averageTime = watch.ElapsedMilliseconds / (double)count;
Console.WriteLine("Average time for API is {0} ms.", averageTime);
}
{
watch.Reset();
watch.Start();
for (int i = 0; i < count; i++)
{
Buffer.MemoryCopy((void*)ptr, (void*)ptr2, size, size);
}
watch.Stop();
averageTime = watch.ElapsedMilliseconds / (double)count;
Console.WriteLine("Average time for Buffer is {0} ms.", averageTime);
}
{
watch.Reset();
watch.Start();
int* src = (int*)ptr;
int* dest = (int*)ptr2;
for (int j = 0; j < count; j++)
{
for (int i = 0; i < size / sizeof(int); i++)
{
dest[i] = src[i];
}
}
watch.Stop();
averageTime = watch.ElapsedMilliseconds / (double)count;
Console.WriteLine("Average time int copy is {0} ms.", averageTime);
}
Marshal.FreeHGlobal(ptr);
Marshal.FreeHGlobal(ptr2);
Console.WriteLine("Done.");
Console.ReadKey();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment