使用dotnet-dump分析dotnet转储文件

有很多时候,在生产环境会产生各种各样的问题,但在生成环境计划是不能调试的,所以dotnet-dump这时就启动作用了。

除了dotnet-dump外,windows下windbg,linux下的lldb是更为强大的分析工具。

微软的文档:

https://docs.microsoft.com/zh-cn/dotnet/core/diagnostics/dotnet-dump

开始使用dotnet-dump

假设一种情况,在生成环境中线程数高,且内存溢出。

 public IActionResult Index()
        {
            _logger.LogInformation("新增一条线程。");
            Task.Run(() =>
            {
                // 添加1Mb。
                while (true)
                {
                    _logger.LogInformation("添加1Mb");
                    var buff = new byte[1024 * 1024];
                    for (int i = 0; i < buff.Length; i++)
                    {
                        buff[i] = 0;
                    }

                    _byteBag.Add(buff);
                    SpinWait.SpinUntil(() => false, 10000);
                }
            });

            return View();
        }

以上简单的设置一下,然后浏览器多刷几次。

 

 

 每刷新一次,则线程数加1,要知道系统有线程数限制,超过极限后会爆炸。

使用dotnet-dump分析

第一步收集转储文件

dotnet-dump collect -p 10504 -o dump

 

 

 第二部分析转储文件

dotnet-dump analyze dump

 

 

 分析:

