2

我的问题是dumpheap -stat返回了大量的对象,我不知道哪些是有根的,哪些不是。

好吧,如果我在单个地址上运行!mrootor!refs命令,我可以,但是这种方法不能很好地扩展到由dumpheap.

例如,dumpheap -stat包含以下行:

000007fef3d14088    74247      2375904 Microsoft.Internal.ReadLock

哇,74,247 个实例。然而,运行

.logopen c:\tmp\2\log.txt;.foreach (entry {!dumpheap -type Microsoft.Internal.ReadLock -short}){!refs ${entry} -target};.logclose

揭示了报告的每个实例DumpHeap实际上都是未回收的垃圾!

我如何发现每个实例都是垃圾是另一个问题。我必须将所有NONE字符串提取到一个文件中,并将所有Objects referencing字符串提取到另一个文件中,然后比较每个文件中的行数。当然有更好的方法:-(。

无论如何,我想知道如何只关注有根对象。理想情况下,我想获得这些对象的统计数据和详细信息。

4

1 回答 1

4

您对所有对象的循环已经很棒了,只是需要将 !refs 命令替换为仅找到根对象的其他命令。我的示例使用字符串,因为我没有使用 ReadLocks 的应用程序。

!refs 命令有两种可能的输出。引用的对象输出例如

Objects referencing 02703f18 (System.String):
follow 02703a88       128   System.Globalization.NumberFormatInfo

垃圾对象如下所示:

Objects referencing 02703f30 (System.String):
NONE

如果第二行包含单词“follows”,您只对第一行的地址感兴趣。幸运的是,地址等于${entry},所以我们实际上不需要它。否则你会遇到和我一样的麻烦

这让我想到了这个关于 .if的问题。

您可以在 !refs 的输出上再次使用 .foreach。让我们首先在单个对象上看一下:

.foreach (reftoken {!refs 027045cc -target}) { .printf "${reftoken}\n" }

这会每行打印一个单词,我们只对第五个单词感兴趣,这意味着我们最初可以跳过 4 个项目,然后跳过其余的,这给了我们

.foreach /pS 4 /ps 3 (reftoken {!refs 027045cc -target}) { .printf "${reftoken}\n" }

出于稳健性目的,让我们使用/ps 99.
接下来我们需要检查这个令牌是否等于follow,这是由

.if ($sicmp("${reftoken}","follow") == 0) { .echo found follow }

并将它们结合在一起:

.foreach (entry {!dumpheap -type System.String -short})
{
   .foreach /pS 4 /ps 99 (reftoken {!refs ${entry} -target}) 
   { 
      .if ($sicmp("${reftoken}","follow") == 0) 
      { 
            .printf "${entry}\n"
      } 
   }
}

在一行中:

 .foreach (entry {!dumpheap -type System.String -short}){.foreach /pS 4 /ps 99 (reftoken {!refs ${entry} -target}) {.if ($sicmp("${reftoken}","follow") == 0) {.printf "${entry}\n"}}}

当然,您可以将.print替换为对您的情况有帮助的任何其他命令。

我希望您可以修改此示例以使用 ReadLock。

于 2013-12-27T22:13:31.447 回答