This post originated from an RSS feed registered with .NET Buzz
by -.
Original Post: Reflection Geschwindigkeitstest
Feed Title: Norbert Eder - Living .NET
Feed URL: http://feeds.feedburner.com/NorbertEder-Livingnet
Feed Description: Copyright (c)2005, 2006 by Norbert Eder
Da ich mir heute wieder mal einen O/R Mapper genauer angesehen habe (Name der Redaktion bekannt), ist mir ein sehr wesentlicher Punkt aufgefallen. Nat��rlich arbeiten diese Frameworks mit Reflection. Selten wird jedoch tats��chlich auf Geschwindigkeit gesetzt, so eben das Framework, welches ich heute in die Finger bekommen habe. Daraufhin musste ich gleich einen Test machen.
Der Testfall ist ein sehr einfacher, der im Normalfall keine wesentliche Last verursacht. Es wird aus einer Assembly lediglich ein bestimmter Typ aufgrund seines Namens geladen und alle Properties ausgegeben. Die ganze ��bung wird 200.000 mal durchgef��hrt, was in einer mittelgro��en Anwendung nicht sehr viel ist.
Wenn man davon ausgeht, dass die Engp��sse in der Reflection bei quasi rekursiven Durchl��ufen erst so richtig entstehen, dann sollte mein Testfall nicht sehr gravierend ausfallen. Hier jedoch das Testergebnis auf meinem Rechner:
Was genau bedeutet dies? Nun, im ersten Durchlauf wird der nachfolgende Code aufgerufen.
for (int i = 0; i < 200000; i++)
{
Assembly a = Assembly.GetExecutingAssembly();
if (a != null)
{
Type t = a.GetType("ReflectionSpeedTest.Person");
FieldInfo[] fis = t.GetFields();
foreach (FieldInfo fi in fis)
{
Console.WriteLine(fi.Name);
}
}
}
Im Vergleich dazu, werden die Feld-Informationen in der zweiten Variante gecached. Das hat zwar den Nachteil, dass der Speicherverbrauch ansteigt, jedoch die Geschwindigkeit um ein Vielfaches erh��ht wird - und das bei dieser wirklich sehr sehr einfachen Aufgabe.
this.fieldInfos = new Hashtable();
Assembly a = Assembly.GetExecutingAssembly();
if (a != null)
{
Type t = a.GetType("ReflectionSpeedTest.Person");
FieldInfo[] fis = t.GetFields();
foreach (FieldInfo fi in fis)
{
this.fieldInfos.Add(fi.Name, fi);
Console.WriteLine(fi.Name);
}
}
for (int i = 0; i < 199999; i++)
{
IDictionaryEnumerator en = this.fieldInfos.GetEnumerator();
while (en.MoveNext())
{
Console.WriteLine(en.Key.ToString());
}
}
Insgesamt ebenfalls wieder 200.000 Aufrufe. ��ber 1800 Millisekunden im Vergleich zu knapp mehr als 15 Millisekunden spricht hierbei schon B��nde. Man bedenke, dass oft aufw��ndigere Probleme mittels Reflection gel��st werden, daher sollte ein Caching durchaus ��berlegt werden. Ansich sehr einfach, jedoch eine gro��e Wirkung.