Démarrage rapide : analyser les données d’utilisation de l’UC dans Visual Studio (code managé)Quickstart: Analyze CPU usage data in Visual Studio (Managed Code)

Visual Studio fournit de nombreuses fonctionnalités puissantes qui vous permettent d’analyser les problèmes de performances dans votre application.The Visual Studio provides many powerful features to help you analyze performance issues in your application. Cette rubrique vous offre un moyen rapide de vous familiariser avec quelques-unes des fonctionnalités de base.This topic provides a quick way to learn some of the basic features. Ici, nous allons examiner l’outil pour identifier les goulots d’étranglement de performances liés à une utilisation élevée de l’UC.Here, we look at the tool to identify performance bottlenecks due to high CPU usage. Les outils de diagnostics sont pris en charge pour le développement .NET dans Visual Studio (y compris ASP.NET) et pour le développement natif/C++.The Diagnostics Tools are supported for .NET development in Visual Studio, including ASP.NET, and for native/C++ development.

Le hub de diagnostic propose de nombreuses autres options pour exécuter et gérer votre session de diagnostic.The Diagnostic hub offers you a lot of other options to run and manage your diagnostics session. Si l’outil Utilisation de l’UC décrit ici ne vous fournit pas les données dont vous avez besoin, les autres outils de profilage fournissent d’autres types d’informations qui peuvent vous être utiles.If the CPU Usage tool described here does not give you the data that you need, the other profiling tools provide different kinds of information that might be helpful to you. Dans de nombreux cas, le goulot d’étranglement des performances de votre application peut ne pas provenir de votre processeur, mais de la mémoire, de l’interface utilisateur de rendu ou du temps de requête réseau.In many cases, the performance bottleneck of your application may be caused by something other than your CPU, such as memory, rendering UI, or network request time. Le hub de diagnostic vous offre de nombreuses autres options pour enregistrer et analyser ce type de données.The Diagnostics hub offers you a lot of other options to record and analyze this kind of data.

Note

Pour .NET Core et ASP.NET Core, l’outil Utilisation de l’UC ne fournit pas de résultats précis avec les fichiers PBD portables.For .NET Core and ASP.NET Core, the CPU Usage tool currently does not provide accurate results with portable PBDs. Utilisez des fichiers PDB complets à la place.Use full PDBs instead.

Créer un projetCreate a project

  1. Dans Visual Studio, sélectionnez Fichier > Nouveau projet.In Visual Studio, choose File > New Project.

  2. Sous Visual C# ou Visual Basic, choisissez Windows Desktop puis, dans le volet central, choisissez Application console (.NET Framework).Under Visual C# or Visual Basic, choose Windows Desktop, and then in the middle pane choose Console App (.NET Framework).

  3. Tapez un nom tel que MyProfilerApp et cliquez sur OK.Type a name like MyProfilerApp and click OK.

    Visual Studio crée le projet.Visual Studio creates the project.

  4. Ouvrez le fichier Program.cs et remplacez tout le code par le code suivant :Open Program.cs and replace all the code with the following code:

    using System;
    using System.Threading;
    public class ServerClass
    {
        const int MIN_ITERATIONS = int.MaxValue / 1000;
        const int MAX_ITERATIONS = MIN_ITERATIONS + 10000;
    
        long m_totalIterations = 0;
        readonly object m_totalItersLock = new object();
        // The method that will be called when the thread is started.
        public void DoWork()
        {
            Console.WriteLine(
                "ServerClass.InstanceMethod is running on another thread.");
    
            var x = GetNumber();
        }
    
        private int GetNumber()
        {
            var rand = new Random();
            var iters = rand.Next(MIN_ITERATIONS, MAX_ITERATIONS);
            var result = 0;
            lock (m_totalItersLock)
            {
                m_totalIterations += iters;
            }
            // we're just spinning here
            // and using Random to frustrate compiler optimizations
            for (var i = 0; i < iters; i++)
            {
                result = rand.Next();
            }
            return result;
        }
    }
    
    public class Simple
    {
        public static void Main()
        {
            for (int i = 0; i < 200; i++)
            {
                CreateThreads();
            }
        }
        public static void CreateThreads()
        {
            ServerClass serverObject = new ServerClass();
    
            Thread InstanceCaller = new Thread(new ThreadStart(serverObject.DoWork));
            // Start the thread.
            InstanceCaller.Start();
    
            Console.WriteLine("The Main() thread calls this after "
                + "starting the new InstanceCaller thread.");
    
        }
    }
    
    Imports System
    Imports System.Threading
    
    Namespace MyProfilerApp
        Public Class ServerClass
            Const MIN_ITERATIONS As Integer = Integer.MaxValue / 1000
            Const MAX_ITERATIONS As Integer = MIN_ITERATIONS + 10000
    
            Private m_totalIterations As Long = 0
            ReadOnly m_totalItersLock As New Object()
            ' The method that will be called when the thread is started.
            Public Sub DoWork()
                Console.WriteLine("ServerClass.InstanceMethod is running on another thread.")
    
                Dim x = GetNumber()
            End Sub
    
            Private Function GetNumber() As Integer
                Dim rand = New Random()
                Dim iters = rand.[Next](MIN_ITERATIONS, MAX_ITERATIONS)
                Dim result = 0
                SyncLock m_totalItersLock
                    m_totalIterations += iters
                End SyncLock
                ' we're just spinning here
                ' and using Random to frustrate compiler optimizations
                For i As Integer = 0 To iters - 1
                    result = rand.[Next]()
                Next
                Return result
            End Function
        End Class
    
        Public Class Simple
            Public Shared Sub Main()
                For i As Integer = 0 To 199
                    CreateThreads()
                Next
            End Sub
            Public Shared Sub CreateThreads()
                Dim serverObject As New ServerClass()
    
                Dim InstanceCaller As New Thread(New ThreadStart(AddressOf serverObject.DoWork))
                ' Start the thread.
                InstanceCaller.Start()
    
                Console.WriteLine("The Main() thread calls this after " + "starting the new InstanceCaller thread.")
    
            End Sub
        End Class
    End Namespace
    

    Note

    En Visual Basic, vérifiez que l’objet de démarrage est défini sur Sub Main (Propriétés > Applications > Objet de démarrage).In Visual Basic, make sure the startup object is set to Sub Main (Properties > Application > Startup Object).

