Nous devons comprendre quelle partie de notre code (ou tierce partie, probablement CLR-CLR) conduit à la boxe d'entiers. P>
Nous avons une application assez grosse sur laquelle nous observons un taux d'allocation élevé de Tout notre code a été spécifiquement écrit pour éliminer la boxe dans la mesure du possible, et "par conception" Nous sommes censés ne pas voir des bocults du tout. Nous soupçonnons donc que c'est une boxe oubliée non éliminée dans notre code ou une boxe causée par le composant tiers et / ou le type CLR Type lui-même. P>
Système est compilé à l'aide de VS2008 et utilise .NET 3.5 (les mesures ont été effectuées dans les bâtiments de débogage et de libération, avec le même comportement). P>
Comment pouvons-nous (utiliser WINDBG, VS2008, le profileur de mémoire, AQTime ou tout autre produit disponible dans le commerce) Détecter pourquoi la boxe se produit? P> System.int32 code> instances. Avec l'aide du profileur de mémoire, nous voyons un petit nombre d'instances existantes int32 code> (18, pour être exactes) et 20-25 milliers de int32 code> allocations par seconde. Tous ces objets sont collectés GC en tant qu'objets GEN0, le système n'a pas de fuites de mémoire et peut être couru pendant longtemps. Lorsque la mémoire instantanée de mémoire est créée, GC est exécuté avant instantané, il ne contient donc aucune trace de ces objets «temporaires». P>
Question h3>
6 Réponses :
Avez-vous fait une analyse statique de votre code? Peut-être que NDEPEND peut vous aider à trouver les méthodes et les types de valeurs de boxe et de non-boîte. P>
Une version d'essai de Ndepend est disponible gratuitement, il serait donc utile d'essayer d'analyser les assemblées, à la fois le vôtre et la ti 3e partie. P>
Nous avons une licence pour NDEPEND, mais il n'est pas pratique de l'utiliser à cet effet - nous avons de nombreux "potentiels" boxe (dans le cadre de la journalisation des erreurs, par exemple), qui ne se produisent jamais dans le scénario actuel. De plus, Ndepend ne suit pas la ligne de source où le problème se produit. Quoi qu'il en soit, dans ce problème de cas spécifique a été suivi au code CLR.
Je pense GlowCode peut signaler que la boxe des types de valeur est survenue, bien que vous ayez besoin de pêcher à travers le options pour savoir comment allumer. p>
Une approche très basse tech, mais étonnamment efficace consiste à joindre un débogueur et à chaque fois frappé une pause, et voir où le programme s'arrête. P>
Si vous allociez une quantité de temps suffisante pour déclencher une grande activité de GC, vous risquez de faire une bonne chance d'interrompre le code où l'allocation de boxe se produit. P>
Cela a l'avantage d'avoir besoin d'aucun nouvel outil (en supposant que vous ayez un IDE ou un débogueur décent) P>
Les opérations de boxe et de non-coffre peuvent être détectées par analyse statique de votre code. Recherchez des règles FXCOP. P>
Un profileur peut être capable de vous aider également, car tant d'allocations par secondes entraîneront sûrement beaucoup de frais généraux. P>
bonne chance et gardez-nous posté sur vos résultats. P>
Je vais essayer des outils d'analyse statiques, bien qu'ils neatent pas la boxe originaire de composants CLR / tiers. Il se trouve que nous avons une licence Ndependends, donc je vais lui donner un profileur d'essai ne montrent rien d'important, total de la CPU est également très faible. On dirait que ces allocations / collections sont plutôt bon marché du point de vue des cycles du processeur.
Une de mes applications préférées est CLR Profiler Cela vous donnera ce que vous recherchez, vous allez mapper toute votre application montrant les différentes générations. C'est un téléchargement gratuit de Microsoft et il est extrêmement puissant et simple à utiliser. J'ai également inclus un lien pour savoir comment l'utiliser. (CLR Profiler Télécharger) a > (Comment utiliser CLR Profiler) P>
Le profileur CLR l'a affiché dans la vue d'allocations. Il a fallu très longtemps pour capturer le tas, et il s'est presque écrasé sur notre petite application de test, mais nous a toujours aidé à résoudre le casse-tête. Le problème a été suivi au code CLR - voir la mise à jour dans ma question.
J'aurais dû mentionner que le profileur CLR est très intrusif du point de vue de la performance. Donc, cela devrait toujours être à l'arrière de l'esprit d'une personne lors de l'utilisation. Peu importe que c'est un excellent outil d'avoir.
plutôt surprenante, les méthodes de la classe DateTime Tolocaltime / TouniversalTime provoquent une boxe. P>
Notre application (serveur d'applications) a été récemment modifiée pour fonctionner "à l'intérieur" dans l'UTC uniquement (pour faire face aux changements d'heure de la lumière du jour, etc.). Notre code clientBase est resté à 99% de temps local. p>
Serveur d'application convertit (si nécessaire) des heures locales à l'UTC fois avant le traitement, provoquant efficacement la surcharge de la boxe sur chaque opération liée à la fois. P>
Nous envisagerons de rééchaler ces opérations "dans la maison", sans la boxe. P>
Je pense que au lieu d'essayer de localiser le code que les boîtes, essayez de trouver les racines de ces boîtes en boîte, je sais que cela est possible à l'aide de Windbg bien que je ne connaisse pas assez de Windbg pour écrire une réponse ici maintenant. Si vous trouvez les racines, comme une arrachelist, vous pourrez peut-être retrouver ses racines, etc., pour trouver le champ d'une classe quelque part qui détient ceux qui les tient. Bien sûr, s'ils ne sont pas enracinés, mais des objets temporaires, que "des milliers par seconde" et "gen0" mentionent, alors je ne suis pas d'aide du tout :)
Les objets ne sont pas enracinés et sont collectés lorsque nous essayons de créer un instantané (à l'aide du profileur de mémoire). Je ne suis pas assez familier avec Windbg, donc je ne sais pas si / comment il peut être utilisé pour afficher des piles d'allocation de ces objets non enracinés.