当堆包含数百万个对象时,如何将 !dumpheap 的输出转储到文件中?
How to dump the output of !dumpheap into a file, when the heap contains millions of objects?
请注意:
0:000> !dumpheap -stat
Statistics:
MT Count TotalSize Class Name
000007fefa9c8c58 1 24 System.ServiceProcess.Res
000007fef99d3de8 1 24 System.Collections.Generic.GenericArraySortHelper`1[[System.DateTime, mscorlib]]
000007fef99cf8e8 1 24 System.Collections.Generic.GenericComparer`1[[System.Decimal, mscorlib]]
...
000007fef8f02090 47295 141585288 System.Char[]
000007fe9b1cbe20 1064155 229857480 Xyz.DataServices.Platform.BalanceTransactionForAccrualByOrg
000007fef8f06888 21401 238104833 System.Byte[]
000007fe9cd2efb8 1211503 358604888 Xyz.DataServices.Platform.AEBalanceTransaction
0000000000386b30 11759620 1701611244 Free
000007fef8e94918 777049 2352540408 System.Object[]
000007fe9c4370e8 10571587 2621753576 Xyz.DB.DL.HREEmployeeManager
000007fef8f00e08 131198125 1859306044 System.String
Total 163792779 objects
Fragmented blocks larger than 0.5 MB:
Addr Size Followed by
...
这意味着我的堆上有数千万(数亿?)个对象。我想把关于他们的信息转储到一个文件中。
所以 告诉我方法,但当我们谈论数十(数百?)数百万行时,这是我们可以获得的最佳方法吗?
我想知道是否有程序 API 我可以根据它直接从转储中提取数据,而不是通过 WinDBG 用户界面。或者也许已经有一个插件可以做到这一点...
一天结束时,我使用 CDB 为 运行 单个调试器命令编写了一个 powershell 脚本。然后将输出保存到文件中。
这里是:
param(
[Parameter(Mandatory=$true, Position = 0)][ValidateScript({Test-Path $_ })]
$dump,
[Parameter(ParameterSetName='cmd', Mandatory=$true, Position = 1)][ValidateNotNullOrEmpty()]
$command,
[Parameter(ParameterSetName='script', Mandatory=$true)][ValidateNotNullOrEmpty()]
$scriptFile,
[Parameter(ParameterSetName='init', Mandatory=$true)][ValidateNotNullOrEmpty()][switch]
$init,
[Parameter()]
$imagePath,
[Parameter()]
$sosexPath = "e:\utils\sosex\sosex.dll",
[Parameter()][switch]
$ScanForImages,
[Parameter()][switch]
$NoSymbolServer,
[Parameter()][switch]
$NoExit
)
$dump = (dir $dump).FullName
$cdb = "C:\Program Files (x86)\Windows Kits.1\Debuggers\x64\cdb.exe"
$InternalScriptFile = [io.path]::GetTempFileName()
$log = [io.path]::GetTempFileName()
if ($ScanForImages)
{
$ImgScan = ".imgscan /l"
}
Set-Content $InternalScriptFile @"
.logopen `"${log}.init`"
.load $sosexPath
"@
if ($init)
{
$CDBOutputDevice = "Out-Default"
Add-Content $InternalScriptFile @"
.logclose
!bhi
"@
}
elseif ($command)
{
$CDBOutputDevice = "Out-Null"
Add-Content $InternalScriptFile @"
!lhi
$ImgScan
.logclose
.logopen `"${log}`"
$command
.logclose
"@
}
else
{
$CDBOutputDevice = "Out-Null"
Add-Content $InternalScriptFile @"
!lhi
$ImgScan
.logclose
.logopen `"${log}`"
"@
Get-Content $scriptFile | Out-File -FilePath $InternalScriptFile -Encoding ASCII -Append
Add-Content $InternalScriptFile @"
.logclose
"@
}
if ($NoExit)
{
$CDBOutputDevice = "Out-Default"
}
else
{
Add-Content $InternalScriptFile @"
q
"@
}
if ($NoSymbolServer)
{
$symbols = "e:\Symbols"
}
else
{
$symbols = "cache*e:\Symbols;srv*http://localhost:33417;srv*http://msdl.microsoft.com/download/symbols"
}
if (Test-Path $imagePath -PathType Container)
{
$symbols = "$imagePath;$symbols"
}
&$cdb -cf $InternalScriptFile -z $dump -y $symbols | &$CDBOutputDevice
if (!$init -and !$NoExit)
{
cat $log
}
不理想 - 我愿意改进。但它有效。
请注意:
0:000> !dumpheap -stat
Statistics:
MT Count TotalSize Class Name
000007fefa9c8c58 1 24 System.ServiceProcess.Res
000007fef99d3de8 1 24 System.Collections.Generic.GenericArraySortHelper`1[[System.DateTime, mscorlib]]
000007fef99cf8e8 1 24 System.Collections.Generic.GenericComparer`1[[System.Decimal, mscorlib]]
...
000007fef8f02090 47295 141585288 System.Char[]
000007fe9b1cbe20 1064155 229857480 Xyz.DataServices.Platform.BalanceTransactionForAccrualByOrg
000007fef8f06888 21401 238104833 System.Byte[]
000007fe9cd2efb8 1211503 358604888 Xyz.DataServices.Platform.AEBalanceTransaction
0000000000386b30 11759620 1701611244 Free
000007fef8e94918 777049 2352540408 System.Object[]
000007fe9c4370e8 10571587 2621753576 Xyz.DB.DL.HREEmployeeManager
000007fef8f00e08 131198125 1859306044 System.String
Total 163792779 objects
Fragmented blocks larger than 0.5 MB:
Addr Size Followed by
...
这意味着我的堆上有数千万(数亿?)个对象。我想把关于他们的信息转储到一个文件中。
所以
我想知道是否有程序 API 我可以根据它直接从转储中提取数据,而不是通过 WinDBG 用户界面。或者也许已经有一个插件可以做到这一点...
一天结束时,我使用 CDB 为 运行 单个调试器命令编写了一个 powershell 脚本。然后将输出保存到文件中。
这里是:
param(
[Parameter(Mandatory=$true, Position = 0)][ValidateScript({Test-Path $_ })]
$dump,
[Parameter(ParameterSetName='cmd', Mandatory=$true, Position = 1)][ValidateNotNullOrEmpty()]
$command,
[Parameter(ParameterSetName='script', Mandatory=$true)][ValidateNotNullOrEmpty()]
$scriptFile,
[Parameter(ParameterSetName='init', Mandatory=$true)][ValidateNotNullOrEmpty()][switch]
$init,
[Parameter()]
$imagePath,
[Parameter()]
$sosexPath = "e:\utils\sosex\sosex.dll",
[Parameter()][switch]
$ScanForImages,
[Parameter()][switch]
$NoSymbolServer,
[Parameter()][switch]
$NoExit
)
$dump = (dir $dump).FullName
$cdb = "C:\Program Files (x86)\Windows Kits.1\Debuggers\x64\cdb.exe"
$InternalScriptFile = [io.path]::GetTempFileName()
$log = [io.path]::GetTempFileName()
if ($ScanForImages)
{
$ImgScan = ".imgscan /l"
}
Set-Content $InternalScriptFile @"
.logopen `"${log}.init`"
.load $sosexPath
"@
if ($init)
{
$CDBOutputDevice = "Out-Default"
Add-Content $InternalScriptFile @"
.logclose
!bhi
"@
}
elseif ($command)
{
$CDBOutputDevice = "Out-Null"
Add-Content $InternalScriptFile @"
!lhi
$ImgScan
.logclose
.logopen `"${log}`"
$command
.logclose
"@
}
else
{
$CDBOutputDevice = "Out-Null"
Add-Content $InternalScriptFile @"
!lhi
$ImgScan
.logclose
.logopen `"${log}`"
"@
Get-Content $scriptFile | Out-File -FilePath $InternalScriptFile -Encoding ASCII -Append
Add-Content $InternalScriptFile @"
.logclose
"@
}
if ($NoExit)
{
$CDBOutputDevice = "Out-Default"
}
else
{
Add-Content $InternalScriptFile @"
q
"@
}
if ($NoSymbolServer)
{
$symbols = "e:\Symbols"
}
else
{
$symbols = "cache*e:\Symbols;srv*http://localhost:33417;srv*http://msdl.microsoft.com/download/symbols"
}
if (Test-Path $imagePath -PathType Container)
{
$symbols = "$imagePath;$symbols"
}
&$cdb -cf $InternalScriptFile -z $dump -y $symbols | &$CDBOutputDevice
if (!$init -and !$NoExit)
{
cat $log
}
不理想 - 我愿意改进。但它有效。