WPF Disciples,
I have stuck my head in the lions mouth and wrote up a blog post http://karlshifflett.wordpress.com/2008/04/27/sample-series-bench-marking-object-loading/ on business entity loading.
I explored four different techniques for business entity object loading from a SQL Database.
LINQ to SQL came in dead last. :-{
Not that this is fully conclusive or a determining factor in all projects or environments but I hope does get us thinking.
I even found an insane technique on Code Project for dynamically creating IL code and running it. Talk about fast!!!!!! This thing open the database connection, fired up a reader, queried 19,972 records and built a generic collection of objects, close the database in .063 seconds. Oh yea, that is really fast.
Cheers,
Karl
The debates begin.
The IL code is generated once and executed. BUT, so is our C# or VB.NET code. I can’t figure out WHY the generated IL code is so much faster than the Manual code that gets compiled into IL code. I guess I’m going to have to break out ILDASM and read what the compiler is doing.
Reflection is not the enemy. You can clearly see that the Reflection method presented here is much faster than the LINQ to SQL solution.
I did a lot of other testing that I didn’t post. I had the other methods use the LINQ generated classes for example. That class is slower but not by much.
The BusinessEntityBase class I provided in PART 3 of my series, has a switch that can be thrown to turn off the special features during loading so I know that my classes will scream too.
This dynamic method is INSANELY fast. So better to compare LINQ to SQL to the Manual or Reflection methods.
But why it is slower, I do not know. It is not generating extra trips to the server and executes the same SQL SELECT statement.
Cheers,
Karl
Marlon,
Give me your phone number and room number and I’ll call you.
I’ll give this a try. The others are using SQL statements and not stored procs.
The SQL Duration is very small for the LINQ method, so I don’t think this is the bottleneck.
Marlon is going to use Ants Profiler and I’ll buy it too.
From:
wpf-di...@googlegroups.com [mailto:wpf-di...@googlegroups.com] On
Behalf Of Mike Brown
Sent: Sunday, April 27, 2008 10:10 PM
To: wpf-di...@googlegroups.com
Subject: Re: Bench Marking Business Entity Object Loading
You know the issue is possibly that the SQL is being regenerated with each call and the other methods possibly cache the SQL.
Running Karl’s code on my system produces different outputs (tried many times…)
Debug
Manual: ------------------------------
Elapsed Time: 00:00:00.3840000
Count: 19972
Reflection: ------------------------------
Elapsed Time: 00:00:00.3580000
Count: 19972
Dynamic: ------------------------------
Elapsed Time: 00:00:00.0720000
Count: 19972
LINQ: ------------------------------
Elapsed Time: 00:00:00.1360000
Count: 19972
Release:
Manual: ------------------------------
Elapsed Time: 00:00:00.4290000
Count: 19972
Reflection: ------------------------------
Elapsed Time: 00:00:00.2760000
Count: 19972
Dynamic: ------------------------------
Elapsed Time: 00:00:00.0720000
Count: 19972
LINQ: ------------------------------
Elapsed Time: 00:00:00.1230000
Count: 19972
That’s reflect what I’ve initially expected…
Mike,
I’m in TOTAL agreement with you on the Façade approach.
Question:
How can you precompile LINQ to SQL code like this? There is nothing to precompile, is there? Just one very simple statement.
Private Sub LoadLINQ()
Dim datStart As Date = Now
Using objDC As New DataClasses1DataContext
objDC.ObjectTrackingEnabled = False
Dim objList As List(Of Contact) = objDC.GetTable(Of Contact).ToList
WriteResults(datStart, Now, "LINQ", objList.Count)
End Using
End Sub
Karl
From:
wpf-di...@googlegroups.com [mailto:wpf-di...@googlegroups.com] On
Behalf Of Mike Brown
Sent: Sunday, April 27, 2008 10:33 PM
To: wpf-di...@googlegroups.com
Subject: Re: Bench Marking Business Entity Object Loading
It's not the database call that is the issue. LINQ to SQL does have an overhead associated with it. Rico's first post in the series shows that an uncompiled LINQ to SQL query has 1/8 the performance of using raw ado.net.
However compiling your LINQ to SQL queries practically negates the overhead of the framework.
Let me put it this way...if you write a LINQ to SQL query, you should compile it. I am a firm believer that your Datacontext should not be exposed outside of your data access layer. I would even go so far as to say that your LINQ to SQL objects should be internal to your data library. Basically you should have a Facade that hides the fact that LINQ to SQL even exists. The code that calls your data layer should be passing in objects from your business layer...the datalayer is responsible for translating those calls as needed to get them to the database.
On Sun, Apr 27, 2008 at 10:15 PM, Karl Shifflett <ka...@littlerichie.com> wrote:
I'll give this a try. The others are using SQL statements and not stored procs.
The SQL Duration is very small for the LINQ method, so I don't think this is the bottleneck.
Marlon is going to use Ants Profiler and I'll buy it too.
From: wpf-di...@googlegroups.com
[mailto:wpf-di...@googlegroups.com]
On Behalf Of Mike Brown
Sent: Sunday, April 27, 2008 10:10 PM
To: wpf-di...@googlegroups.com
Subject: Re: Bench Marking Business Entity Object Loading
You know the issue is possibly that the SQL is being regenerated with each call and the other methods possibly cache the SQL.
You can compile your Linq to SQL queries and you'll get the performance of stored procedures on the DB. Rico Mariani wrote an entire series about performance of LINQ compiled queries...you get just a 3% overhead against writing the data access layer by hand and using raw ADO.NET Don't believe me ... read it yourself.
<br
WOW. Talk about different.
I’m on Vista x64.
Has anyone else run this code? I would love to get to the bottom of this. Very strange that Reflection is beating Manual.
Corrado, did you run this code as is or modify it? Your LINQ numbers are so much better than mine.
style='font-size:12.0pt;font-family:"Times New Roman","serif"'>
Yes Karl,
Just modified connection string, code runs as-is J
Corrado,
What O/S and type of computer did you run these tests on? Maybe this can account for the different results???
Vista or XP
x32 or x64
Number of CPU’s or Cores
Processor speed
Main memory
Mine is:
Vista x64, Quad, 2.4GHz, 4GB.
From: wpf-di...@googlegroups.com [mailto:wpf-di...@googlegroups.com] On Behalf Of Corrado Cavalli
Sent: Monday, April 28, 2008 1:36 AM
To: wpf-di...@googlegroups.com
Func<Northwinds, IQueryable<Orders>, int> q =
CompiledQuery.Compile<Northwinds, int, IQueryable<Orders>>
((Northwinds nw, int orderid) =>
from o in nw.Orders
where o.OrderId == orderid
select o );
Northwinds nw = new Northwinds(conn);
foreach (Orders o in q(nw, orderid))
{
...
}
I’m going to get Ants Profiler so that I can figure out what is going on and where the holdup is on my system.
Marlon,
Holy smokes, you have not slept yet?
Here is the only line of LINQ code I have:
objList As List(Of Contact) = objDC.GetTable(Of Contact).ToList
Didn’t see anything to pre-compile.
Karl
Marlon, no I fell off the wagon and did get some sleep.
I’m much more concerned about you. Hope you can get some sleep before your day begins.
From: wpf-di...@googlegroups.com [mailto:wpf-di...@googlegroups.com] On Behalf Of Marlon Grech
Sent: Monday, April 28, 2008 7:16 AM
To: wpf-di...@googlegroups.com
Best to you on your great day in Redmond!
I’m going to run these tests on other machines and try and get to the bottom of this. I have been running tests this morning and get the same results.
The Ants Profiler should also shed some light.
Marlon has both the Ants Profiler and Mem Profiler. He will look into this with both products soon too.
From: wpf-di...@googlegroups.com [mailto:wpf-di...@googlegroups.com] On Behalf Of Corrado Cavalli
Sent: Monday, April 28, 2008 7:48 AM
To: wpf-di...@googlegroups.com
<br
Not yet. Thanks for the suggestion!
<br
Function(database As DataClasses1DataContext)_
Manual: --------------------------
Elapsed Time: 00:00:00.2656131
Count: 19972
Reflection: ----------------------
Elapsed Time: 00:00:00.2968617
Count: 19972
Dynamic: -------------------------
Elapsed Time: 00:00:00.1406187
Count: 19972
LINQ PreCompiled: ----------------
Elapsed Time: 00:00:00.7030935
Count: 19972
LINQ: ----------------------------
Elapsed Time: 00:00:00.2031159
Count: 19972
Manual: ------------------------
Elapsed Time: 00:00:00.2656131
Count: 19972
Reflection: --------------------
Elapsed Time: 00:00:00.2968617
Count: 19972
Dynamic: -----------------------
Elapsed Time: 00:00:00.1406187
Count: 19972
LINQ: --------------------------
Elapsed Time: 00:00:00.6562206
Count: 19972
LINQ PreCompiled: --------------
Elapsed Time: 00:00:00.2656131
Count: 19972
________________________________
From: wpf-di...@googlegroups.com on behalf of Mike Brown
Sent: Mon 4/28/2008 9:06 AM
To: wpf-di...@googlegroups.com
Subject: Re: Bench Marking Business Entity Object Loading