Friday, 7 July 2017

c# - How to create a new object instance from a Type

Compiled expression is best way! (for performance to repeatedly create instance in runtime).




static readonly Func YCreator = Expression.Lambda>(
Expression.New(typeof(Y).GetConstructor(Type.EmptyTypes))
).Compile();

X x = YCreator();


Statistics (2012):



    Iterations: 5000000

00:00:00.8481762, Activator.CreateInstance(string, string)
00:00:00.8416930, Activator.CreateInstance(type)
00:00:06.6236752, ConstructorInfo.Invoke
00:00:00.1776255, Compiled expression
00:00:00.0462197, new


Statistics (2015, .net 4.5, x64):



    Iterations: 5000000

00:00:00.2659981, Activator.CreateInstance(string, string)
00:00:00.2603770, Activator.CreateInstance(type)
00:00:00.7478936, ConstructorInfo.Invoke
00:00:00.0700757, Compiled expression
00:00:00.0286710, new


Statistics (2015, .net 4.5, x86):



    Iterations: 5000000

00:00:00.3541501, Activator.CreateInstance(string, string)
00:00:00.3686861, Activator.CreateInstance(type)
00:00:00.9492354, ConstructorInfo.Invoke
00:00:00.0719072, Compiled expression
00:00:00.0229387, new


Statistics (2017, LINQPad 5.22.02/x64/.NET 4.6):



    Iterations: 5000000

No args
00:00:00.3897563, Activator.CreateInstance(string assemblyName, string typeName)
00:00:00.3500748, Activator.CreateInstance(Type type)
00:00:01.0100714, ConstructorInfo.Invoke
00:00:00.1375767, Compiled expression
00:00:00.1337920, Compiled expression (type)
00:00:00.0593664, new
Single arg
00:00:03.9300630, Activator.CreateInstance(Type type)
00:00:01.3881770, ConstructorInfo.Invoke

00:00:00.1425534, Compiled expression
00:00:00.0717409, new


Statistics (2019, x64/.NET 4.8):



Iterations: 5000000
No args
00:00:00.3287835, Activator.CreateInstance(string assemblyName, string typeName)
00:00:00.3122015, Activator.CreateInstance(Type type)

00:00:00.8035712, ConstructorInfo.Invoke
00:00:00.0692854, Compiled expression
00:00:00.0662223, Compiled expression (type)
00:00:00.0337862, new
Single arg
00:00:03.8081959, Activator.CreateInstance(Type type)
00:00:01.2507642, ConstructorInfo.Invoke
00:00:00.0671756, Compiled expression
00:00:00.0301489, new



Statistics (2019, x64/.NET Core 3.0):



Iterations: 5000000
No args
00:00:00.3226895, Activator.CreateInstance(string assemblyName, string typeName)
00:00:00.2786803, Activator.CreateInstance(Type type)
00:00:00.6183554, ConstructorInfo.Invoke
00:00:00.0483217, Compiled expression
00:00:00.0485119, Compiled expression (type)

00:00:00.0434534, new
Single arg
00:00:03.4389401, Activator.CreateInstance(Type type)
00:00:01.0803609, ConstructorInfo.Invoke
00:00:00.0554756, Compiled expression
00:00:00.0462232, new


Full code:




static X CreateY_New()
{
return new Y();
}

static X CreateY_New_Arg(int z)
{
return new Y(z);
}


static X CreateY_CreateInstance()
{
return (X)Activator.CreateInstance(typeof(Y));
}

static X CreateY_CreateInstance_String()
{
return (X)Activator.CreateInstance("Program", "Y").Unwrap();
}


static X CreateY_CreateInstance_Arg(int z)
{
return (X)Activator.CreateInstance(typeof(Y), new object[] { z, });
}

private static readonly System.Reflection.ConstructorInfo YConstructor =
typeof(Y).GetConstructor(Type.EmptyTypes);
private static readonly object[] Empty = new object[] { };
static X CreateY_Invoke()
{

return (X)YConstructor.Invoke(Empty);
}

