Debugger display of PLINQ queries

Stephen Toub - MSFT

Sometimes very simple additions to an API or implementation make me happy.  One such nicety in the CTP of PLINQ is the implementation of ToString on the concrete types that represent query operators.  These implementations provide a textual representation of the query structure, which can be very nice for debugging purposes.

Consider the following LINQ query, using the implementation of LINQ-to-Objects that shipped with Visual Studio 2008:

    var q =
        from x in list1 
        from y in list2
        where x == y
        select x.Length;

If I hover over the ‘q’ variable in the debugger, I see the following:

image

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).  If I change this to use PLINQ:

    var q =
        from x in list1.AsParallel()
        from y in list2
        where x == y
        select x.Length;

I get a much better understanding of the query in the debugger tip:

image

Here’s the text from the tip (in case it’s difficult to make out in the image):

{SelectQueryOperator`2(WhereQueryOperator`1(SelectManyQueryOperator`3
    (ScanQueryOperator`1(ParallelEnumerableWrapper`1))))}

From this, we can see that the query contains a Select that operates on a Where that operates on a SelectMany.  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.  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.

To see other related benefits, consider another LINQ example:

    var q =
        from x in Enumerable.Range(0, 100)
        select x * x;

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:

image

With PLINQ, I can actually drill down and look at details such as the bounds on the range:

image

(You can actually get the same information with the original LINQ-to-Object sample, but to do so you need to first call GetEnumerator on the IEnumerable<T> and then call MoveNext on the returned IEnumerator<T> in order to initialize the relevant fields in the resulting compiler-generated types.)

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 same.

0 comments

Discussion is closed.

Feedback usabilla icon