Geeks With Blogs

News Google

Nick Harrison Blog<Nick>.Next()

Whenever I talk about reflection, questions about performance always come up. People are worried that reflection will make their code slower. While you should always worry about performance , you should not let performance worries keep you from making appropriate use of new technology. An ounce of testing is worth a pound of speculation. Recently, I did some timing studies to set my own fears to rest. I loaded the NorthWinds database with 100,000 Employee records. I then created an Employee object with a read /write property for every column in this table. Finally I compared various methods of initializing this object from the contents of a DataReader. I compared Hard Coded with explicit type conversion, Reflective finding the PropertyInfo object each and every time, hard coded with out the type conversion, and Reflective, caching the PropertyInfo objects to a HashTable instead of searching for them for every record. The results may be a little surprising: Your results may vary depending on the nature of your objects, but I believe that the results will be similar. 

 

What do I mean by “Hard Coded With Type Conversion”


   System.DateTime start = DateTime.Now;
   System.Data.IDataReader dr = GetData(recordCount);  
   while (dr.Read())
   {
    CustomTypes.Employees newEmployee = new CustomTypes.Employees ();
    newEmployee.Address = dr["Address"].ToString();
    newEmployee.BirthDate = DateTime.Parse( dr["BirthDate"].ToString());
    newEmployee.City = dr["City"].ToString();
    newEmployee.Country = dr["Country"].ToString();
    newEmployee.EmployeeID = Int32.Parse( dr["EmployeeID"].ToString());
    newEmployee.Extension = dr["Extension"].ToString();
    newEmployee.FirstName = dr["FirstName"].ToString();
    newEmployee.HireDate = DateTime.Parse( dr["HireDate"].ToString());
    newEmployee.LastName = dr["LastName"].ToString();
    newEmployee.PostalCode = dr["PostalCode"].ToString();
    newEmployee.Region = dr["Region"].ToString();
    newEmployee.ReportsTo =  Int32.Parse( dr["ReportsTo"].ToString());
    newEmployee.Title = dr["Title"].ToString();
    newEmployee.TitleOfCourtesy = dr["TitleOfCourtesy"].ToString();
    pgbHardCodedConversion.Increment (1);
   }
   dr.Close();
   System.DateTime stop = DateTime.Now ;
   System.TimeSpan ts = new TimeSpan (stop.Ticks - start.Ticks );
   lblHardCodedConvertedTime.Text = "Finished in " + ts.TotalMilliseconds + " milliseconds";

 

Some may argue that of course this will be very slow and no one would I do it like this, but I have seen this code or similar code all of the time. I am sure you have as well.    We often forget that the values in the datareader already match the data type of the corresponding column in the table and such parsing is not necessary.

Simple Reflective Version:

 

   Type targetType = targetObject.GetType();
   while (dr.Read ())
   {
    for (int index = 0; index < dr.FieldCount;index++)
    {
     PropertyInfo property = targetType.GetProperty (dr.GetName (index));
     if (property != null)
     {
      if (property.CanWrite )
      {
       try
       {
        property.SetValue (targetObject, dr.GetValue (index), null);
       }
       catch
       {
       }
      }
     } 
    }
   }

This technique works well.    We don't have to worry about what columns are in the data reader.   We don't have to worry about what properties are in the object.    The closer they match, the better, but any properties in common will be initialized.     The only problem is that we are doing a good deal more reflection than necessary.    Since the properties want change from one record to the next, all of the calls to GetProperty are not really needed.

Caching the PropertyInfo Objects

Here we will initialize a HashTable with all of the PropertyInfo objects before reading the first record.   As the initial print screen shows, this can have a substantial performance impact.   If you are only loading up a hand full of objects and you are looking at a great many properties, this may not be worth the effort.   You need to do your own testing :)


   ArrayList returnValue = new ArrayList ();
   Hashtable properties = new Hashtable();
   Type targetType = targetObject.GetType();
   foreach (PropertyInfo currentProperty in targetType.GetProperties ())
   {
    properties[currentProperty.Name ] = currentProperty;
   }
   while (dr.Read())
   {
    object newObject = Activator.CreateInstance (targetType);
    for (int index = 0; index < dr.FieldCount;index++)
    {
     PropertyInfo property = (PropertyInfo) properties[dr.GetName (index)];
     if (property != null)
     {
      if (property.CanWrite )
      {
       try
       {
        property.SetValue (newObject, dr.GetValue (index), null);
       }
       catch
       {
       }
      }
     }
    }
    returnValue.Add (newObject);
   }
   dr.Close();

 

Conclusions

The results show what I believe to be fairly typical results in comparing the performance of reflective vs.  non-reflective code.   I believe that the benefits of having adaptive dynamic code will usually be worth any trade offs in performance.    (If there are any)    Because the reflective code is much more reusable, it is much more likely to be tuned and thoroughly tested.    Simple applications of reflection like this can also reduce the amount of tedious, repetitive code where bugs and problems are more likely to crop up.

Is anyone else finding similar results using reflection?    Has anyone had different results using reflection?

Posted on Sunday, May 29, 2005 9:08 PM Performance Timings | Back to top

Related Posts on Geeks With Blogs Matching Categories

Comments on this post: Comparing Reflection and Hard Coded for initializing an object from a Data Read

# Nick Harrison is Blogging
Requesting Gravatar...
I just noticed that Nick Harrison is blogging&nbsp;(I&rsquo;ve mentioned him before).&nbsp; He is without...
Left by protected virtual void jaysonBlo on Dec 20, 2005 11:42 PM

# re: Comparing Reflection and Hard Coded for initializing an object from a Data Read
Requesting Gravatar...
What were your results? I cant see them on your site. Im currently buinding a similar binding entity base class
Left by Ariel Rosado on Mar 20, 2012 9:49 PM

comments powered by Disqus

Copyright © Nick Harrison | Powered by: GeeksWithBlogs.net