views:

309

answers:

5

Hello,

I have compared two queries which fetch some fairly large data from a database table. For query one I used Linq To Sql and for the other I use passthrough SQL via ADO.NET.

I know that Linq To Sql has to do a lot of work behind the scenes, but what is it actually doing? The two queries fetches the same amount of data but the Linq To Sql query is more than 5 seconds slower and uses 150mb more RAM!

Here is my test code:

Using Linq To Sql :

public void MakeList()
    {
        int start = Environment.TickCount;
        var document = from d in _dm.tDokuments select d;

        List<tDokument> documentList = document.ToList();
        int end = Environment.TickCount;

        GridView1.DataSource = documentList;
        GridView1.DataBind();

        Label1.Text = (end - start).ToString();
    }

Passthrough SQL + ADO.NET:

public void MakeList()
    {

        int start = Environment.TickCount;
        SqlCommand sqlCommand = new SqlCommand("SELECT * FROM tDokument", _connection);
        SqlDataAdapter da = new SqlDataAdapter(sqlCommand);

        DataSet ds = new DataSet();
        da.Fill(ds);
        int end = Environment.TickCount;

        GridView1.DataSource = ds;
        GridView1.DataBind();

        Label1.Text = (end - start).ToString();
    }
+3  A: 

Have you looked at the actual SQL being sent to SQL Server with Profiler?

In this case I suspect it's how the client is handling it (DataSet vs List) that is causing the difference, but I'm nowhere near a c# expert.

gbn
The dataset is going to have more overhead associated with it than the generic list, so this really shouldn't be the issue.
Jason
@Jason: thanks. I assumed the list would.
gbn
+1  A: 

Your measure may not be accurate, please use the System.Diagnostics.StopWatch class for time measurement:

static void Main(string[] args)
{
    var sw = Stopwatch.StartNew();
    Thread.Sleep(100);
    Console.WriteLine(sw.Elapsed.ToString());
    Console.Read();
}
Jader Dias
Sound advice (though should probably be a comment). Obviously the Thread.Sleep might cause the thread to sleep for longer than 100 ms.
RichardOD
Yes, but when I ran the program above the printed result was slightly smaller than 100ms
Jader Dias
A comment would not enable the code formatting
Jader Dias
It shouldn't do. On my machine it is always a little longer than 100ms.
RichardOD
@Jader- good point about the formatting.
RichardOD
00:00:00.0993450 or similar 3 times in a row
Jader Dias
@Jader- very interesting. I guess I didn't consider the inaccuracies of the windows timer. Found this article though which interesting (C++, but I think still relevant)- http://www.codeproject.com/KB/system/sleepstudy.aspx
RichardOD
@Jader- there's another interesting post on it here- http://stackoverflow.com/questions/1303667/how-accurate-is-thread-sleeptimespan.
RichardOD
+6  A: 

Linq2Sql is returning strongly typed objects where as the dataset is getting populated with what essentially amounts to a hash table.

In Linq, the population of the data and the binding of that data to a GridView uses a lot of reflection to generate the desired results.

In the second piece of code, the data is being loaded into a dataset and binded to a GridView. This is essentially loading a hashtable with data and lookups to bind.

Hashtable operations are always going to be faster than reflection. With a small amount of data, there is not going to be a noticeable difference but for lots of data, you will see the impact of reflection in Linq.

Jason
Thank you for your answer. I need an answer tho. What is reflection?
Poku
Reflection is the procees of discovering the properties, methods, events of an object or type programatically. Check out the System.Reflection namespace on MSDN. It's what Linq has to do to assign the values return by the query to the properties of the tDokument object.It is much slower than direct property assignment.
Jason
+2  A: 

Capture and analyze the SQL statement(s) that are being sent over the wire in your Linq To Sql example. SQL Profiler will do the trick.

Run both those statements from Example 1 and 2 directly against your SQL Server using Management Studio. Likely you won't see ANY substantial difference in the query plan.

I think the majority of time is spent in constructing the C# objects (Jason's answer nails it, I think).

p.campbell
+2  A: 

Linq to Sql has to figure out from your code what kind of query to run against the database then it has to translate the results of the query into strongly typed objects, which means casting will occur. That's two things your DataSet version doesn't do.

If you're interested in Linq to Sql performance, there is the option of using compiled queries which removes the need for interpretation at runtime.

Will