 |
|
|
|
| Author |
Message |
not_a_commie
Joined: 11 Aug 2007 Posts: 1
|
Posted: Fri Sep 14, 2007 2:56 pm Post subject: fastest way to construct a struct from a type? |
|
|
It seems that the only way to construct a struct from a type is to use
Activator.CreateInstance. Is that true? Can anyone improve
(performance-wise) upon this function below:
///
/// Create an object of the given type
/// A default constructor is required to be successful.
/// A failure will return null.
///
/// The type of the object to create.
/// Arguments for the desired
constructor.
public static object CreateObject(Type type, params object[]
constructorParams)
{
if (type == null)
throw new ArgumentNullException("Type");
try
{
if (type.IsArray)
{
int[] dimensions = new int[constructorParams.Length];
for (int i = 0; i < constructorParams.Length; i++)
dimensions[i] = (int)constructorParams[i];
return Array.CreateInstance(type.GetElementType(), dimensions);
}
else if (type == typeof(string))
{
return "";
}
else
{
// the easy and slow way:
//return Activator.CreateInstance(type, constructorParams);
if (constructorParams == null || constructorParams.Length <= 0)
{
ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
if (ci == null) // stupid structs and their default
constructors....
return Activator.CreateInstance(type); // it does cache the most
recent 16 types
DynamicMethod dm = new DynamicMethod("MyCtor", type,
Type.EmptyTypes, typeof(ClassFactory).Module, true);
ILGenerator ilgen = dm.GetILGenerator();
ilgen.Emit(OpCodes.Nop);
ilgen.Emit(OpCodes.Newobj, ci);
ilgen.Emit(OpCodes.Ret);
return ((CtorDelegate)dm.CreateDelegate(typeof(CtorDelegate)))();
// we could cache these delegates with a type lookup
// but preparation time is really very minimal
// see here: http://blogs.msdn.com/haibo_luo/archive/2005/11/17/494009.aspx
// and here: http://blogs.msdn.com/haibo_luo/articles/494008.aspx
}
else
{
Type[] constructorTypes = new Type[constructorParams.Length];
for (int i = 0; i < constructorParams.Length; i++)
constructorTypes[i] = constructorParams.GetType();
// DynamicMethod is not quite as fast in this case
// where we don't have a delegate matching the function
// This should be really rare in deserialization, though
ConstructorInfo ci = type.GetConstructor(constructorTypes);
if (ci == null) // stupid structs and their default
constructors....
return Activator.CreateInstance(type); // it does cache the most
recent 16 types
return ci.Invoke(constructorParams);
}
// another thing we could do is cache IClonables and just return
cloned copies in that case
}
}
catch (Exception e)
{
if (e.InnerException is LicenseException)
throw e.InnerException;
throw new ClassFactoryException("Error constructing object " +
type.Name, e);
}
}
private delegate object CtorDelegate();
Archived from group: microsoft>public>dotnet>languages>csharp |
|
| Back to top |
|
 |
