Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Tool Window Support for LINQ and Lambda, PerfTip and Diagnostics Tool Window in Visual Studio 2015

5.00/5 (9 votes)
14 Jun 2016CPOL9 min read 23.7K  
This article will cover other debugging improvements of VisualStudio 2015 like the tool window support for LINQ and Lambda expressions, the newperftips, and the new diagnostic tool window.

Introduction

This article is the continuation of Debugging Improvements - Day #5 of the series. The earlier part of the series covered topics like breakpoint configuration improvements and new improved error lists in Visual Studio 2015. This article will cover other debugging improvements of Visual Studio 2015 like the tool window support for LINQ and Lambda expressions, the new perftips, and the new diagnostic tool window.

Learning Visual Studio 2015 Series

Prerequisites

Visual Studio 2015 Express has been used in this tutorial to explain the concepts and features. For samples and practice, a Visual Studio solution is created having a console application named VS2015ConsoleApplication. The console application contains a MyProduct class which contains products as an entity-specific basic operations like fetching the product and returning the list of products as shown below.

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace VS2015ConsoleApplication
{
    public class MyProducts :IProducts
    {
        List<Product> _allProduct = new List<Product>();
        public MyProducts()
        {
            _allProduct.Add(new Product {ProductCode="0001",ProductName="IPhone",ProductPrice="60000",ProductType="Phone",ProductDescription="Apple IPhone" } );
            _allProduct.Add(new Product { ProductCode = "0002", ProductName = "Canvas", ProductPrice = "20000", ProductType = "Phone", ProductDescription = "Micromax phone" });
            _allProduct.Add(new Product { ProductCode = "0003", ProductName = "IPad", ProductPrice = "30000", ProductType = "Tab", ProductDescription = "Apple IPad" });
            _allProduct.Add(new Product { ProductCode = "0004", ProductName = "Nexus", ProductPrice = "30000", ProductType = "Phone", ProductDescription = "Google Phone" });
            _allProduct.Add(new Product { ProductCode = "0005", ProductName = "S6", ProductPrice = "40000", ProductType = "Phone", ProductDescription = "Samsung phone" });
 
        }
 
        /// <summary>
        /// FetchProduct having price greater that 3000
        /// </summary>
        /// <returns></returns>
        public List<Product> FetchProduct() => (from p in _allProduct where Convert.ToInt32(p.ProductPrice) > 30000 select p).ToList();
 
        /// <summary>
        /// FetchProduct
        /// </summary>
        /// <param name="pCode"></param>
        /// <returns></returns>
        public Product FetchProduct(string pCode)
        {
            return _allProduct.Find(p => p.ProductCode == pCode);
        }
 
        /// <summary>
        /// FetchProduct with productCode and productName
        /// </summary>
        /// <param name="productCode"></param>
        /// <param name="productName"></param>
        /// <returns></returns>
        public Product FetchProduct(string productCode, string productName)
        {
            return _allProduct.Find(p => p.ProductCode == productCode && p.ProductName==productName);
        }
 
        public List<Product> GetProductList()
        {
            return _allProduct;
        }
    }
}

where IProducts is a simple interface.

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace VS2015ConsoleApplication
{
    interface IProducts
    {
        Product FetchProduct(string productCode);
        Product FetchProduct(string productCode,string productName);
        List<Product> GetProductList();
    }
}

In the following Program.cs file the FetchProduct() method is called to get the list of all the products.

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace VS2015ConsoleApplication
{
    class Program
    {
        static void Main()
        {
            var myProducts = new MyProducts();
            var allProducts = myProducts.GetProductList();
            Console.ReadLine();
        }
    }
}

Tool window support for LINQ and lambda expressions

This is one of the best improvements that Visual Studio 2015 has come up with. In earlier versions of Visual Studio when a developer tries to execute/write LINQ or Lambda expressions in the immediate window or the watch window, the code was not supported and a message used to appear that LINQ and lambda expressions are not allowed in immediate or watch windows. With the newly released product i.e. Visual Studio 2015, this limitation has been taken care of. Now a developer has the liberty to execute LINQ and Lambda expressions in the immediate window. This feature proves to be very helpful in run time debugging the code, as one can write LINQ queries in immediate windows at run time to select or filter the lists or objects.

