ComputerScience

Matthieu TUDURY… Just another WordPress site…

Production debugging : 100% CPU dans une application ASP.NET

Le but de cet article est de donner deux méthodes (la simple, l'avancée) permettant de trouver la cause d'un 100% CPU qui ne se produit que sur un environnement de production sur lequel nous n'avons pas toute la panoplie d'outils nous permettant de trouver rapidement la cause.

(Les ecrans qui suivent sont sur Windows 2008 R2)

Diagnostiques de base

Avant de passer dans les diagnostiques avancés, nous allons commencer par essayer d'isoler une URL qui génère ce probleme.

A l'aide de l'outil d'administration de IIS, au niveau serveur, on peut afficher la liste des processus généré par IIS.

Pour chaque process, il est possible de voir la liste des Requetes.

Et de trouver ainsi celle qui pose probleme dans un cas particulier.

A l'aide de ces requetes on a un déjà une bonne idée d'ou peut se situer le probleme.

Diagnostiques avancés

Connaitre la liste des requetes ne résoud pas pour autant le probleme dans tous les cas (cas ou cela ne depend pas de la requete mais d'un evenement exterieur…). Et il faudrait au minimum savoir quel bout de code génère ce 100% CPU. S'il n'est pas facile de le connaitre de prime abord, il est possible à l'aide de la stack trace des thread en cours d'execution de savoir approximativement ou se trouve le probleme.

Le principe qui va etre appliqué pour ce diagnostique avancé, sera de prendre des images du processus en cours et de regarder dans quel partie du code se trouve le programme. A l'aide de plusieurs de ces images prises a des moments différents, on va pouvoir grossierement déterminer ou se trouve le bout de code en cause.

Prérequis

Il faut commencer par télécharger les debugging tools pour windows et les installer sur le serveur ou le problème se produit : (Voir plus bas une méthode par le gestionnaire de tache ne nécessitant pas ce prérequis sur le serveur)

http://msdn.microsoft.com/en-us/windows/hardware/gg463009.aspx

Une fois installé dans le dossier de destination vous devez avoir l'outils adplus.exe :

Récupération du Process ID

Repérer le PID du processus ASP.NET qui pose problème à l'aide du gestionnaire de taches (Menu View > Select columns) :

Enregistrement d'images mémoires (Dumps)

Nous allons utiliser adplus.exe pour générer un Dump complet du processus que nous pourrons analyser à l'aide de l'outil WinDbg.

Prenons comme exemple ou le processus w3wp.exe utilisant la majorité du CPU est le PID : 3376, et nous crérons un dossier c:\dumps qui contiendra l'ensemble des dumps du processus.

adplus.exe -hang -p 3376 -quiet -o c:\dumps

Patienter environ 10s après que le programme vous ait rendu la main.

Il vous faudra reproduire cette actions plusieurs fois lorsque le probleme se produit. Attention le process est mis en pause (freezer) pendant les quelques secondes du Dump mémoire et ne répondra donc plus aux requetes utilisateurs pendant cette durée.

Dump sans ADPlus

Si vous n'avez pas le temps d'installer ADPlus, vous pouvez tout de même effectué des dumps directement depuis le gestionnaire des taches (TaskManager). Pour cela, dans l'onglet process, faites un clic droit sur le process en question, puis Create Dump File.

Analyse d'une image mémoire (dump)

En plus de AdPlus, les debugging tools incluent l'outils WinDbg que vous trouverez dans votre menu démarrer.

Lancez cet outil. (attention à executer celui correspondant à votre architecture à debugger : x64 ou x86)

Ouvrez le Dump en utilisant : File > Open Crash Dump et en allant chercher le dump qui a été généré dans le dossier que vous avez fournit à adplus lors de l'étape précédente.

Pour qu'il soit capable de transformer des adresses dans des DLLs en Nom de méthode, vous allez devoir charger les symbols. Le plus simple est de laisser WinDbg le faire tout seul en lui indiquant le serveur de Microsoft adapté.

SRV*c:\temp*http://msdl.microsoft.com/download/symbols

Adapter WinDbg aux diagnostiques de code .NET :

dans la fenêtre command :

.loadby sos clr

Maintenant il ne reste plus qu'a lister la pile des appels (call stack) de l'ensemble des threads pour récupérer l'emplacement d'execution à l'instant de ce dump mémoire.

Pour cela la commande ci-dessous a exécuter dans la fenêtre de commande va lister l'ensemble des piles d'appels dans les processus et threads en cours d'execution dans ce dump :

~* e !clrstack

Maintenant, il reste a partir de ces informations a en déduire le problème.

plus d'informations :