Skip to content

Instantly share code, notes, and snippets.

@20chan
Created September 21, 2017 05:43
Show Gist options
  • Save 20chan/d1e95529a4d39e836ea38cc8e0d29f9d to your computer and use it in GitHub Desktop.
Save 20chan/d1e95529a4d39e836ea38cc8e0d29f9d to your computer and use it in GitHub Desktop.
Execute expression using JIT, compiled expression, lambda in C#
using System;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
namespace AssemblySharp
{
public static class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool VirtualFree(IntPtr lpAddress, int dwSize, FreeType dwFreeType);
[Flags]
public enum FreeType
{
Decommit = 0x4000,
Release = 0x8000,
}
[Flags]
public enum AllocationType
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000
}
[Flags]
public enum MemoryProtection
{
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
GuardModifierflag = 0x100,
NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400
}
const int
PAGE_READWRITE = 0x40,
PROCESS_VM_OPERATION = 0x0008,
PROCESS_VM_READ = 0x0010,
PROCESS_VM_WRITE = 0x0020;
const uint PAGE_EXECUTE_READWRITE = 0x40;
delegate int IntDelegate();
static byte[] code = new byte[] {
// mov eax, 100
0xb8,
0x64, 0x00, 0x00, 0x00,
// add eax, 200
0x05,
0xc8, 0x00, 0x00, 0x00,
// ret
0xc3
};
static void PrintElapsedTime(string name, Func<int> func, int count = 1000000)
{
var now = DateTime.Now;
int total = 100000;
for (int i = 0; i < total; i++)
func();
var ellapsed = DateTime.Now - now;
Console.WriteLine($"{$"{total} times {name}".PadRight(40)} runned: {ellapsed.TotalMilliseconds}ms elapsed");
}
static void Main(string[] args)
{
var buffer = VirtualAlloc(IntPtr.Zero, (uint)code.Length, AllocationType.Commit, MemoryProtection.ExecuteReadWrite);
Marshal.Copy(code, 0, buffer, code.Length);
ptr = Marshal.GetDelegateForFunctionPointer<IntDelegate>(buffer);
Expression<Func<int, int>> exp = (i) => 200 + i;
compiled = exp.Compile();
for (int i = 0; i < 10; i++)
{
Console.WriteLine($"Phase {i}...");
PrintElapsedTime(nameof(AllocAndExec), AllocAndExec);
PrintElapsedTime(nameof(RunCompiledExpression), AllocAndExec);
PrintElapsedTime(nameof(RunLambda), RunLambda);
}
VirtualFree(buffer, 0, FreeType.Release);
Console.Read();
}
static IntDelegate ptr;
static int AllocAndExec()
{
return ptr();
}
static Func<int, int> compiled;
static int RunCompiledExpression()
{
return compiled(100);
}
static Func<int, int> lambd = (i) => i + 200;
static int RunLambda()
{
return lambd(100);
}
}
}
Phase 0...
100000 times AllocAndExec runned: 6.0247ms elapsed
100000 times RunCompiledExpression runned: 4.0367ms elapsed
100000 times RunLambda runned: 1.0021ms elapsed
Phase 1...
100000 times AllocAndExec runned: 4.0114ms elapsed
100000 times RunCompiledExpression runned: 4.9957ms elapsed
100000 times RunLambda runned: 0.9927ms elapsed
Phase 2...
100000 times AllocAndExec runned: 4.0099ms elapsed
100000 times RunCompiledExpression runned: 5.0131ms elapsed
100000 times RunLambda runned: 0ms elapsed
Phase 3...
100000 times AllocAndExec runned: 5.0796ms elapsed
100000 times RunCompiledExpression runned: 4.9474ms elapsed
100000 times RunLambda runned: 0ms elapsed
Phase 4...
100000 times AllocAndExec runned: 4.0103ms elapsed
100000 times RunCompiledExpression runned: 4.0359ms elapsed
100000 times RunLambda runned: 0.981ms elapsed
Phase 5...
100000 times AllocAndExec runned: 5.0105ms elapsed
100000 times RunCompiledExpression runned: 4.0084ms elapsed
100000 times RunLambda runned: 1.0032ms elapsed
Phase 6...
100000 times AllocAndExec runned: 4.0103ms elapsed
100000 times RunCompiledExpression runned: 5.0546ms elapsed
100000 times RunLambda runned: 1.0104ms elapsed
Phase 7...
100000 times AllocAndExec runned: 3.9616ms elapsed
100000 times RunCompiledExpression runned: 5.0603ms elapsed
100000 times RunLambda runned: 0ms elapsed
Phase 8...
100000 times AllocAndExec runned: 5.0614ms elapsed
100000 times RunCompiledExpression runned: 4.52ms elapsed
100000 times RunLambda runned: 0.4999ms elapsed
Phase 9...
100000 times AllocAndExec runned: 4.4657ms elapsed
100000 times RunCompiledExpression runned: 4.5619ms elapsed
100000 times RunLambda runned: 1.4435ms elapsed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment