.NETGURU
Reflection Performance Question.
Messages   Related Types
This message was discovered on microsoft.public.dotnet.framework.performance.
Responses highlighted in red are from those people who are likely to be able to contribute good, authoratitive information to this discussion. They include Microsoft employees, MVP's and others who IMHO contribute well to these kinds of discussions.
Post a new message to this list...

paulg
hi all.
I am creating an application in which I map tables to objects. For the
GetAll function,

Instead of:

Public ArrayList GetAll(){
SqlDataReader reader = null;
...
reader = cmd.ExecuteReader();
ArrayList result = new ArrayList();
while(reader.Read()){
Customer customer = new Customer();
customer.CustomerID = GetInt(reader["CustomerID"]);
customer.FirstName = GetString(reader["FirstName"]);
customer.FirstName = GetString(reader["LastName"]);
....
....
result.Add(customer);
}
reader.Close();
return result;
}

I adapted the following:

public void GetAll(SqlDataReader reader, IDBObject obj, ref ArrayList list)
{

Type objType = obj.GetType();
PropertyInfo[] fields = objType.GetProperties();
while(reader.Read()){
foreach(PropertyInfo pi in fields){
IDBObject newObj = obj.New();
pi.SetValue(newObj, reader[pi.Name] is DBNull?null"reader
[pi.Name], null);
}
list.Add(newObj);
}
reader.Close();
}

IDBObject is an interface which is implemented by all database objects in
application.
This works fine for me and it is more generic so that all database objects
can use this.
My question is that what is the difference in terms of performance and why?

Second question.
What is the difference between array and arraylist in terms of performance
and why? ( I am binding the list to dropdown boxes and grids)
Reply to this message...
 
    
Fred Hirschfeld
I am creating an Object Relational Mapping framework using reflection with
an XML mapping document and have not really noticed any performance issues
loading data. I have not been Load Testing it yet but the simple application
uses 1:M relationships and loads a fairly large object tree without much
delay.

If this is for a business application, then I would expect that the
performance difference is negligable and use the Reflection method. You may
also want to look at a commercial product for this as well since they offer
extras like Object Caching (helps with performance), Lazy Load, ...

There is also a good book I would recommend for patterns in this area:
Patterns of Enterprise Application Architecture by Martin Fowler (ISBN:
0-321-12742-0

Fred

"paulg" <Click here to reveal e-mail address> wrote in message
news:Xns9544D6D389F45nobodynowherecom@207.46.248.16...
[Original message clipped]

Reply to this message...
 
    
Sinan
Using reflection is about 1000 times slower than directly accessing to
the properties. If property info classes are cahced it goes down to
700 times. This test was done on .Net Framework 1.1.

We are generating class loader/savers using an XML document that is
partially generated from database metadata, which works pretty good.
But still we are using reflection for small applications, or when
performance is not really a concern.

If there is a way to speed up reflection to access property values
please let me know.

Sinan Komut

"Fred Hirschfeld" <a@b.c> wrote in message news:<Click here to reveal e-mail address>...
[Original message clipped]

Reply to this message...
 
    
Fred Hirschfeld
I am not using reflection to access property values, only to inflate the
objects in the first place. Once the object is in memory it is a simple
variable access. With Caching and Lazy Loading, you can get some really good
performance even in larger applications.

I ran my tests on reflection and noted that in looping 100000 times getting
a property it was ~1 msec average access for straight property and ~10 msec
average access for finding the property and getting its value. In testing
the setter, the reflection timing increased slightly to ~13 msecs.

NOTE: I did also perform an additional test where I removed the finding /
querying for the PropertyInfo from the loop and that decreased the setting
time to ~6.5 msecs and gets to 4 msecs on average. This shows a means to
optimize the way to get the properties by only aquiring the getter/setter
PropertyInfo once for the particular property and caching it with the Class
definition to improve performance at runtime.

From these it does not appear to be a really big issue granted if you are
doing this and loading 100 objects in a single call that each have 10
properties it would mean ~1.3 seconds for the data population in addition to
any database querying. I have been using this technique with more that that
many objects loading and the performance is sufficient (without any
optimizations yet).

I do see your point that in really time sensitive applications / real-time
this extra little bit could seem like a lot when servicing 1000's of users
at once. This is where you get into trade-off between performance and
maintenance / development.

Fred

"Sinan" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Sinan
On my machine P4 ~ 2GHz

Direct property access takes around 0.015 nanoseconds.
Accessing property value through reflection takes 12.35 nanoseconds.
Accessing property using cached property info takes 9.06 nanoseconds.

So this time reflection is around 800 times slower than accessing to
the property value. I wonder why our test results are so different.
Which version of .Net framework are you using? And following is the
class that I've used for testing.

    class Class1
    {
        public string Test
        {
            get
            {
                return "Test";
            }
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            Class1 c1 = new Class1();

            long ticks = Environment.TickCount;
            string x = null;
            int staticCount = 1000000;
            for(int i=0; i<staticCount; i++)
            {
                x = c1.Test;
            }
            Console.WriteLine(x);
            float secs1 = (float)(Environment.TickCount - ticks)/1000;
            Console.WriteLine("Static call: {0,0:n} calls took {1} second(s)",
staticCount, secs1);

            ticks = Environment.TickCount;
            Type t = c1.GetType();
            int reflectionCount = 100000;
            for(int i=0; i<reflectionCount; i++)
            {
                PropertyInfo pi = t.GetProperty("Test");
                x = (string)pi.GetValue(c1, null);
            }
            float secs2 = (float)(Environment.TickCount - ticks)/1000;
            Console.WriteLine("Reflection call: {0,0:n} calls took {1}
second(s)", reflectionCount, secs2);

            ticks = Environment.TickCount;
            t = c1.GetType();
            PropertyInfo p1 = t.GetProperty("Test");
            int cachedCount = 100000;
            for(int i=0; i<cachedCount; i++)
            {
                x = (string)p1.GetValue(c1, null);
            }
            float secs3 = (float)(Environment.TickCount - ticks)/1000;
            Console.WriteLine("Reflection call: {0,0:n} calls took {1}
seconds", cachedCount, secs3);

            float secsPerStaticCall = secs1/staticCount;
            float secsPerReflectionCall = secs2/reflectionCount;
            float secsPerCachedCall = secs3/cachedCount;

            Console.WriteLine("\r\n");
            Console.WriteLine("Nanoseconds per property access {0}",
secsPerStaticCall*1000000);
            Console.WriteLine("Nanoseconds per reflection access {0}",
secsPerReflectionCall*1000000);
            Console.WriteLine("Nanoseconds per cahced access {0}",
secsPerCachedCall*1000000);
            if(secs1 > 0)
            {
                Console.WriteLine("\r\n");
                Console.WriteLine("Property access is {0} times faster than
reflection, Property access is {1} times faster than cached property
info call", (secsPerReflectionCall/secsPerStaticCall),
(secsPerCachedCall/secsPerStaticCall));
            }

            Console.ReadLine();
        }
    }

"Fred Hirschfeld" <a@b.c> wrote in message news:<Click here to reveal e-mail address>...
[Original message clipped]

Reply to this message...
 
    
Fred Hirschfeld
Here is my results using your code (in a WinForm) mixed with mine...

My system is a P4 3GHz HT with 1 gig of ram using .NET 1.1 on WinXP:
Static call: 10,000,000.00 calls took 0.078 second(s) - Ticks = 78
Reflection call: 10,000,000.00 calls took 4.797 second(s) - Ticks = 4797
Reflection call 2: 10,000,000.00 calls took 11.062 second(s) - Ticks = 11062

Seconds per property access 0.0078
Seconds per reflection access 1.1062
Seconds per cahced access 0.4797

Property access is 141.8205 times faster than reflection, Property access is
61.5 times faster than cached property info call

My second system is a P4 1.8GHz with 512 gig of ram laptop using .NET 1.1 on
WinXP:
Static call: 10,000,000.00 calls took 0.21 second(s) - Ticks = 210
Reflection call: 10,000,000.00 calls took 7.902 second(s) - Ticks = 7902
Reflection call 2: 10,000,000.00 calls took 17.205 second(s) - Ticks = 17205

Seconds per property access 0.021
Seconds per reflection access 1.7205
Seconds per cahced access 0.7902

Property access is 81.92857 times faster than reflection, Property access is
37.62857 times faster than cached property info call

Not sure why mine are showing that better of a result but I would expect on
a server and large application with multiple processors, this would make the
performance acceptable for a large portion of applications. There will still
be some apps that could not take this performance hit and you could add a
feature to the Object Relational to create the concrete mapping classes
dynamically in memory at load time to manage the inflation process.

Fred

"Sinan" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
    
Bob Grommes
Paul,

I haven't tried to benchmark anything similar and even if I had, it would
not necessarily prove anything. As they say, "your mileage may vary".
Using a more generalized, reflection-based methodology is sure to be slower
generally, but how MUCH slower depends alot on usage patterns. If you're
mostly pulling in a few records at a time to work with them in a UI then
it's probably not going to matter if it takes an extra fraction of a second;
if you're doing batch processing it might be a different story. You really
have to run some of your own tests.

Something that you might also consider is the possibility of writing some
code generators to create routines like the first version of GetAll().
Something that does the gruntwork at design time rather than at runtime.
Often this gives you the best of both worlds.

Regarding arrays vs. arraylists -- arrays hold items of a specific data
type, but arraylists are lists of objects and thus you have boxing /
unboxing overhead for anything you put in or take out of an ArrayList. That
overhead is significant, so if you can live with an array, it's a good way
to go. The problem with arrays is that they are of a static size; it's
expensive to simulate "redimensioning". Actually, both the types and
quantity of items to be stored are not necessarily known at design time, so
one of the collection classes like ArrayList or Hashtable may be necessary.
Even if you know the number of items (or an acceptable maximum) at design
time you may be forced to resort to an array of objects if those objects
will be of various types. Other than being a little more lightweight than
an ArrayList, there's not much advantage in an array of objects over an
ArrayList.

The other possibility, if you can design your application around CLR 2.0, is
to use List<T>, the generic version of ArrayList. That way you can have
dynamic size *and* strong typing. The performance of a List<T> should be
very similar to that of an array.

--Bob

"paulg" <Click here to reveal e-mail address> wrote in message
news:Xns9544D6D389F45nobodynowherecom@207.46.248.16...
[Original message clipped]

Reply to this message...
 
    
Jon Skeet [C# MVP] (VIP)
Bob Grommes <Click here to reveal e-mail address> wrote:
[Original message clipped]

Not quite. You have boxing/unboxing overhead if you put value types
into (or take them out of) an ArrayList. If you're dealing with
reference types, no boxing is involved.

--
Jon Skeet - <Click here to reveal e-mail address>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Reply to this message...
 
    
Bob Grommes
You are right -- boxing with value types, casting overhead with reference
types. Both involve overhead, though.

--Bob

"Jon Skeet [C# MVP]" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
[Original message clipped]

Reply to this message...
 
 
System.Collections.ArrayList
System.Console
System.Data.SqlClient.SqlDataReader
System.DBNull
System.Environment
System.Reflection.PropertyInfo




ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
Ad


Need Dot Net Interview Questions?
Ask ExamGuru, Inc. for advice and help on Passing .Net Interviews
.Net Projects
Best-of-breed application framework for .NET projects, developed by ExamGuru, Inc. and ExamGuru IT
Free .net Help
Commission ExamGuru, Inc. and his team for your next bespoke software project
FogBUGZ
The only bug tracking system carefully crafted with one goal in mind: helping teams create great software.
Awesome Tools
If you don't know about these, you're missing out... IT Certification Questions
IT Interview Questions
Free Oracle 10g Training
MCSE Boortcamp
Cisco Study Guides
Cheap Study Guides
Exact Questions
Dot Net Interview Questions
Oracle OCP
Cheap Travel
Designer Perfumes - Wholesale Prices
Free Programming Tutorials
 
ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
 Copyright © ExamGuru, Inc. 2001-2006
Contact Us - Terms of Use - Privacy Policy - www.dot-net-guru.com - www.examguru.net - www.oraclesource.net - www.itinterviews.net - www.examguru.net/ITCertification