Étape 1 : Collecter les données de profilageStep 1: Collect profiling data

  1. Tout d’abord, définissez un point d’arrêt dans votre application sur cette ligne de code dans la fonction Main :First, set a breakpoint in your app on this line of code in the Main function:

    for (int i = 0; i < 200; i++)

    ou, pour Visual Basic :or, for Visual Basic:

    For i As Integer = 0 To 199

    Définissez un point d’arrêt en cliquant dans la marge à gauche de la ligne de code.Set a breakpoint by clicking in the gutter to the left of the line of code.

  2. Ensuite, définissez un deuxième point d’arrêt sur l’accolade fermante à la fin de la fonction Main :Next, set a second breakpoint on the closing brace at the end of the Main function:

    Définir des points d’arrêt pour le profilageSet breakpoints for profiling

    Conseil

    En définissant deux points d’arrêt, vous limitez la collecte de données aux sections de code que vous souhaitez analyser.By setting two breakpoints, you can limit data collection to the parts of code that you want to analyze.

  3. La fenêtre Outils de diagnostic est déjà visible, sauf si vous l’avez désactivée.The Diagnostic Tools window is already visible unless you have turned it off. Pour réafficher la fenêtre, cliquez sur Déboguer / Fenêtres / Afficher les outils de diagnostic.To bring up the window again, click Debug / Windows / Show Diagnostic Tools.

  4. Cliquez sur Déboguer / Démarrer le débogage (ou Démarrer dans la barre d’outils, ou F5).Click Debug / Start Debugging (or Start on the toolbar, or F5).

    Quand l’application est chargée, la vue Résumé des outils de diagnostics s’affiche.When the app finishes loading, the Summary view of the Diagnostics Tools appears.

  5. Pendant que le débogueur est suspendu, activez la collecte des données d’utilisation de l’UC en choisissez Enregistrer le profil du processeur, puis ouvrez l’onglet Utilisation de l’UC.While the debugger is paused, enable the collection of the CPU Usage data by choosing Record CPU Profile, and then open the CPU Usage tab.

    Activation du profilage de l’UC dans les outils de diagnosticDiagnostics Tools Enable CPU Profiling

    Quand la collecte des données est activée, le bouton d’enregistrement affiche un cercle rouge.When data collection is enabled, the record button displays a red circle.

    Quand vous choisissez Enregistrer le profil du processeur, Visual Studio commence l’enregistrement de vos fonctions (notamment leur durée d’exécution) et fournit un graphique chronologique qui vous permet de vous concentrer sur des segments spécifiques de la session d’échantillonnage. Vous pouvez afficher ces données collectées uniquement quand votre application est interrompue à un point d’arrêt.When you choose Record CPU Profile, Visual Studio will begin recording your functions and how much time they take to execute, and also provides a timeline graph you can use to focus on specific segments of the sampling session.You can only view this collected data when your application is halted at a breakpoint.

  6. Appuyez sur F5 pour exécuter l’application jusqu’au deuxième point d’arrêt.Hit F5 to run the app to your second breakpoint.

    Vous disposez maintenant de données de performances pour votre application, et plus spécifiquement pour la région de code qui s’exécute entre les deux points d’arrêt.Now, you now have performance data for your application specifically for the region of code that runs between the two breakpoints.

    Le profileur commence la préparation des données de thread.The profiler begins preparing thread data. Attendez qu’elle se termine.Wait for it to finish.

    L’outil Utilisation de l’UC affiche le rapport sous l’onglet Utilisation de l’UC.The CPU Usage tool displays the report in the CPU Usage tab.

    À ce stade, vous pouvez commencer à analyser les données.At this point, you can begin to analyze the data.