> clrthreads
ThreadCount:      39
UnstartedThread:  0
BackgroundThread: 38
PendingThread:    0
DeadThread:       0
Hosted Runtime:   no
                                                                                                            Lock
 DBG   ID     OSID ThreadOBJ           State GC Mode     GC Alloc Context                  Domain           Count Apt Exception
  20    1     1f34 000001BE985BEF50  202a020 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     MTA
  32    2     32dc 000001C3A69D50D0    2b220 Preemptive  000001C258931410:000001C258931668 000001BE96B95A10 0     MTA (Finalizer)
  27    3     2488 000001C3A6A0F500  102a220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     MTA (Threadpool Worker)
  52    7     4b90 000001C3A6BEF8F0  202b220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     MTA
  29   14     29e4 000001C3A7286CB0  3029220 Preemptive  000001BFD8936AE8:000001BFD89389C0 000001BE96B95A10 0     MTA (Threadpool Worker)
  41   16     3c38 000001C3A7286010  3029220 Preemptive  000001C0989349E0:000001C098934BE8 000001BE96B95A10 0     MTA (Threadpool Worker)
   1   18      798 000001C3A7401180  3029220 Preemptive  000001C0589317B8:000001C058931CF8 000001BE96B95A10 0     MTA (Threadpool Worker)
  58   19     4ee0 000001C3A73FD260  3029220 Preemptive  000001BF58931900:000001BF58931AC8 000001BE96B95A10 0     MTA (Threadpool Worker)
  11   20     1594 000001C3A73FF1F0  3029220 Preemptive  000001C2189324A0:000001C218932738 000001BE96B95A10 0     MTA (Threadpool Worker)
   9   21     12c0 000001C3A74004E0  3029220 Preemptive  000001C118931A60:000001C118931AC0 000001BE96B95A10 0     MTA (Threadpool Worker)
  17   22     1a44 000001C3A73FBF70  3029220 Preemptive  000001BED8931938:000001BED8931970 000001BE96B95A10 0     MTA (Threadpool Worker)
  53   23     4d0c 000001C3A73FCC10  3029220 Preemptive  000001C258932770:000001C258932B10 000001BE96B95A10 0     MTA (Threadpool Worker)
  12   24     1648 000001C3A73FD8B0  3029220 Preemptive  000001BFD8934BF8:000001BFD89369C0 000001BE96B95A10 0     MTA (Threadpool Worker)
  55   25     4d4c 000001C3A73FC5C0  3029220 Preemptive  000001BE98932F40:000001BE98933590 000001BE96B95A10 0     MTA (Threadpool Worker)
  31   26     2ff0 000001C3A73FFE90  3029220 Preemptive  000001BF18933560:000001BF18933578 000001BE96B95A10 0     MTA (Threadpool Worker)
   7   27     11b0 000001C3A73FEBA0  3029220 Preemptive  000001C198932150:000001C198932510 000001BE96B95A10 0     MTA (Threadpool Worker)
  59   28     4fc0 000001C3A73FDF00  3029220 Preemptive  000001C218933848:000001C218935258 000001BE96B95A10 0     MTA (Threadpool Worker)
  35   29     35bc 000001C3A73FE550  3029220 Preemptive  000001C2189330D8:000001C2189331D0 000001BE96B95A10 0     MTA (Threadpool Worker)
  10   30     12dc 000001C3A73FF840  3029220 Preemptive  000001BF98931900:000001BF98932140 000001BE96B95A10 0     MTA (Threadpool Worker)
  34   33     34fc 000001C3A73F9FE0  3029220 Preemptive  000001BFD8932FB0:000001BFD89349C0 000001BE96B95A10 0     MTA (Threadpool Worker)
  56   15     4da4 000001C3A73FA630    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
   6   35      ef8 000001C3A73FAC80    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
  50   36     492c 000001C3A73FB920    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
  21   37     2048 000001C3A7285370    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
  13   38     18f0 000001C3A6C23470    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
  40   39     3ac8 000001C3A6C22E20    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
  15   40     1974 000001C3A6C23AC0    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
   8   41     1200 000001C3A6C24110    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
   4   42      a94 000001C3A6C22180    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
  43   43     4220 000001C3A6C227D0    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
  26   44     2480 000001C3A6C24760    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
  30   45     2d1c 000001C3A6C21B30    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
  33   46     3498 000001C3A6C24DB0    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
   5   47      bd8 000001C3A6C25400    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
  38   48     3610 000001C3A76DC0C0    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
  18   49     1da0 000001C3A76DB420    21220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     Ukn
  36   34     35d0 000001C3A76DADD0  8029220 Preemptive  000001C058932268:000001C058933CF8 000001BE96B95A10 0     MTA (Threadpool Completion Port)
  49   31     4778 000001C3A76D9AE0  1029220 Preemptive  000001C1D8938958:000001C1D8938C38 000001BE96B95A10 0     MTA (Threadpool Worker)
  14   32     1904 000001C3A76D6860  8029220 Preemptive  0000000000000000:0000000000000000 000001BE96B95A10 0     MTA (Threa

分析线程

  49   31     4778 000001C3A76D9AE0  1029220 Preemptive  000001C1D8938958:000001C1D8938C38 000001BE96B95A10 0     MTA (Threadpool Worker)
> setthread 31
> clrstack
OS Thread Id: 0x2ff0 (31)
        Child SP               IP Call Site
000000AEC14FE0A8 00007ffd1ee8c414 [HelperMethodFrame: 000000aec14fe0a8] System.Threading.Thread.SleepInternal(Int32)
000000AEC14FE1A0 00007FFC6C1438CD System.Threading.SpinWait.SpinOnceCore(Int32)
000000AEC14FE250 00007FFC6C1811E7 System.Threading.SpinWait.SpinUntil(System.Func`1<Boolean>, Int32)
000000AEC14FE2A0 00007FFC6BF23560 DotnetDump.Controllers.HomeController.<Index>b__3_0() [E:\Test\DotnetDump\Controllers\HomeController.cs @ 40]
000000AEC14FE340 00007FFCCAB2C01F System.Threading.Tasks.Task`1[[System.__Canon, System.Private.CoreLib]].InnerInvoke()
000000AEC14FE380 00007FFCCAA38092 System.Threading.Tasks.Task+<>c.<.cctor>b__274_0(System.Object)
000000AEC14FE3B0 00007FFCCAA38012 System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread, System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
000000AEC14FE400 00007FFCCAA37CE7 System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef, System.Threading.Thread)
000000AEC14FE4A0 00007FFCCAA37BC3 System.Threading.Tasks.Task.ExecuteEntryUnsafe(System.Threading.Thread)
000000AEC14FE4E0 00007FFCCAA37B5B System.Threading.Tasks.Task.ExecuteFromThreadPool(System.Threading.Thread)
000000AEC14FE510 00007FFC6C149BF1 System.Threading.ThreadPoolWorkQueue.Dispatch()
000000AEC14FE990 00007ffccb0b6ba3 [DebuggerU2MCatchHandlerFrame: 000000aec14fe990]

通过此方法分析线程调用栈。由于有pdb文件,因此可以很方便的看到具体的错误信息。

使用clrsatck -a 

找到

000000AEC14FE2A0 00007FFC6BF23560 DotnetDump.Controllers.HomeController.<Index>b__3_0() [E:\Test\DotnetDump\Controllers\HomeController.cs @ 40]
    PARAMETERS:
        this (0x000000AEC14FE340) = 0x000001c0589e6a40
    LOCALS:
        0x000000AEC14FE318 = 0x000001c2dc831e00
        0x000000AEC14FE314 = 0x0000000000100000
        0x000000AEC14FE310 = 0x0000000000000000
        0x000000AEC14FE30C = 0x0000000000000001
> dumpobj 0x000001c0589e6a40
Name:        DotnetDump.Controllers.HomeController
MethodTable: 00007ffc6bd80058
EEClass:     00007ffc6bd73968
Size:        104(0x68) bytes
File:        E:\Test\DotnetDump\bin\Debug\netcoreapp3.1\DotnetDump.dll
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
00007ffc6bd9dd98  400005c        8 ...ControllerContext  0 instance 000001c0589e6508 _controllerContext
00007ffc6b9a69a8  400005d       10 ...lMetadataProvider  0 instance 0000000000000000 _metadataProvider
00007ffc6b9a8130  400005e       18 ...odelBinderFactory  0 instance 0000000000000000 _modelBinderFactory
00007ffc6b9a83e0  400005f       20 ...ectModelValidator  0 instance 0000000000000000 _objectValidator
00007ffc6bd9dea0  4000060       28 ...re.Mvc.IUrlHelper  0 instance 0000000000000000 _url
00007ffc6b9ae310  4000061       30 ...lemDetailsFactory  0 instance 0000000000000000 _problemDetailsFactory
00007ffc6bd9d0c8  400001e       38 ...empDataDictionary  0 instance 000001c0589e7100 _tempData
0000000000000000  400001f       40 ...s.DynamicViewData  0 instance 0000000000000000 _viewBag
00007ffc6bd9cf18  4000020       48 ...iewDataDictionary  0 instance 000001c0589e6ac8 _viewData
00007ffc6c052648  4000003       50 ...ler, DotnetDump]]  0 instance 000001c2189959c0 _logger
00007ffc6c05a3e8  4000004       58 ...Private.CoreLib]]  0 instance 000001c0589e6aa8 _byteBag

查看具体的变量信息dumpobj 内存地址。

第二种:分析内存泄漏

由于上面较为明显的看到内存问题,因此将代码改为,这种代码假设是无意中添加到一个变量_byteBag中。

使用命令:

安装上面的步骤收集转储文件后。进入分析

dumpheap -stat

可以使用参数 -max -min

再次获得所有实例列表

dumpheap -mt 00007ffc69712360 

使用gcroot获得根

 gcroot -all 000001c95d0b1038

> gcroot -all 000001c95d0b1038

 

 

没事不要写静态变量存储数据,依赖注入时代,可以使用单例代替。

posted @ 2020-11-01 19:19  指左转右  阅读(2241)  评论(1编辑  收藏  举报