<?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>Parallel Programming with .NET : Testing</title><link>http://blogs.msdn.com/pfxteam/archive/tags/Testing/default.aspx</link><description>Tags: Testing</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Debugger display of PLINQ queries</title><link>http://blogs.msdn.com/pfxteam/archive/2008/01/15/7119154.aspx</link><pubDate>Tue, 15 Jan 2008 21:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7119154</guid><dc:creator>toub</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/pfxteam/comments/7119154.aspx</comments><wfw:commentRss>http://blogs.msdn.com/pfxteam/commentrss.aspx?PostID=7119154</wfw:commentRss><wfw:comment>http://blogs.msdn.com/pfxteam/rsscomments.aspx?PostID=7119154</wfw:comment><description>&lt;P&gt;Sometimes very simple additions to an API or implementation make me happy.&amp;nbsp; One such&amp;nbsp;nicety in the CTP of PLINQ is the implementation of ToString on the concrete types that represent query operators.&amp;nbsp; These implementations provide a textual representation of the query structure, which can be very nice for debugging purposes.&lt;/P&gt;
&lt;P&gt;Consider the following LINQ query, using the implementation of LINQ-to-Objects that shipped with Visual Studio 2008:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var q = &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from x in list1&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from y in list2 &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; where x == y &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; select x.Length;&lt;/P&gt;
&lt;P&gt;If I hover over the 'q' variable in the debugger, I see the following:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image.png" atomicselection="true" mce_href="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=90 alt=image src="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_thumb.png" width=422 border=0 mce_src="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Based on the type displayed in the debugger tip, I'm only able to discern the type of the last operator in the query (the Select).&amp;nbsp; If I change this to use PLINQ:&lt;/P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var q = &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from x in list1&lt;STRONG&gt;.AsParallel()&lt;/STRONG&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from y in list2 &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; where x == y &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; select x.Length; 
&lt;P&gt;I get a much better understanding of the query in the debugger tip:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_2.png" atomicselection="true" mce_href="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_2.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=85 alt=image src="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_thumb_2.png" width=769 border=0 mce_src="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_thumb_2.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Here's the text from the tip (in case it's difficult to make out in the image):&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;{SelectQueryOperator`2(WhereQueryOperator`1(SelectManyQueryOperator`3&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (ScanQueryOperator`1(ParallelEnumerableWrapper`1))))}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;From this, we can see that the query contains a Select that operates on a Where that operates on a SelectMany.&amp;nbsp; Our ability to do this is a side-benefit of PLINQ's need to analyze the query structure in order to parallelize it; as part of that, we walk the query tree building up information about it, and we store that information in data structures that are then visible to the implementation and to the debugger.&amp;nbsp; The base query operator types in PLINQ override ToString to provide this information, such that the debugger tip is able to display it to you.&lt;/P&gt;
&lt;P&gt;To see other related benefits, consider another LINQ example:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var q = &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from x in Enumerable.Range(0, 100)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; select x * x; 
&lt;P&gt;If at a later point I'd like to analyze this query in the debugger, there's very little information I can glean from it:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_3.png" atomicselection="true" mce_href="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_3.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=120 alt=image src="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_thumb_3.png" width=529 border=0 mce_src="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_thumb_3.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;With PLINQ, I can actually drill down and look at details such as the bounds on the range:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_4.png" atomicselection="true" mce_href="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_4.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=246 alt=image src="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_thumb_4.png" width=758 border=0 mce_src="http://blogs.msdn.com/blogfiles/pfxteam/WindowsLiveWriter/DebuggerdisplayofPLINQqueries_F10E/image_thumb_4.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;(You can actually get the same information with the original LINQ-to-Object sample, but to do so&amp;nbsp;you need to first call GetEnumerator on the IEnumerable&amp;lt;T&amp;gt; and then call MoveNext on the returned IEnumerator&amp;lt;T&amp;gt; in order to initialize the relevant fields in the resulting&amp;nbsp;compiler-generated types.)&lt;/P&gt;
&lt;P&gt;Pretty neat. Keep in mind that the debugger is able to provide insight into the internals of the system, but these internals will likely change from release to release in the future, so you shouldn't rely in any way on them staying the&amp;nbsp;same.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7119154" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/pfxteam/archive/tags/PLINQ/default.aspx">PLINQ</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Testing/default.aspx">Testing</category><category domain="http://blogs.msdn.com/pfxteam/archive/tags/Parallel+Extensions/default.aspx">Parallel Extensions</category></item></channel></rss>