<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>ADO.NET team blog : Petshop</title><link>http://blogs.msdn.com/adonet/archive/tags/Petshop/default.aspx</link><description>Tags: Petshop</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>ADO.NET performance improvements with the .NET Framework 2.0 SP1</title><link>http://blogs.msdn.com/adonet/archive/2008/01/28/ado-net-performance-improvements-with-the-net-framework-2-0-sp1.aspx</link><pubDate>Tue, 29 Jan 2008 04:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7295577</guid><dc:creator>dpblogs</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/adonet/comments/7295577.aspx</comments><wfw:commentRss>http://blogs.msdn.com/adonet/commentrss.aspx?PostID=7295577</wfw:commentRss><description>&lt;DIV class=ExternalClass375C863B795C4DECB187638317618A6E&gt;
&lt;P&gt;With the release of Visual Studio 2008 and the .NET Framework 2.0 SP1, there are some bug fixes and improvements in ADO.NET (A list of the general fixes is at &lt;A title=http://support.microsoft.com/kb/945757 href="http://support.microsoft.com/kb/945757" mce_href="http://support.microsoft.com/kb/945757"&gt;http://support.microsoft.com/kb/945757&lt;/A&gt;)&lt;/P&gt;
&lt;P&gt;We worked with the CLR team to get improvements like the &lt;A href="http://msdn.microsoft.com/msdnmag/issues/07/10/ThreadPool/default.aspx" mce_href="http://msdn.microsoft.com/msdnmag/issues/07/10/ThreadPool/default.aspx"&gt;thread pool improved scalability&lt;/A&gt;, and that was important for making sure our SqlReader performance is better in multithreaded scenarios (like your ASP.NET applications under load).&lt;/P&gt;
&lt;P&gt;Particularly improved were scenarios like Data set insertion, and multi-threaded scenarios (such as ASP.NET applications) using SqlDataReader (25% better or more, depending on hardware and OS architecture).&lt;/P&gt;
&lt;P&gt;For a complex real world web application, like &lt;A href="http://msdn2.microsoft.com/en-us/library/aa479070.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa479070.aspx"&gt;Petshop&lt;/A&gt;, the improvement is not so big, since the application does many other things in addition to data access, but still you should get part of the benefits.&lt;/P&gt;
&lt;P&gt;A summary of our lab numbers, just as a reference of how much improvement you can get:&lt;/P&gt;
&lt;TABLE class="" cellSpacing=0 cellPadding=2 width=617 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=264&gt;Scenario&lt;/TD&gt;
&lt;TD class="" vAlign=top width=104&gt;.NET FW 2.0&lt;/TD&gt;
&lt;TD class="" vAlign=top width=131&gt;.NET FW 2.0 SP1&lt;/TD&gt;
&lt;TD class="" vAlign=top width=116&gt;Improvement&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=262&gt;SqlReader&lt;/TD&gt;
&lt;TD class="" vAlign=top align=right width=105&gt;14855&lt;/TD&gt;
&lt;TD class="" vAlign=top align=right width=130&gt;18100&lt;/TD&gt;
&lt;TD class="" vAlign=top align=right width=120&gt;27.3%&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=260&gt;DataSet insert&lt;/TD&gt;
&lt;TD class="" vAlign=top align=right width=105&gt;9637&lt;/TD&gt;
&lt;TD class="" vAlign=top align=right width=129&gt;12890&lt;/TD&gt;
&lt;TD class="" vAlign=top align=right width=123&gt;40.8%&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=257&gt;Pet Shop 4.0(Browse the store)&lt;/TD&gt;
&lt;TD class="" vAlign=top align=right width=105&gt;22.44&lt;/TD&gt;
&lt;TD class="" vAlign=top align=right width=129&gt;24.40&lt;/TD&gt;
&lt;TD class="" vAlign=top align=right width=126&gt;8.72%&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=256&gt;Pet Shop 4.0 (Buy some pets)&lt;/TD&gt;
&lt;TD class="" vAlign=top align=right width=106&gt;21.54&lt;/TD&gt;
&lt;TD class="" vAlign=top align=right width=129&gt;23.04&lt;/TD&gt;
&lt;TD class="" vAlign=top align=right width=129&gt;6.99%&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;* Average throughput, over a set of runs, on 4 proc dual core servers with W2K3 SP1, 16 Gb. of RAM, with a sample average load (not by far peak capacity). Hardware differences, network conditions and the way your scenario is written affect performance, among many other things, so your mileage may vary.&lt;/P&gt;
&lt;P&gt;You can find the code for &lt;A href="http://msdn2.microsoft.com/en-us/library/aa479070.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa479070.aspx"&gt;Petshop here&lt;/A&gt;, and here I paste a sample of code similar to our main test loop (which is run in multiple threads, by our test harness. Remember that most SqlClient classes are not thread-safe, so your code shouldn't use the same object in two different threads):&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;FONT face="Courier New"&gt;public void SqlReader() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (SqlConnection conn = new SqlConnection(_connectionString)) { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn.Open(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlCommand cmd = new SqlCommand(_sql, conn);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (SqlDataReader reader = cmd.ExecuteReader()) { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int fields = reader.FieldCount; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (reader.Read()) { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 0; i &amp;lt; fields; i++) { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; object obj = reader.GetValue(i); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;} &lt;BR&gt;&lt;BR&gt;public void DataSetInsert() { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlConnection conn = new SqlConnection(_connectionString); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataSet ds = new DataSet(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlDataAdapter adp = new SqlDataAdapter(_sql, conn); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; adp.Fill(ds, "atable"); &lt;BR&gt;} &lt;BR&gt;&lt;/FONT&gt;&lt;/BLOCKQUOTE&gt;&lt;/DIV&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7295577" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/adonet/archive/tags/ADO.NET/default.aspx">ADO.NET</category><category domain="http://blogs.msdn.com/adonet/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.msdn.com/adonet/archive/tags/Petshop/default.aspx">Petshop</category><category domain="http://blogs.msdn.com/adonet/archive/tags/2.0+SP1/default.aspx">2.0 SP1</category></item></channel></rss>