Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,7 @@ _Pvt_Extensions

# FAKE - F# Make
.fake/
/src/DotNetCross.Memory.Copies.Benchmarks2/chart.json
/I5-4590.xlsx
/I7-3610QM.xlsx
/src/DotNetCross.Memory.Copies.Benchmarks2/chart0_8400.json
12 changes: 6 additions & 6 deletions DotNetCross.Memory.Copies.sln
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetCross.Memory.Copies.Benchmarks", "src\DotNetCross.Memory.Copies.Benchmarks\DotNetCross.Memory.Copies.Benchmarks.csproj", "{DF33082A-C7BE-4305-BCAD-159D667C9420}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "DotNetCross.Memory.Copies.Benchmarks2", "src\DotNetCross.Memory.Copies.Benchmarks2\DotNetCross.Memory.Copies.Benchmarks2.xproj", "{9396CFEF-F925-4202-98E7-1F0759DF0C5B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DF33082A-C7BE-4305-BCAD-159D667C9420}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DF33082A-C7BE-4305-BCAD-159D667C9420}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DF33082A-C7BE-4305-BCAD-159D667C9420}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DF33082A-C7BE-4305-BCAD-159D667C9420}.Release|Any CPU.Build.0 = Release|Any CPU
{9396CFEF-F925-4202-98E7-1F0759DF0C5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9396CFEF-F925-4202-98E7-1F0759DF0C5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9396CFEF-F925-4202-98E7-1F0759DF0C5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9396CFEF-F925-4202-98E7-1F0759DF0C5B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>9396cfef-f925-4202-98e7-1f0759df0c5b</ProjectGuid>
<RootNamespace>DotNetCross.Memory.Copies.Benchmarks2</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
8 changes: 8 additions & 0 deletions src/DotNetCross.Memory.Copies.Benchmarks2/GoogleChart/C.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace DotNetCross.Memory.Copies.Benchmarks2
{
public class C
{
public object v { get; set; }
public string f { get; set; }
}
}
9 changes: 9 additions & 0 deletions src/DotNetCross.Memory.Copies.Benchmarks2/GoogleChart/Col.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace DotNetCross.Memory.Copies.Benchmarks2
{
public class Col
{
public string id { get; set; }
public string label { get; set; }
public string type { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace DotNetCross.Memory.Copies.Benchmarks2
{
public class GoogleChart
{
public Col[] cols { get; set; }
public Row[] rows { get; set; }
}
}
7 changes: 7 additions & 0 deletions src/DotNetCross.Memory.Copies.Benchmarks2/GoogleChart/Row.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace DotNetCross.Memory.Copies.Benchmarks2
{
public class Row
{
public C[] c { get; set; }
}
}
105 changes: 105 additions & 0 deletions src/DotNetCross.Memory.Copies.Benchmarks2/Memcopy/AndermanMovsb.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace DotNetCross.Memory.Copies.Benchmarks2
{
//Used this code only for testing. This code works only on 64bit
public static class AndermanMovsb
{
private const uint PAGE_READWRITE = 0x04;
private const uint PAGE_EXECUTE = 0x10;
private const uint PAGE_EXECUTE_READWRITE = 0x40;
private const uint MEM_COMMIT = 0x1000;
private const uint MEM_RELEASE = 0x8000;

[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool VirtualProtect(IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, out uint lpflOldProtect);

[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
private static extern IntPtr VirtualAlloc(IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, uint flProtect);

[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool VirtualFree(IntPtr lpAddress, IntPtr dwSize, uint dwFreeType);

public delegate int MyMoveSb(ulong RCX, ulong RDX, ulong R8);

public static MyMoveSb movsb;
public static MyMoveSb pinvoke;

static AndermanMovsb()
{
//RAX�=�0000008377040000 RBX�=�0000000000000005 RCX�=�0000000000000004 RDX�=�0000000000000005 RSI�=�0000008300018350 RDI�=�0000000000000004 R8 �=�0000000000000006 R9 �=�000007F9C2460F84 R10�=�0000000000000000 R11�=�0000000000000000 R12�=�00000083754BDF70 R13�=�0000000000000004 R14�=�0000000000000006 R15�=�000000837555A4D0 RIP�=�0000008377040000 RSP�=�00000083754BDDF8 RBP�=�00000083754BDEA0 EFL�=�00000246
/*
0: 49 89 fb mov r11,rdi
3: 49 89 f2 mov r10,rsi
6: 48 89 ce mov rsi,rcx
9: 48 89 d7 mov rdi,rdx
c: 4c 89 c1 mov rcx,r8
f: f3 a4 rep movs BYTE PTR es:[rdi],BYTE PTR ds:[rsi]
11: 4c 89 d6 mov rsi,r10
14: 4c 89 df mov rdi,r11
17: c3 ret
*/
byte[] assemblyCode = { 0x49, 0x89, 0xFB, 0x49, 0x89, 0xF2, 0x48, 0x89, 0xCE, 0x48, 0x89, 0xD7, 0x4C, 0x89, 0xC1, 0xF3, 0xA4, 0x4C, 0x89, 0xD6, 0x4C, 0x89, 0xDF, 0xC3 };
byte[] assemblyCode2 = { 0xC3 };


// We need to push the code bytes into a native buffer

var bufPtr = IntPtr.Zero;

try
{
// Put the sourcecode in a native buffer
bufPtr = VirtualAlloc(IntPtr.Zero, (IntPtr)4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

Marshal.Copy(assemblyCode, 0, bufPtr, assemblyCode.Length);
Marshal.Copy(assemblyCode2, 0, bufPtr+64, assemblyCode2.Length);

uint oldProtection;
var result = VirtualProtect(bufPtr, (IntPtr)assemblyCode.Length, PAGE_EXECUTE, out oldProtection);

if (!result)
{
throw new Win32Exception();
}
movsb = Marshal.GetDelegateForFunctionPointer<MyMoveSb>(bufPtr);
pinvoke = Marshal.GetDelegateForFunctionPointer<MyMoveSb>(bufPtr+64);
bufPtr = IntPtr.Zero;
}
finally
{
// Free the native buffer
if (bufPtr != IntPtr.Zero)
{
var result = VirtualFree(bufPtr, IntPtr.Zero, MEM_RELEASE);
if (!result)
{
throw new Win32Exception();
}
}
}
}


public static unsafe void Memmove(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
{
if (count == 0) return;
if (src == null || dst == null) throw new ArgumentNullException(nameof(src));
if (srcOffset + count > src.Length) throw new ArgumentException(nameof(src));
if (count < 0 || srcOffset < 0 || dstOffset < 0) throw new ArgumentOutOfRangeException(nameof(count));
if (dstOffset + count > dst.Length) throw new ArgumentException(nameof(dst));

fixed (byte* pSrcOrigin = &src[srcOffset])
fixed (byte* pDstOrigin = &dst[dstOffset])
{
var pSrc = pSrcOrigin;
var pDst = pDstOrigin;
var result1 = movsb((ulong)pSrc, (ulong)pDst,(ulong)count);
}
}
}
}
104 changes: 104 additions & 0 deletions src/DotNetCross.Memory.Copies.Benchmarks2/Memcopy/AndermanOptimized.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using System;
using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;

namespace DotNetCross.Memory.Copies.Benchmarks2
{
public static class AndermanOptimized
{

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void Memmove(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
{
const int alignment = 0x10;
const int mask = alignment - 1;

if (count == 0) return;
if (src == null || dst == null) throw new ArgumentNullException(nameof(src));
if (srcOffset + count > src.Length) throw new ArgumentException(nameof(src));
if (count < 0 || srcOffset < 0 || dstOffset < 0) throw new ArgumentOutOfRangeException(nameof(count));
if (dstOffset + count > dst.Length) throw new ArgumentException(nameof(dst));

fixed (byte* pSrcOrigin = &src[srcOffset])
fixed (byte* pDstOrigin = &dst[dstOffset])
{
var pSrc = pSrcOrigin;
var pDst = pDstOrigin;
if (count < 16)
{
if (count < 8)
{
if (count < 4)
{
if (count < 2)
{
*(pDst + 0) = *(pSrc + 0);
}
else
{
*(short*)pDst = *(short*)pSrc;
*(short*)(pDst + (count & 0xf) - 2) = *(short*)(pSrc + (count & 0xf) - 2);
}
}
else
{
*(int*)pDst = *(int*)pSrc;
*(int*)(pDst + (count & 0xf) - 4) = *(int*)(pSrc + (count & 0xf) - 4);
}

}
else
{
*(long*)pDst = *(long*)pSrc;
*(long*)(pDst + (count & 0xf) - 8) = *(long*)(pSrc + (count & 0xf) - 8);
}
return;
}

pSrc -= (long)pDst;
Unsafe.Write(pDst, Unsafe.Read<Vector<byte>>(pSrc + (long)pDst));

var offset = (int)((ulong)pDst & mask);
count += offset - alignment;
pDst += alignment - offset;

while (count >= 4 * Vector<byte>.Count)
{
var x1 = Unsafe.Read<Vector<byte>>(pSrc + (long)pDst);
var x2 = Unsafe.Read<Vector<byte>>(pSrc + (long)pDst + Vector<byte>.Count);
count -= 4 * Vector<byte>.Count;
Unsafe.Write(pDst, x1);
Unsafe.Write(pDst + Vector<byte>.Count, x2);
pDst += 4 * Vector<byte>.Count;
x1 = Unsafe.Read<Vector<byte>>(pSrc + (long)pDst - 2 * Vector<byte>.Count);
x2 = Unsafe.Read<Vector<byte>>(pSrc + (long)pDst - Vector<byte>.Count);
Unsafe.Write(pDst - 2 * Vector<byte>.Count, x1);
Unsafe.Write(pDst - Vector<byte>.Count, x2);
}
while (count >= 2 * Vector<byte>.Count)
{
var x1 = Unsafe.Read<Vector<byte>>(pSrc + (long)pDst);
var x2 = Unsafe.Read<Vector<byte>>(pSrc + (long)pDst + Vector<byte>.Count);
count -= 2 * Vector<byte>.Count;
Unsafe.Write(pDst, x1);
Unsafe.Write(pDst + Vector<byte>.Count, x2);
pDst += 2 * Vector<byte>.Count;
}
while (count >= 1 * Vector<byte>.Count)
{
var x1 = Unsafe.Read<Vector<byte>>(pSrc + (long)pDst);
count -= Vector<byte>.Count;
Unsafe.Write(pDst, x1);
pDst += Vector<byte>.Count;
}
if (count > 0)
{
pDst += count - Vector<byte>.Count;
Unsafe.Write(pDst, Unsafe.Read<Vector<byte>>(pSrc + (long) pDst));
}
}
}
}

}
Loading