Nicholas Paldino [.NET/C#
Joined: 08 Aug 2007 Posts: 71
|
Posted: Thu Dec 13, 2007 4:52 pm Post subject: Re: fastest way to construct a struct from a type? |
|
|
Curious, can you create a generic version of this and then use
default(T) (where T is the type parameter)? If you can, then that might be
the easiest, and most maintainable solution.
Of course, if you are loading the type information (loading the name of
the type, that is) and don't have access to it at compile time, it won't
help.
Other than that, you can probably still go down the dynamic code
generation route. I would recommend an interface which would return an
object, and you would then create dynamic types implementing that interface.
It would imply create an instance of your structure for you. Then, you
would have a dictionary keyed by type which would return this interface
implementation, and then just call the method to return a new instance of
the value type.
--
- Nicholas Paldino [.NET/C# MVP]
- mvp@spam.guard.caspershouse.com
"not_a_commie" wrote in message @o80g2000hse.googlegroups.com...
> It seems that the only way to construct a struct from a type is to use
> Activator.CreateInstance. Is that true? Can anyone improve
> (performance-wise) upon this function below:
>
>
> ///
> /// Create an object of the given type
> /// A default constructor is required to be successful.
> /// A failure will return null.
> ///
> /// The type of the object to create.
> /// Arguments for the desired
> constructor.
> public static object CreateObject(Type type, params object[]
> constructorParams)
> {
> if (type == null)
> throw new ArgumentNullException("Type");
> try
> {
> if (type.IsArray)
> {
> int[] dimensions = new int[constructorParams.Length];
> for (int i = 0; i < constructorParams.Length; i++)
> dimensions[i] = (int)constructorParams[i];
> return Array.CreateInstance(type.GetElementType(), dimensions);
> }
> else if (type == typeof(string))
> {
> return "";
> }
> else
> {
> // the easy and slow way:
> //return Activator.CreateInstance(type, constructorParams);
> if (constructorParams == null || constructorParams.Length <= 0)
> {
> ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
> if (ci == null) // stupid structs and their default
> constructors....
> return Activator.CreateInstance(type); // it does cache the most
> recent 16 types
>
> DynamicMethod dm = new DynamicMethod("MyCtor", type,
> Type.EmptyTypes, typeof(ClassFactory).Module, true);
> ILGenerator ilgen = dm.GetILGenerator();
> ilgen.Emit(OpCodes.Nop);
> ilgen.Emit(OpCodes.Newobj, ci);
> ilgen.Emit(OpCodes.Ret);
> return ((CtorDelegate)dm.CreateDelegate(typeof(CtorDelegate)))();
> // we could cache these delegates with a type lookup
> // but preparation time is really very minimal
> // see here:
> http://blogs.msdn.com/haibo_luo/archive/2005/11/17/494009.aspx
> // and here: http://blogs.msdn.com/haibo_luo/articles/494008.aspx
> }
> else
> {
> Type[] constructorTypes = new Type[constructorParams.Length];
> for (int i = 0; i < constructorParams.Length; i++)
> constructorTypes[i] = constructorParams.GetType();
> // DynamicMethod is not quite as fast in this case
> // where we don't have a delegate matching the function
> // This should be really rare in deserialization, though
> ConstructorInfo ci = type.GetConstructor(constructorTypes);
> if (ci == null) // stupid structs and their default
> constructors....
> return Activator.CreateInstance(type); // it does cache the most
> recent 16 types
>
> return ci.Invoke(constructorParams);
> }
> // another thing we could do is cache IClonables and just return
> cloned copies in that case
> }
> }
> catch (Exception e)
> {
> if (e.InnerException is LicenseException)
> throw e.InnerException;
> throw new ClassFactoryException("Error constructing object " +
> type.Name, e);
> }
> }
> private delegate object CtorDelegate();
> |
|
| Back to top |
|
 |
Ben Voigt [C++ MVP]
Joined: 08 Aug 2007 Posts: 189
|
Posted: Thu Dec 13, 2007 6:19 pm Post subject: Re: fastest way to construct a struct from a type? |
|
|
"Nicholas Paldino [.NET/C# MVP]" wrote in
message @microsoft.com...
> Curious, can you create a generic version of this and then use
> default(T) (where T is the type parameter)? If you can, then that might
> be the easiest, and most maintainable solution.
>
> Of course, if you are loading the type information (loading the name of
> the type, that is) and don't have access to it at compile time, it won't
> help.
>
> Other than that, you can probably still go down the dynamic code
> generation route. I would recommend an interface which would return an
No dynamic code generation needed (well the JIT will be generating code, but
it always does that).
> object, and you would then create dynamic types implementing that
> interface. It would imply create an instance of your structure for you.
> Then, you would have a dictionary keyed by type which would return this
> interface implementation, and then just call the method to return a new
> instance of the value type.
For the zero (or fixed) parameter case, construct a delegate from the
ConstructorInfo and store those in a dictionary. Then creating multiples of
the same type is as cheap as a delegate call.
See http://msdn2.microsoft.com/en-us/library/53cz7sc6.aspx
>
>
> --
> - Nicholas Paldino [.NET/C# MVP]
> - mvp@spam.guard.caspershouse.com
>
> "not_a_commie" wrote in message
> @o80g2000hse.googlegroups.com...
>> It seems that the only way to construct a struct from a type is to use
>> Activator.CreateInstance. Is that true? Can anyone improve
>> (performance-wise) upon this function below:
>>
>>
>> ///
>> /// Create an object of the given type
>> /// A default constructor is required to be successful.
>> /// A failure will return null.
>> ///
>> /// The type of the object to create.
>> /// Arguments for the desired
>> constructor.
>> public static object CreateObject(Type type, params object[]
>> constructorParams)
>> {
>> if (type == null)
>> throw new ArgumentNullException("Type");
>> try
>> {
>> if (type.IsArray)
>> {
>> int[] dimensions = new int[constructorParams.Length];
>> for (int i = 0; i < constructorParams.Length; i++)
>> dimensions[i] = (int)constructorParams[i];
>> return Array.CreateInstance(type.GetElementType(), dimensions);
>> }
>> else if (type == typeof(string))
>> {
>> return "";
>> }
>> else
>> {
>> // the easy and slow way:
>> //return Activator.CreateInstance(type, constructorParams);
>> if (constructorParams == null || constructorParams.Length <= 0)
>> {
>> ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
>> if (ci == null) // stupid structs and their default
>> constructors....
>> return Activator.CreateInstance(type); // it does cache the most
>> recent 16 types
>>
>> DynamicMethod dm = new DynamicMethod("MyCtor", type,
>> Type.EmptyTypes, typeof(ClassFactory).Module, true);
>> ILGenerator ilgen = dm.GetILGenerator();
>> ilgen.Emit(OpCodes.Nop);
>> ilgen.Emit(OpCodes.Newobj, ci);
>> ilgen.Emit(OpCodes.Ret);
>> return ((CtorDelegate)dm.CreateDelegate(typeof(CtorDelegate)))();
>> // we could cache these delegates with a type lookup
>> // but preparation time is really very minimal
>> // see here:
>> http://blogs.msdn.com/haibo_luo/archive/2005/11/17/494009.aspx
>> // and here: http://blogs.msdn.com/haibo_luo/articles/494008.aspx
>> }
>> else
>> {
>> Type[] constructorTypes = new Type[constructorParams.Length];
>> for (int i = 0; i < constructorParams.Length; i++)
>> constructorTypes[i] = constructorParams.GetType();
>> // DynamicMethod is not quite as fast in this case
>> // where we don't have a delegate matching the function
>> // This should be really rare in deserialization, though
>> ConstructorInfo ci = type.GetConstructor(constructorTypes);
>> if (ci == null) // stupid structs and their default
>> constructors....
>> return Activator.CreateInstance(type); // it does cache the most
>> recent 16 types
>>
>> return ci.Invoke(constructorParams);
>> }
>> // another thing we could do is cache IClonables and just return
>> cloned copies in that case
>> }
>> }
>> catch (Exception e)
>> {
>> if (e.InnerException is LicenseException)
>> throw e.InnerException;
>> throw new ClassFactoryException("Error constructing object " +
>> type.Name, e);
>> }
>> }
>> private delegate object CtorDelegate();
>>
> |
|
| Back to top |
|
 |
Ben Voigt [C++ MVP]
Joined: 08 Aug 2007 Posts: 189
|
Posted: Thu Dec 13, 2007 6:54 pm Post subject: Re: fastest way to construct a struct from a type? |
|
|
"Ben Voigt [C++ MVP]" wrote in message
news:%23oG9ozbPIHA.4880@TK2MSFTNGP03.phx.gbl...
>
> "Nicholas Paldino [.NET/C# MVP]" wrote
> in message @microsoft.com...
>> Curious, can you create a generic version of this and then use
>> default(T) (where T is the type parameter)? If you can, then that might
>> be the easiest, and most maintainable solution.
>>
>> Of course, if you are loading the type information (loading the name
>> of the type, that is) and don't have access to it at compile time, it
>> won't help.
>>
>> Other than that, you can probably still go down the dynamic code
>> generation route. I would recommend an interface which would return an
>
> No dynamic code generation needed (well the JIT will be generating code,
> but it always does that).
>
>> object, and you would then create dynamic types implementing that
>> interface. It would imply create an instance of your structure for you.
>> Then, you would have a dictionary keyed by type which would return this
>> interface implementation, and then just call the method to return a new
>> instance of the value type.
>
> For the zero (or fixed) parameter case, construct a delegate from the
> ConstructorInfo and store those in a dictionary. Then creating multiples
> of the same type is as cheap as a delegate call.
>
> See http://msdn2.microsoft.com/en-us/library/53cz7sc6.aspx
Sorry, this won't work because Delegate.CreateDelegate takes a parameter of
type MethodInfo, not MethodBase. My mistake.
>
>>
>>
>> --
>> - Nicholas Paldino [.NET/C# MVP]
>> - mvp@spam.guard.caspershouse.com
>>
>> "not_a_commie" wrote in message
>> @o80g2000hse.googlegroups.com...
>>> It seems that the only way to construct a struct from a type is to use
>>> Activator.CreateInstance. Is that true? Can anyone improve
>>> (performance-wise) upon this function below:
>>>
>>>
>>> ///
>>> /// Create an object of the given type
>>> /// A default constructor is required to be successful.
>>> /// A failure will return null.
>>> ///
>>> /// The type of the object to create.
>>> /// Arguments for the desired
>>> constructor.
>>> public static object CreateObject(Type type, params object[]
>>> constructorParams)
>>> {
>>> if (type == null)
>>> throw new ArgumentNullException("Type");
>>> try
>>> {
>>> if (type.IsArray)
>>> {
>>> int[] dimensions = new int[constructorParams.Length];
>>> for (int i = 0; i < constructorParams.Length; i++)
>>> dimensions[i] = (int)constructorParams[i];
>>> return Array.CreateInstance(type.GetElementType(), dimensions);
>>> }
>>> else if (type == typeof(string))
>>> {
>>> return "";
>>> }
>>> else
>>> {
>>> // the easy and slow way:
>>> //return Activator.CreateInstance(type, constructorParams);
>>> if (constructorParams == null || constructorParams.Length <= 0)
>>> {
>>> ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
>>> if (ci == null) // stupid structs and their default
>>> constructors....
>>> return Activator.CreateInstance(type); // it does cache the most
>>> recent 16 types
>>>
>>> DynamicMethod dm = new DynamicMethod("MyCtor", type,
>>> Type.EmptyTypes, typeof(ClassFactory).Module, true);
>>> ILGenerator ilgen = dm.GetILGenerator();
>>> ilgen.Emit(OpCodes.Nop);
>>> ilgen.Emit(OpCodes.Newobj, ci);
>>> ilgen.Emit(OpCodes.Ret);
>>> return ((CtorDelegate)dm.CreateDelegate(typeof(CtorDelegate)))();
>>> // we could cache these delegates with a type lookup
>>> // but preparation time is really very minimal
>>> // see here:
>>> http://blogs.msdn.com/haibo_luo/archive/2005/11/17/494009.aspx
>>> // and here: http://blogs.msdn.com/haibo_luo/articles/494008.aspx
>>> }
>>> else
>>> {
>>> Type[] constructorTypes = new Type[constructorParams.Length];
>>> for (int i = 0; i < constructorParams.Length; i++)
>>> constructorTypes[i] = constructorParams.GetType();
>>> // DynamicMethod is not quite as fast in this case
>>> // where we don't have a delegate matching the function
>>> // This should be really rare in deserialization, though
>>> ConstructorInfo ci = type.GetConstructor(constructorTypes);
>>> if (ci == null) // stupid structs and their default
>>> constructors....
>>> return Activator.CreateInstance(type); // it does cache the most
>>> recent 16 types
>>>
>>> return ci.Invoke(constructorParams);
>>> }
>>> // another thing we could do is cache IClonables and just return
>>> cloned copies in that case
>>> }
>>> }
>>> catch (Exception e)
>>> {
>>> if (e.InnerException is LicenseException)
>>> throw e.InnerException;
>>> throw new ClassFactoryException("Error constructing object " +
>>> type.Name, e);
>>> }
>>> }
>>> private delegate object CtorDelegate();
>>>
>>
>
> |
|
| Back to top |
|
 |
Marc Gravell
Joined: 08 Aug 2007 Posts: 46
|
Posted: Fri Dec 14, 2007 1:54 pm Post subject: Re: fastest way to construct a struct from a type? |
|
|
For info, if you are using .NET 3.5, you can use the Expression
namespace to do this without having to mess with the IL directly.
Example below - results first:
ConstructorInfo: 15564 [1000000]
Func: 52 [1000000]
So it takes 1/300th the time, which is nice.
Code follows; most of it is the test rig, and much of the rest could
be refactored to simplify [Jon - might fit in with ExpressionUtil -
would that make sense to you?]
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Diagnostics;
interface INamed { string Name { get; } int Counter { get; } }
class Demo : INamed {
public string Name { get; private set; }
public int Counter { get { return 1; } } // for checksum
public Demo(string name) {
Name = name;
}
}
class Program {
static void Main() {
Type type = typeof(Demo); // in reality by name of as a plugin
ConstructorInfo ci = type.GetConstructor(new[]
{typeof(string)});
ParameterExpression param =
Expression.Parameter(typeof(string), "name");
Func ctor = Expression.Lambda
INamed>>(
Expression.New(ci, param), param).Compile();
const int COUNT = 1000000;
Stopwatch watch = new Stopwatch();
ci.Invoke(new[] { "hi" }); // for JIT
int check = 0;
watch.Start();
for (int i = 0; i < COUNT; i++) {
INamed instance = (INamed) ci.Invoke(new[] { "hi" });
check += instance.Counter;
}
watch.Stop();
Console.WriteLine("ConstructorInfo: {0} [{1}]",
watch.ElapsedMilliseconds, check);
watch.Reset();
ctor("hi"); // for JIT
check = 0;
watch.Start();
for (int i = 0; i < COUNT; i++) {
INamed instance = ctor("hi");
check += instance.Counter;
}
watch.Stop();
Console.WriteLine("Func: {0} [{1}]",
watch.ElapsedMilliseconds, check);
}
} |
|
| Back to top |
|
 |
Marc Gravell
Joined: 08 Aug 2007 Posts: 46
|
Posted: Fri Dec 14, 2007 2:07 pm Post subject: Re: fastest way to construct a struct from a type? |
|
|
Refactored helper methods, to allow simple usage, i.e.
Type type = typeof(Demo); // however you get this!
var ctor = type.Ctor();
i.e. a ctor that accepts a string, and we'll treat the result as an
INamed since such things are commonly based on an
interface/base-class. If not, can use Ctor
Marc
-----------
public static Func Ctor(this Type type) {
ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
return Expression.Lambda>(
Expression.New(ci)).Compile();
}
public static Func Ctor(this Type
type) {
ConstructorInfo ci = type.GetConstructor(new[] {
typeof(TArg1) });
ParameterExpression param1 =
Expression.Parameter(typeof(TArg1), "arg1");
return Expression.Lambda>(
Expression.New(ci, param1), param1).Compile();
}
public static Func Ctor
TResult>(this Type type) {
ConstructorInfo ci = type.GetConstructor(new[] {
typeof(TArg1), typeof(TArg2) });
ParameterExpression param1 =
Expression.Parameter(typeof(TArg1), "arg1"),
param2 = Expression.Parameter(typeof(TArg2), "arg2");
return Expression.Lambda>(
Expression.New(ci, param1, param2), param1,
param2).Compile();
}
public static Func Ctor
TArg2, TArg3, TResult>(this Type type) {
ConstructorInfo ci = type.GetConstructor(new[] {
typeof(TArg1), typeof(TArg2), typeof(TArg3) });
ParameterExpression param1 =
Expression.Parameter(typeof(TArg1), "arg1"),
param2 = Expression.Parameter(typeof(TArg2), "arg2"),
param3 = Expression.Parameter(typeof(TArg3), "arg3");
return Expression.Lambda>(
Expression.New(ci, param1, param2, param3), param1,
param2, param3).Compile();
}
public static Func
Ctor(this Type type) {
ConstructorInfo ci = type.GetConstructor(new[] {
typeof(TArg1), typeof(TArg2), typeof(TArg3), typeof(TArg4) });
ParameterExpression param1 =
Expression.Parameter(typeof(TArg1), "arg1"),
param2 = Expression.Parameter(typeof(TArg2), "arg2"),
param3 = Expression.Parameter(typeof(TArg3), "arg3"),
param4 = Expression.Parameter(typeof(TArg4), "arg4");
return Expression.Lambda
TResult>>(
Expression.New(ci, param1, param2, param3, param4),
param1, param2, param3, param4).Compile();
}
|
|
| Back to top |
|
 |
|
|
| Related Topics: | Help: The type library has lots of unexpected struct type de Hi, We have a COM+ component developed in managed C++. After using regsvcs.exe to install the component, we checked the type library. For ..Net 2002, only the interface and COM object defined in the component are listed in tlb, but .Net 2003 gives a lot o
how to cast IntPtr type to struct type Hi all, how to cast an System.IntPtr value to struct type. Example: protected override void WndProc(ref m) { const int = 0x0047; if(m.Msg == { string str=""; str);
PInvoke: struct with char** Member as struct** Parameter in Following C code is given: typedef struct { LONG num_tables; /* number of tables */ CHAR **tables; /* table names */ CHAR *where; /* where clause */ } // Allocates memory for a future SE_
Cryptography -- Construct RSAParameter from a Constant Strin Hi All, I have a CONSTANT String (which can be converted to Byte Array) of fixed length. Based on this string I wish to make a RSAParameter rsaParam, which then can be imported to Dim rsa as Dim buffer
struct covnertion(VB->C#) problem hello, all. I am trying to convert a struct from VB to c# in order to use an old DLL. Here is the definition in VB Public Type CHost Host As String * 60 Port As String * 5 Info As String * 120 'Inof returned from host Timeout As String * 10 End T |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|