Let’s cover the topic through practical examples. We already have a solution with a console application that fetches a list of Products. To practically check this tool support feature, place a breakpoint at Console.ReadLine() in program.cs i.e. when the list is fetched.

Image 1

When we hover and try to see all products, we get list of products as shown in the below image.

Image 2

Now suppose there is a situation where a developer wants to perform certain operations for debugging at this breakpoint like checking the product name, product price of each product entity, or needs to see products that only have a price greater than 30000, then a developer has to explicitly navigate through each list item in the window opened as shown below.

Image 3

The above mentioned methodology for debugging and navigating is quite time consuming. Consider a list with 1000’s of records. One can leverage the support of LINQ and Lambda expressions in the immediate window to expedite the debugging requirements now. Suppose we need to get a list of all the ProductName in the list. Let’s see how we do this in immediate window.

Open the immediate window. You can open it through Visual Studio Debug menu as shown below. i.e. Debug->Windows->Immediate or you can use the keyboard default shortcut to open the window i.e. Ctrl+Alt+I.

Image 4

The immediate window will open at bottom of the class file and you can view the products list by typing allProducts in the window while the code execution is paused at breakpoint. You’ll get the list of products as we saw while hovering the mouse over the allProducts variable.

Image 5

Now let’s write a LINQ query to get all product names from the list of products and press enter. Notice that a list of ProductName is fetched through this LINQ query immediately.

C#
(from p in allProducts select p.ProductName).ToList();

Image 6

Likewise, you can also perform filtering over the list or execute any LINQ query that you need to execute for the sake of debugging.

In earlier versions, LINQ was not supported in the immediate window. Now let’s try this with lambda expression.

C#
allProducts.Select(p=>p.ProductName).ToList();

We get the same result.

Image 7

This is an extremely useful feature for debugging the collections or objects. You can also use LINQ and lambda in the watch window.

New PerfTips Feature

The new PerfTips feature in Visual Studio 2015 provides performance-centric information. A developer can get performance-specific information without depending upon any tool, code or stopwatch implementation. While debugging the code, the PerfTips feature displays performance information in the form of a tooltip. The tooltip shows the span of time for which the code was running. While stepping over the code, it displays the span of time that the code was running during that step. Even if we run from breakpoint to breakpoint, the PerfTip feature displays the span of time the code was running between the two breakpoints. Let’s cover this feature through practical examples. I have changed the Main method of Program.cs file to the following.

C#
static void Main()
   {
       var myProducts = new MyProducts();
       var allProducts = myProducts.GetProductList();
       foreach (var prod in allProducts)
       {
           Console.WriteLine(prod.ProductName);
       }
       foreach (var prod in allProducts)
       {
           if(Convert.ToInt32(prod.ProductPrice)>30000)
           Console.WriteLine(String.Format("ProductName : {0} and ProductPrice : {1}",prod.ProductName,prod.ProductPrice));
       }
       Console.ReadLine();
   }

Let’s place the breakpoint at the start of the first foreach loop in the Program.cs class, let's say we want to get the length of time elapsed while reaching to this line of code. Run the application.

Image 8

You can see the PerTips appeared saying time elapsed is less than 1 millisecond. We did not use any stopwatch or code or any third party tool to get this time elapsed. It is the new perfTips feature of Visual Studio 2015 that shows the time elapsed during program execution till this breakpoint. Now I will run the application again. but with one change. I have put Thread.Sleep for 10 milliseconds after both the foreach loops and placed the breakpoint there. Now when you run the application and step over the Thread.Sleep(10) breakpoint, the PerfTips feature will add that elapsed 10 millisecond too while displaying the time elapsed in previous step.

Image 9

It clearly says the time elapsed till previous step was less than or equal to 14 milliseconds. You can also get the time elapsed between two breakpoints. Let’s try to do that. Let’s put the first breakpoint at the start of the method and another at last line of the method. Now when you run the application the code execution stops at first breakpoint. Simply press F5 or continue with the execution, the execution will halt at second breakpoint, therefore showing the total time elapsed for complete method to execute.