private static readonly System.Reflection.ConstructorInfo YConstructor_Arg =
typeof(Y).GetConstructor(new[] { typeof(int), });
static X CreateY_Invoke_Arg(int z)
{
return (X)YConstructor_Arg.Invoke(new object[] { z, });
}


private static readonly Func YCreator = Expression.Lambda>(
Expression.New(typeof(Y).GetConstructor(Type.EmptyTypes))
).Compile();
static X CreateY_CompiledExpression()
{
return YCreator();
}

private static readonly Func YCreator_Type = Expression.Lambda>(
Expression.New(typeof(Y))

).Compile();
static X CreateY_CompiledExpression_Type()
{
return YCreator_Type();
}

private static readonly ParameterExpression YCreator_Arg_Param = Expression.Parameter(typeof(int), "z");
private static readonly Func YCreator_Arg = Expression.Lambda>(
Expression.New(typeof(Y).GetConstructor(new[] { typeof(int), }), new[] { YCreator_Arg_Param, }),
YCreator_Arg_Param

).Compile();
static X CreateY_CompiledExpression_Arg(int z)
{
return YCreator_Arg(z);
}

static void Main(string[] args)
{
const int iterations = 5000000;


Console.WriteLine("Iterations: {0}", iterations);

Console.WriteLine("No args");
foreach (var creatorInfo in new[]
{
new {Name = "Activator.CreateInstance(string assemblyName, string typeName)", Creator = (Func)CreateY_CreateInstance},
new {Name = "Activator.CreateInstance(Type type)", Creator = (Func)CreateY_CreateInstance},
new {Name = "ConstructorInfo.Invoke", Creator = (Func)CreateY_Invoke},
new {Name = "Compiled expression", Creator = (Func)CreateY_CompiledExpression},
new {Name = "Compiled expression (type)", Creator = (Func)CreateY_CompiledExpression_Type},

new {Name = "new", Creator = (Func)CreateY_New},
})
{
var creator = creatorInfo.Creator;

var sum = 0;
for (var i = 0; i < 1000; i++)
sum += creator().Z;

var stopwatch = new Stopwatch();

stopwatch.Start();
for (var i = 0; i < iterations; ++i)
{
var x = creator();
sum += x.Z;
}
stopwatch.Stop();
Console.WriteLine("{0}, {1}", stopwatch.Elapsed, creatorInfo.Name);
}


Console.WriteLine("Single arg");
foreach (var creatorInfo in new[]
{
new {Name = "Activator.CreateInstance(Type type)", Creator = (Func)CreateY_CreateInstance_Arg},
new {Name = "ConstructorInfo.Invoke", Creator = (Func)CreateY_Invoke_Arg},
new {Name = "Compiled expression", Creator = (Func)CreateY_CompiledExpression_Arg},
new {Name = "new", Creator = (Func)CreateY_New_Arg},
})
{
var creator = creatorInfo.Creator;


var sum = 0;
for (var i = 0; i < 1000; i++)
sum += creator(i).Z;

var stopwatch = new Stopwatch();
stopwatch.Start();
for (var i = 0; i < iterations; ++i)
{
var x = creator(i);

sum += x.Z;
}
stopwatch.Stop();
Console.WriteLine("{0}, {1}", stopwatch.Elapsed, creatorInfo.Name);
}
}

public class X
{
public X() { }

public X(int z) { this.Z = z; }
public int Z;
}

public class Y : X
{
public Y() {}
public Y(int z) : base(z) {}
}

No comments:

Post a Comment

casting - Why wasn&#39;t Tobey Maguire in The Amazing Spider-Man? - Movies &amp; TV

In the Spider-Man franchise, Tobey Maguire is an outstanding performer as a Spider-Man and also reprised his role in the sequels Spider-Man...