Étape 2 : Analyser les données d’utilisation de l’UCStep 2: Analyze CPU usage data

Nous vous recommandons de commencer à analyser vos données en examinant la liste des fonctions située sous l’onglet Utilisation de l’UC, en identifiant les fonctions qui effectuent la plus grande partie du travail, puis en analysant ces fonctions les unes après les autres.We recommend that you begin analyzing your data by examining the list of functions under CPU Usage, identifying the functions that are doing the most work, and then taking a closer look at each one.

  1. Dans la liste des fonctions, examinez celles qui effectuent le plus de travail.In the function list, examine the functions that are doing the most work.

    Outils de diagnostics - Onglet Utilisation de l’UCDiagnostics Tools CPU Usage Tab

    Conseil

    Les fonctions sont classées par ordre et ce sont celles qui effectuent le plus de travail qui figurent en haut de la liste (elles ne sont pas classées selon leur ordre d’appel).Functions are listed in order starting with those doing the most work (they're not in call order). Ainsi, vous pouvez identifier rapidement les fonctions avec les temps d’exécution les plus longs.This helps you quickly identify the longest running functions.

  2. Dans la liste des fonctions, double-cliquez sur la fonction ServerClass::GetNumber.In the function list, double-click the ServerClass::GetNumber function.

    Quand vous double-cliquez sur la fonction, la vue Appelant/appelé s’ouvre dans le volet gauche.When you double-click the function, the Caller/Callee view opens in the left pane.

    Outils de diagnostics - Vue Appelant/appeléDiagnostics Tools Caller Callee View

    Dans cette vue, la fonction sélectionnée apparaît dans le titre et dans la zone Fonction active (ici, GetNumber).In this view, the selected function shows up in the heading and in the Current Function box (GetNumber, in this example). La fonction qui a appelé la fonction active s’affiche sur la gauche sous Fonctions appelantes, et toutes les fonctions appelées par la fonction active s’affichent dans la zone Fonctions appelées située à droite.The function that called the current function is shown on the left under Calling Function, and any functions called by the current function are shown in Called Functions box on the right. Vous pouvez sélectionner l’une ou l’autre de ces zones pour modifier la fonction active.(You can select either box to change the current function.)

    Cette vue montre la durée totale (en ms), ainsi que le pourcentage du temps global d’exécution de l’application, nécessaires à l’exécution de la fonction.This view shows you the total time (ms) and the percentage of the overall app running time that the function has taken to complete.

    La section Corps de la fonction montre également la durée totale (et le pourcentage correspondant) passée dans le corps de la fonction, à l’exclusion du temps passé dans les fonctions appelantes et appelées.Function Body also shows you the total amount of time (and the percentage of time) spent in the function body excluding time spent in calling and called functions. (Dans cette illustration, 2856 ms sur 2863 ont été passées dans le corps de la fonction. Le temps restant (<20 ms) a été passé dans du code externe appelé par cette fonction.)(In this illustration, 2856 out of 2863 ms were spent in the function body, and the remaining time (<20 ms) was spent in external code called by this function). Les valeurs réelles seront différentes, en fonction de votre environnement.Actual values will be different depending on your environment.

    Conseil

    Des valeurs élevées dans le corps de la fonction peuvent indiquer un goulot d’étranglement de performances au sein de la fonction.High values in Function Body may indicate a performance bottleneck within the function itself.

Étapes suivantesNext steps

Voir aussiSee Also