Image 10

In our case it is less than 4 milliseconds. You can leverage the capabilities of this feature for troubleshooting performance bottle necks in your application.

Diagnostic Tool Window

The new Diagnostic Tools window in Visual Studio appears whenever you run the application with debugging.

This window provides an ample amount of information that is very helpful when debugging the application. It contains a timeline across the top that provides a temporal display of application’s debugging session.

Image 11

The diagnostic tool window can be launched via Debug-> Show Diagnostic Tools option as shown in the below image.

Image 12

Under the timeline are three important views.

  • The Debugger Events view displays breakpoint, output, and IntelliTrace events.

Image 13

  • The Memory view displays the processor or memory usage in bytes.

Image 14

  • The CPU utilization view displays the percent of processor CPU usage.

Image 15

At the bottom of the Diagnostic Tools window are tabs with additional details and options with filters. The yellow arrow shown at the bottom shows that code is currently being debugged and is stopped at breakpoint.

Image 16

use the existing code base as a sample to explore the features. Place the breakpoints at two locations as shown below in the existing Program.cs file we have been using throughout the prior articles.

Image 17

Now run the application and wait for execution to pause at break point. Now open the Diagnostic tools or press Ctrl+Alt+F2. You get following view of Diagnostic tool window.

Image 18

TimeLine

This example debugging session was 0.19 seconds from the time of application start until the current breakpoint and we are looking at about 5.5 seconds of that time here in the timeline. The black bars here and here allow you to select a portion of the timeline.

Image 19

The selected time interval, shown in white, is the area of the timeline that a developer want to focus on. You can drag either black bar to adjust the selection area. The other sections of this window adjust based on the location of the black bars. Note that since our selected area includes part of a red line in the breakpoint track, the list also displays the end of that breakpoint line.

Image 20

Debugger Events

The Debugger Events view in the Diagnostic Tools window displays events that occurred during the debugging session. This view is broken into various tracks. The Break Events track shows events which stopped execution of the application, such as breakpoints that were hit, stepping through the code or breaking exceptions. The bars indicate the amount of time the application was running in between break events. The bars in this track are color coded; red indicates a breakpoint or breaking exception, yellow indicates a step through the code, and blue indicates a break all operation.

Image 21

The blue bar indicates the time from the last breakpoint until the time that the debugging session was paused, using the Break All feature. Hover over a bar to view the elapsed time.

Image 22

The IntelliTrace track shows all of the other events collected by IntelliTrace, such as ADO.NET calls, file access, and so on. It is also color coded, black for important events, gray for less important events, and purple for custom events.

Process Memory

The Process Memory section of the Diagnostic Tools window helps you monitor the memory usage of the app while you are debugging. A memory usage tool was introduced in Visual Studio 2013 as part of the Performance and Diagnostics hub. In Visual Studio 2015, this tool was merged into the Diagnostic Tools window and enhanced. As with the current memory usage tool, you can take a memory snapshot at any point in time and compare it against another snapshot.

Image 23

In this sample debugging session you can see there is one snapshot.

Image 24

Using the memory usage tool helps you analyze the cause of memory spikes or leaks. You can also View the Heap information through Memory Usage window.

Image 25

CPU

The CPU utilization section of the Diagnostic Tools window helps you monitor the CPU usage of your application by viewing a live CPU graph.

Image 26

This graph shows you how much CPU resources are used by the code. Looking at the CPU usage with the debugger events helps you correlate spikes in CPU with the execution of the code, making it easier to debug CPU-related issues.

You can switch on CPU profiling for more detailed CPU usage statistics.

Image 27

You can use the Diagnostic Tools window to aid in your debugging process and improve productivity and performance.

Conclusion

In this article we covered two very useful and critical features of Visual Studio 2015, named PerfTip and Diagnostic Tools Window. We saw how the PerfTip can provide valuable performance information while debugging without any setup code or external tools. We saw how Diagnostic tool window can help you debug your code and monitor CPU and memory usage too.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)