[Mono-devel-list] System.Reflection Performance

Ben Maurer bmaurer at users.sourceforge.net
Fri Jan 2 00:29:42 EST 2004


Hello,

Today I was doing performance testing and noticed that some reflection
operations were taking alot longer than I thought they would. So, I
decided to profile. My origional issue was with MethodBase.Invoke. I
wrote the following test:

using System;
using System.Reflection;

public class A {
	public void Foo (int a, int b, int c, int d, int e, string s, string ss, string sss)
	{
	}
	
	public static void Main ()
	{
		A a = new A ();
		MethodInfo mi = typeof (A).GetMethod ("Foo");
		object [] rgs = {1, 2, 3, 4, 5, "a", "b", "c"};
		
		for (int i = 0; i < 500000; i ++)
			mi.Invoke (a, rgs);
	}
}

On my local Linux box, I got:
[benm at Ben perf]$ time mono ref1.exe
 
real    0m21.470s
user    0m21.360s
sys     0m0.010s

I copied the program over to a Windows box, where it ran in 3 seconds.
The windows box has a lower processor speed and less ram than my Linux
box. I decided to --profile it, and I got (obviously, i reduced the
number of times the loop executed):


> ########################
>  548.976       1  548.976   .A::Main()
>   Callers (with count) that contribute at least for 1%:
>            1  100 % .A::Main(object,intptr,intptr)
> ########################
>  549.953       1  549.953   .A::Main(object,intptr,intptr)
>   Callers (with count) that contribute at least for 1%:
> ########################
>  484.546    5000    0.097   System.Reflection.MethodBase::Invoke(object,object[])
>   Callers (with count) that contribute at least for 1%:
>         5000  100 % .A::Main()
> ########################
>  475.791    5000    0.095   System.Reflection.MonoMethod::Invoke(object,BindingFlags,Binder,object[],CultureInfo)
>   Callers (with count) that contribute at least for 1%:
>         5000  100 % System.Reflection.MethodBase::Invoke(object,object[])
> ########################
>  416.657    5000    0.083   System.Reflection.Binder::ConvertArgs(Binder,object[],ParameterInfo[],CultureInfo)
>   Callers (with count) that contribute at least for 1%:
>         5000  100 % System.Reflection.MonoMethod::Invoke(object,BindingFlags,Binder,object[],CultureInfo)
> ########################
>  292.208   40000    0.007   .Default::ChangeType(object,Type,CultureInfo)
>   Callers (with count) that contribute at least for 1%:
>        40000  100 % System.Reflection.Binder::ConvertArgs(Binder,object[],ParameterInfo[],CultureInfo)
> ########################
>  222.243   40001    0.006   System.Object::GetType()
>   Callers (with count) that contribute at least for 1%:
>            1  100 % System.Exception::.ctor(string)
> ########################

So, it is quite obvious that the GetType is the bulk of the problem.

using System;

class T {
	static void Main ()
	{
		object o = 1;
		
		for (int i = 0; i < 5000000; i ++) {
			Type t = o.GetType ();
			// dont opt t away somehow
			if (t == null)
				break;
		}
	}
}

On Mono:
[benm at Ben perf]$ time mono ref2.exe
 
real    0m23.568s
user    0m23.450s
sys     0m0.010s

On the windows box, it ran in .6 seconds. Remember, the windows box is
slower.

I am wondering if any of the runtime gurus can think of ways to make
GetType faster. GetType is by no means *fast* in MS, it is not designed
to be. However, it seems reasonable that it should be a tad bit faster
than this.

As a side note, I did a quick test on the Invoke call in MS.net, it is
pretty clear that they call the Binder iff the parameter type does not
match exactly (I tested by making a Binder that would always return 500,
and then called a method with the sig (int,int) with params (byte,int).
The first parameter was passed as 500, the second was unmodified.) So,
it appears we could change Invoke to do the check in C. In C we would be
able to take alot of shortcuts (not allocating the params array, quicker
type operations, etc, etc). I think this would be an easy way to fix the
specific manifestation of the problem. However, I really think GetType
should be *much* faster. There are alot of tricks that can be done with
GetType that would depend on it being quick.

-- Ben





More information about the Mono-devel-list mailing list