记一次 redis 事件注册不当导致的内存泄露

线上的程序跑着跑着内存越来越大,并且没有下降的趋势,重启一下程序也只能短暂恢复。通过 htop 命令再按一下 M 键按内存占用大小排个序,程序会占好几个G。那好,让我们来分析一下。

收集dump

通过 tophtop 进程管理器,或 ps 命令查找到目标进程 id,然后使用如下命令生成 dump:

createdump --full <PID>

dump 会自动保存在 /tmp 目录,文件名格式一般是 coredump.PID

小试牛刀

拿到 dump 后,通过 windbg 打开。首先使用命令 !address -summary 查看一下。

注意:有的朋友可能打开 dump 文件后,发现 sos 扩展加载失败,需要手动加载一下,输入命令 .load sos 即可。

0:000> !address -summary

                                     
Mapping file section regions...
Mapping module regions...
Mapping heap regions...
*** WARNING: Unable to verify timestamp for libc-2.17.so

--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
<unknown>                               869 ffffffff`f409b600 (  16.000 EB) 100.00%  100.00%
Image                                  1117        0`0b565a00 ( 181.397 MB)   0.00%    0.00%

--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
                                        808 ffffffff`018de000 (  16.000 EB)          100.00%
MEM_PRIVATE                            1178        0`fdd23000 (   3.966 GB)   0.00%    0.00%

--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
                                        808 ffffffff`018de000 (  16.000 EB) 100.00%  100.00%
MEM_COMMIT                             1178        0`fdd23000 (   3.966 GB)   0.00%    0.00%

--- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal
PAGE_READWRITE                          520        0`f6bf0000 (   3.855 GB)   0.00%    0.00%
PAGE_EXECUTE_READ                       160        0`05141000 (  81.254 MB)   0.00%    0.00%
PAGE_READONLY                           466        0`0147c000 (  20.484 MB)   0.00%    0.00%
PAGE_EXECUTE_WRITECOPY                   32        0`00b76000 (  11.461 MB)   0.00%    0.00%

--- Largest Region by Usage ----------- Base Address -------- Region Size ----------
<unknown>                              7ffd`7f5ad000 ffff8002`80053000 (  16.000 EB)
Image                                  7f44`7390c000        0`013d2000 (  19.820 MB)

从输出结果中 MEM_COMMIT 一栏可以看出,内存占了3.9G。

下一步要看是托管内存还是非托管内存吃掉。

托管内存

使用 eeheap 命令查看:

0:000> !sos eeheap 
Loader Heap:
----------------------------------------
System Domain:        7f447979a8c0
LoaderAllocator:      7f447979a8c0
LowFrequencyHeap:     7f4406ce0000(10000:c000) 7f4406cc0000(10000:10000) 7f4406ca0000(10000:10000) 7f4406c80000(10000:10000) 7f4406c50000(10000:10000) 7f4406c20000(10000:10000) 7f4406c00000(10000:10000) 7f4406be0000(10000:10000) 7f4406bc0000(10000:10000) 7f4406b60000(10000:10000) 7f4406b30000(10000:10000) 7f4406b00000(10000:10000) 7f4406ad0000(10000:10000) 7f4406a90000(20000:20000) 7f4406a70000(10000:a000) 7f4406a20000(10000:f000) 7f4406a00000(10000:10000) 7f44069e0000(10000:10000) 7f44069d0000(10000:10000) 7f4406990000(40000:40000) 7f4406950000(30000:29000) 7f4406940000(10000:10000) 7f4406720000(10000:f000) 7f4406700000(10000:10000) 7f44066e0000(10000:10000) 7f44066d0000(10000:10000) 7f44066b0000(10000:10000) 7f4406690000(10000:10000) 7f4406670000(10000:10000) 7f4406540000(10000:10000) 7f4406530000(10000:10000) 7f4406390000(10000:b000) 7f4406330000(10000:10000) 7f4406300000(10000:10000) 7f44062e0000(10000:10000) 7f4406270000(10000:10000) 7f4406240000(10000:10000) 7f4406210000(10000:10000) 7f4406200000(10000:10000) 7f44061d0000(30000:2a000) 7f44061b0000(10000:4000) 7f4406190000(10000:10000) 7f4406170000(10000:10000) 7f4406160000(10000:f000) 7f4406140000(10000:c000) 7f4406110000(10000:10000) 7f44060e0000(10000:10000) 7f4405ed0000(10000:10000) 7f4405eb0000(10000:10000) 7f4405e90000(10000:10000) 7f4405e70000(10000:10000) 7f4405e50000(10000:f000) 7f4405d70000(10000:10000) 7f4405d50000(10000:10000) 7f4405d20000(10000:10000) 7f4405d00000(10000:10000) 7f4405ce0000(10000:10000) 7f4405cd0000(10000:10000) 7f4405cb0000(10000:f000) 7f4405c90000(10000:f000) 7f4405bd0000(10000:10000) 7f4405b40000(10000:10000) 7f4405b20000(10000:f000) 7f4405af0000(10000:10000) 7f4405ad0000(10000:10000) 7f4405aa0000(30000:2f000) 7f4405a90000(10000:e000) 7f4405a70000(10000:10000) 7f4405a30000(10000:10000) 7f4405a10000(10000:10000) 7f44059a0000(10000:10000) 7f4405980000(10000:10000) 7f4405970000(10000:10000) 7f4405950000(10000:10000) 7f4405730000(10000:10000) 7f4405720000(10000:10000) 7f4405700000(10000:10000) 7f44056e0000(10000:10000) 7f44056b0000(10000:10000) 7f44056a0000(10000:10000) 7f4405670000(10000:10000) 7f4405650000(10000:10000) 7f4405630000(10000:f000) 7f44055e0000(10000:10000) 7f44055d0000(10000:10000) 7f44055c0000(10000:10000) 7f44055a0000(10000:10000) 7f4405590000(10000:10000) 7f4405580000(10000:10000) 7f4405560000(10000:10000) 7f4405540000(10000:10000) 7f4405520000(10000:10000) 7f4405510000(10000:10000) 7f44054f0000(10000:10000) 7f44054e0000(10000:10000) 7f44054c0000(10000:10000) 7f44054a0000(10000:10000) 7f4405490000(10000:10000) 7f4405280000(10000:d000) 7f4405260000(10000:10000) 7f4405240000(10000:10000) 7f4405230000(10000:10000) 7f4405210000(10000:10000) 7f4405200000(10000:10000) 7f44051f0000(10000:10000) 7f44051a0000(10000:10000) 7f4405180000(10000:10000) 7f4405150000(10000:10000) 7f4405120000(10000:10000) 7f44050e0000(10000:10000) 7f4405050000(10000:10000) 7f4405020000(10000:10000) 7f4404ff0000(10000:10000) 7f4404fc0000(10000:10000) 7f4404fb0000(10000:10000) 7f4404f90000(10000:f000) 7f4404f50000(10000:10000) 7f4404f40000(10000:10000) 7f4404f30000(10000:10000) 7f4404f10000(10000:7000) 7f4404e60000(10000:10000) 7f4404e50000(10000:e000) 7f4404e30000(10000:d000) 7f4404d20000(10000:10000) 7f4404d10000(10000:10000) 7f4404cf0000(10000:7000) 7f4404c70000(10000:10000) 7f4404c50000(10000:10000) 7f4404a40000(10000:b000) 7f4404a20000(10000:e000) 7f4404a00000(10000:10000) 7f4404970000(10000:10000) 7f4404950000(10000:10000) 7f4404940000(10000:10000) 7f4404930000(10000:7000) 7f4404920000(10000:f000) 7f4404900000(10000:10000) 7f44048e0000(10000:10000) 7f4404830000(10000:10000) 7f4404810000(10000:10000) 7f44047f0000(10000:c000) 7f4404710000(10000:10000) 7f44046f0000(10000:10000) 7f44046d0000(10000:10000) 7f44046a0000(10000:10000) 7f4404550000(10000:10000) 7f44044a0000(10000:10000) 7f44043d0000(10000:10000) 7f44043c0000(10000:10000) 7f44040c0000(10000:b000) 7f4404000000(10000:e000) 7f4403ed0000(10000:10000) 7f4403e30000(10000:10000) 7f4403d10000(10000:10000) 7f4403d00000(10000:f000) 7f4403c90000(10000:a000) 7f4403bc0000(10000:10000) 7f4403bb0000(10000:f000) 7f44037a0000(10000:a000) 7f4403770000(10000:10000) 7f4403730000(10000:10000) 7f44036d0000(10000:10000) 7f4403660000(10000:10000) 7f4403510000(10000:10000) 7f44033f0000(10000:c000) 7f44032a0000(10000:10000) 7f4403280000(10000:10000) 7f4403270000(10000:f000) 7f4403220000(40000:3f000) 7f4402980000(20000:1a000) 7f4402650000(10000:d000) 7f4402620000(10000:d000) 7f4402580000(10000:10000) 7f4402360000(10000:f000) 7f4402210000(10000:10000) 7f4402140000(10000:10000) 7f4402050000(10000:10000) 7f4402030000(10000:10000) 7f4401ee0000(10000:10000) 7f4401d70000(10000:10000) 7f4401cb0000(10000:10000) 7f4401ad0000(10000:10000) 7f44018b0000(10000:f000) 7f44016d0000(10000:10000) 7f4401520000(10000:10000) 7f44013b0000(10000:10000) 7f4401210000(20000:1f000) 7f4400f90000(10000:3000) 7f4400de0000(10000:10000) 7f4400d20000(10000:10000) 7f4400b00000(10000:f000) 7f4400a20000(10000:10000) 7f4400870000(10000:10000) 7f4400730000(20000:20000) 7f44004d0000(10000:2000) 7f4400280000(10000:10000) 7f4400200000(10000:e000) 7f44001f0000(10000:9000) 7f4400100000(10000:10000) 7f44000f0000(10000:10000) 7f44000a0000(10000:10000) 7f4400000000(10000:10000) 7f43fffb0000(50000:50000) 7f43ff4e0000(3000:1000) Size: 0xd3b000 (13873152) bytes total, 0xb4000 (737280) bytes wasted.
HighFrequencyHeap:    7f4406cd0000(10000:f000) 7f4406cb0000(10000:10000) 7f4406c70000(10000:10000) 7f4406c60000(10000:10000) 7f4406c40000(10000:10000) 7f4406c30000(10000:10000) 7f4406c10000(10000:10000) 7f4406bf0000(10000:10000) 7f4406bd0000(10000:10000) 7f4406b70000(10000:10000) 7f4406b50000(10000:10000) 7f4406b40000(10000:10000) 7f4406b10000(10000:10000) 7f4406af0000(10000:10000) 7f4406ae0000(10000:10000) 7f4406ac0000(10000:10000) 7f4406ab0000(10000:10000) 7f4406a80000(10000:10000) 7f4406a60000(10000:10000) 7f4406a50000(10000:10000) 7f4406a40000(10000:10000) 7f4406a30000(10000:10000) 7f4406a10000(10000:10000) 7f44069f0000(10000:10000) 7f4406980000(10000:10000) 7f4406730000(10000:10000) 7f4406710000(10000:10000) 7f44066f0000(10000:10000) 7f44066c0000(10000:10000) 7f44066a0000(10000:10000) 7f4406680000(10000:10000) 7f4406620000(10000:10000) 7f4406550000(10000:10000) 7f44063a0000(10000:10000) 7f4406380000(10000:f000) 7f4406320000(10000:10000) 7f4406310000(10000:10000) 7f44062f0000(10000:f000) 7f44062d0000(10000:10000) 7f4406280000(10000:10000) 7f4406230000(10000:f000) 7f44061c0000(10000:10000) 7f44061a0000(10000:10000) 7f4406180000(10000:10000) 7f4406150000(10000:10000) 7f4406130000(10000:10000) 7f4406100000(10000:10000) 7f44060f0000(10000:10000) 7f4405ec0000(10000:10000) 7f4405ea0000(10000:10000) 7f4405e80000(10000:10000) 7f4405e60000(10000:10000) 7f4405e30000(10000:10000) 7f4405d60000(10000:10000) 7f4405d40000(10000:10000) 7f4405d10000(10000:10000) 7f4405cf0000(10000:10000) 7f4405cc0000(10000:10000) 7f4405ca0000(10000:10000) 7f4405c80000(10000:10000) 7f4405b50000(10000:10000) 7f4405b30000(10000:10000) 7f4405b10000(10000:10000) 7f4405b00000(10000:10000) 7f4405ae0000(10000:10000) 7f4405a80000(10000:f000) 7f4405a60000(10000:10000) 7f4405a20000(10000:10000) 7f4405990000(10000:10000) 7f4405960000(10000:10000) 7f4405740000(10000:10000) 7f4405710000(10000:10000) 7f44056f0000(10000:10000) 7f44056d0000(10000:10000) 7f44056c0000(10000:10000) 7f4405680000(10000:10000) 7f4405660000(10000:10000) 7f4405640000(10000:10000) 7f4405610000(10000:10000) 7f4405600000(10000:10000) 7f44055f0000(10000:10000) 7f44055b0000(10000:10000) 7f4405570000(10000:10000) 7f4405530000(10000:10000) 7f4405500000(10000:10000) 7f44054d0000(10000:10000) 7f44054b0000(10000:10000) 7f4405270000(10000:10000) 7f4405250000(10000:10000) 7f4405220000(10000:10000) 7f44051e0000(10000:10000) 7f4405190000(10000:10000) 7f4405170000(10000:10000) 7f4405160000(10000:10000) 7f4405140000(10000:10000) 7f4405130000(10000:10000) 7f4405110000(10000:10000) 7f4405100000(10000:10000) 7f44050f0000(10000:10000) 7f4405060000(10000:10000) 7f4405040000(10000:10000) 7f4405030000(10000:10000) 7f4405010000(10000:10000) 7f4405000000(10000:10000) 7f4404fe0000(10000:10000) 7f4404fd0000(10000:10000) 7f4404fa0000(10000:10000) 7f4404f80000(10000:10000) 7f4404f60000(10000:10000) 7f4404f20000(10000:10000) 7f4404f00000(10000:10000) 7f4404e40000(10000:10000) 7f4404d00000(10000:10000) 7f4404cd0000(10000:10000) 7f4404c60000(10000:10000) 7f4404a30000(10000:10000) 7f4404a10000(10000:10000) 7f4404980000(10000:10000) 7f4404960000(10000:10000) 7f4404910000(10000:10000) 7f44048f0000(10000:10000) 7f44048d0000(10000:10000) 7f44048c0000(10000:10000) 7f4404820000(10000:10000) 7f4404800000(10000:10000) 7f44047e0000(10000:10000) 7f4404700000(10000:10000) 7f44046e0000(10000:10000) 7f44046c0000(10000:10000) 7f44046b0000(10000:10000) 7f4404690000(10000:10000) 7f44045b0000(10000:10000) 7f4404540000(10000:10000) 7f44044b0000(10000:10000) 7f4404490000(10000:10000) 7f4404480000(10000:10000) 7f44043e0000(10000:10000) 7f4404020000(10000:10000) 7f4404010000(10000:10000) 7f4403fa0000(10000:10000) 7f4403ee0000(10000:10000) 7f4403e40000(10000:10000) 7f4403d30000(10000:10000) 7f4403d20000(10000:10000) 7f4403ca0000(10000:10000) 7f4403c70000(10000:10000) 7f4403c60000(10000:10000) 7f4403bd0000(10000:10000) 7f44037b0000(10000:10000) 7f4403790000(10000:10000) 7f4403780000(10000:10000) 7f4403760000(10000:10000) 7f4403750000(10000:10000) 7f4403740000(10000:10000) 7f4403720000(10000:10000) 7f4403710000(10000:10000) 7f44036e0000(10000:10000) 7f44036c0000(10000:10000) 7f44036b0000(10000:10000) 7f4403420000(10000:10000) 7f4403410000(10000:10000) 7f4403400000(10000:10000) 7f44033a0000(10000:10000) 7f4403330000(10000:10000) 7f4403290000(10000:10000) 7f4403260000(10000:10000) 7f4402660000(10000:10000) 7f4402640000(10000:10000) 7f4402630000(10000:10000) 7f4402590000(10000:10000) 7f4402480000(10000:10000) 7f4402370000(10000:10000) 7f44022e0000(10000:10000) 7f4402230000(10000:10000) 7f4402220000(10000:10000) 7f4402130000(10000:10000) 7f4402120000(10000:10000) 7f4402070000(10000:10000) 7f4402060000(10000:10000) 7f4402040000(10000:10000) 7f4402020000(10000:10000) 7f4401df0000(10000:10000) 7f4401d80000(10000:10000) 7f4401d60000(10000:10000) 7f4401d00000(10000:10000) 7f44019c0000(10000:10000) 7f4401850000(10000:10000) 7f44016e0000(10000:10000) 7f4401600000(10000:10000) 7f4401510000(10000:10000) 7f44012e0000(10000:10000) 7f4400f20000(10000:10000) 7f4400d40000(10000:10000) 7f4400d30000(10000:10000) 7f4400b70000(10000:10000) 7f4400a30000(10000:10000) 7f44009c0000(10000:10000) 7f44004e0000(10000:10000) 7f4400110000(10000:10000) 7f44000e0000(10000:10000) 7f44000d0000(10000:10000) 7f44000c0000(10000:10000) 7f44000b0000(10000:10000) 7f4400010000(10000:10000) 7f43ff4e4000(9000:5000) Size: 0xcc0000 (13369344) bytes total, 0x8000 (32768) bytes wasted.
StubHeap:             7f4405070000(10000:5000) 7f43ff4ed000(3000:3000) Size: 0x8000 (32768) bytes total.
IndirectionCellHeap:  7f4405690000(10000:5000) 7f43ff4f0000(6000:6000) Size: 0xb000 (45056) bytes total.
LookupHeap:           7f4404f70000(10000:6000) 7f43ff4ff000(4000:4000) Size: 0xa000 (40960) bytes total.
ResolveHeap:          7f43ff534000(57000:20000) Size: 0x20000 (131072) bytes total.
DispatchHeap:         7f43ff503000(31000:e000) Size: 0xe000 (57344) bytes total.
CacheEntryHeap:       7f4406220000(10000:3000) 7f43ff4f6000(9000:9000) Size: 0xc000 (49152) bytes total.
Total size:           Size: 0x1a52000 (27598848) bytes total, 0xbc000 (770048) bytes wasted.
----------------------------------------
Domain 1:             5558fbe901d0
LoaderAllocator:      5558fbe901d0
No unique loader heaps found.
----------------------------------------
JIT Manager:          5558fbe936c0
LoaderCodeHeap:       7f4400020000(80000:36000) Size: 0x36000 (221184) bytes total.
LoaderCodeHeap:       7f4401940000(80000:39000) Size: 0x39000 (233472) bytes total.
LoaderCodeHeap:       7f44032b0000(80000:42000) Size: 0x42000 (270336) bytes total.
LoaderCodeHeap:       7f4403be0000(80000:49000) Size: 0x49000 (299008) bytes total.
LoaderCodeHeap:       7f44044c0000(80000:5a000) Size: 0x5a000 (368640) bytes total.
LoaderCodeHeap:       7f4404840000(80000:5f000) Size: 0x5f000 (389120) bytes total.
LoaderCodeHeap:       7f4404a50000(200000:18f000) Size: 0x18f000 (1634304) bytes total.
LoaderCodeHeap:       7f4405290000(200000:1c4000) Size: 0x1c4000 (1851392) bytes total.
LoaderCodeHeap:       7f4405750000(200000:1b1000) Size: 0x1b1000 (1773568) bytes total.
LoaderCodeHeap:       7f4405ee0000(200000:1b6000) Size: 0x1b6000 (1794048) bytes total.
LoaderCodeHeap:       7f4406740000(200000:15f000) Size: 0x15f000 (1437696) bytes total.
HostCodeHeap:         7f4403c80000(10000:10000) Size: 0x10000 (65536) bytes total.
HostCodeHeap:         7f4404ce0000(10000:10000) Size: 0x10000 (65536) bytes total.
HostCodeHeap:         7f4405a50000(10000:10000) Size: 0x10000 (65536) bytes total.
HostCodeHeap:         7f4405d80000(10000:10000) Size: 0x10000 (65536) bytes total.
HostCodeHeap:         7f4406120000(10000:10000) Size: 0x10000 (65536) bytes total.
HostCodeHeap:         7f4406260000(10000:10000) Size: 0x10000 (65536) bytes total.
HostCodeHeap:         7f4406290000(40000:40000) Size: 0x40000 (262144) bytes total.
HostCodeHeap:         7f4406340000(40000:40000) Size: 0x40000 (262144) bytes total.
HostCodeHeap:         7f4406b80000(40000:40000) Size: 0x40000 (262144) bytes total.
Total size:           Size: 0xaec000 (11452416) bytes total.
----------------------------------------

========================================
Number of GC Heaps: 1
----------------------------------------
generation 0 starts at 7f423d1f52c8
generation 1 starts at 7f423cc8b198
generation 2 starts at 7f43c7fff000
ephemeral segment allocation context: none
Small object heap
         segment            begin        allocated        committed allocated size         committed size        
    7f419d080000     7f419d081000     7f41acef9e78     7f41acf1a000 0xfe78e78 (266833528)  0xfe9a000 (266969088) 
    7f41bbfe0000     7f41bbfe1000     7f41cbb9b950     7f41cbbbc000 0xfbba950 (263956816)  0xfbdc000 (264093696) 
    7f4203ff0000     7f4203ff1000     7f4213feffb0     7f4213ff0000 0xfffefb0 (268431280)  0x10000000 (268435456)
    7f422bffa000     7f422bffb000     7f423a3a02f0     7f423a3c1000 0xe3a52f0 (238703344)  0xe3c7000 (238841856) 
    7f428bff0000     7f428bff1000     7f429bfeffe0     7f429bff0000 0xfffefe0 (268431328)  0x10000000 (268435456)
    7f429bff2000     7f429bff3000     7f42abff2000     7f42abff2000 0xffff000 (268431360)  0x10000000 (268435456)
    7f42abffe000     7f42abfff000     7f42bbffdfd0     7f42bbffe000 0xfffefd0 (268431312)  0x10000000 (268435456)
    7f42d3ffe000     7f42d3fff000     7f42e3ffe000     7f42e3ffe000 0xffff000 (268431360)  0x10000000 (268435456)
    7f42fb030000     7f42fb031000     7f430b030000     7f430b030000 0xffff000 (268431360)  0x10000000 (268435456)
    7f4317ffe000     7f4317fff000     7f4327ffe000     7f4327ffe000 0xffff000 (268431360)  0x10000000 (268435456)
    7f43c7ffe000     7f43c7fff000     7f43d7ffdfe8     7f43d7ffe000 0xfffefe8 (268431336)  0x10000000 (268435456)
    7f423bffe000     7f423bfff000     7f423d33f780     7f423e51b000 0x1340780 (20187008)   0x251d000 (38916096)  
Large object heap starts at 7f43d7fff000
         segment            begin        allocated        committed allocated size         committed size        
    7f40ed054000     7f40ed055000     7f40f1055038     7f40f1056000 0x4000038 (67108920)   0x4002000 (67117056)  
    7f41d3fe4000     7f41d3fe5000     7f41d7fe5038     7f41d8006000 0x4000038 (67108920)   0x4022000 (67248128)  
    7f41dbfe6000     7f41dbfe7000     7f41dffe7038     7f41e0008000 0x4000038 (67108920)   0x4022000 (67248128)  
    7f41ebfea000     7f41ebfeb000     7f41effeb038     7f41f000c000 0x4000038 (67108920)   0x4022000 (67248128)  
    7f41f3fec000     7f41f3fed000     7f41f7fed038     7f41f800e000 0x4000038 (67108920)   0x4022000 (67248128)  
    7f41fbfee000     7f41fbfef000     7f41fffef038     7f4200010000 0x4000038 (67108920)   0x4022000 (67248128)  
    7f432fffe000     7f432ffff000     7f4337063918     7f4337084000 0x7064918 (117852440)  0x7086000 (117989376) 
    7f43d7ffe000     7f43d7fff000     7f43de5eb030     7f43de5ec000 0x65ec030 (106872880)  0x65ee000 (106881024) 
Pinned object heap starts at 7f43dffff000
         segment            begin        allocated        committed allocated size         committed size        
    7f43dfffe000     7f43dffff000     7f43e02bc4f8     7f43e02c0000 0x2bd4f8 (2872568)     0x2c2000 (2891776)    
------------------------------
GC Allocated Heap Size:    Size: 0xd4a1f110 (3567382800) bytes.
GC Committed Heap Size:    Size: 0xd5d3c000 (3587424256) bytes.

Total bytes consumed by CLR: 0xd827a000 (3626475520)

可以看到,CLR 吃掉了3.6G。Ok,到这儿基本可以确定是托管内存问题。

相信大家都注意到小对象堆和大对象堆有大量的内存段,吃掉了主要的托管内存。

接下来使用 dumpheap -stat 来统计下托管堆上内存所有对象:

0:000> !sos dumpheap -stat
Statistics:
          MT      Count   TotalSize Class Name
7f4406bf5ef0          1          24 NPOI.OpenXmlFormats.ExtendedPropertiesDocument
7f4406bf60a0          1          24 NPOI.OpenXmlFormats.CustomPropertiesDocument
7f4406bf67e8          1          24 NPOI.OpenXmlFormats.CT_CustomProperties
7f4406bf74e0          1          24 NPOI.OpenXmlFormats.CT_Property[]
7f4406bf8540          1          24 NPOI.HSSF.Util.HSSFColor+Black
7f4406bf8678          1          24 NPOI.HSSF.Util.HSSFColor+White
...
...
7f440213aa08      3,270     313,920 System.Reflection.Emit.DynamicMethod
7f44000c8080      4,135     358,828 System.Int32[]
7f4401519498     10,309     365,192 System.RuntimeType[]
7f440480b990          2     458,800 StackExchange.Redis.RawResult[]
7f440213faa0      3,270     470,880 System.Reflection.Emit.DynamicILGenerator
7f440185dcf8      5,133     492,768 System.Reflection.RuntimeParameterInfo
7f44000e7e60      3,216     551,160 System.String[]
7f440185e0a8      6,986     558,880 System.Signature
7f44012e8f10     10,812   1,124,448 System.Reflection.RuntimeMethodInfo
7f44000c7bc8     15,112   1,305,648 System.SByte[]
7f44000cd2e0     30,854   2,294,568 System.String
7f4400110eb0        224   5,064,502 System.Char[]
7f4400b784f0     18,748  21,734,523 System.Byte[]
7f44046efe70  6,541,452 418,652,928 System.EventHandler<StackExchange.Redis.EndPointEventArgs>
7f44047001b0  6,541,452 418,652,928 System.EventHandler<StackExchange.Redis.HashSlotMovedEventArgs>
7f4404700488  6,541,452 418,652,928 System.EventHandler<StackExchange.Redis.InternalErrorEventArgs>
7f44046efc10  6,541,452 418,652,928 System.EventHandler<StackExchange.Redis.RedisErrorEventArgs>
5558fbe656a0    293,562 474,504,032 Free
7f440001b0f8      5,222 538,033,592 System.Object[]
7f44046ef988 13,082,904 837,305,856 System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs>
Total 39,789,084 objects, 3,567,106,882 bytes

这个命令会按照 mt 汇总统计每个对象的数量及所占内存大小,并按内存大小排序,我们看到询问有几个对象格外抢眼,其中最后一个有 1000w 个 EvevtHandler 对象,占 837 M,那就继续往下看。

罪魁祸首

我们需要看一下这 1000w 对象到底什么来头,因为上述是按 mt 汇总的,所以现在用 dumpheap -mt 展开看一下:

0:000> !sos dumpheap -mt 7f44046ef988
         Address               MT           Size
    7f419d0810c0     7f44046ef988             64 
    7f419d081100     7f44046ef988             64 
    7f419d081240     7f44046ef988             64  
...
    7f419d2f0e50     7f44046ef988             64 
    7f419d2f0f90     7f44046ef988             64 
    7f419d2f0fd0     7f44046ef988             64 

Statistics:
          MT  Count TotalSize Class Name
7f44046ef988 13,160   842,240 System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs>
Total 13,160 objects, 842,240 bytes

对象太多,不可能展示完,所以这里做了一个省略。好的,接下来抽查几个对象使用命令 dumpobj 看一下:

0:000> !sos dumpobj /d 7f419d2f0fd0
Name:        System.EventHandler`1[[StackExchange.Redis.ConnectionFailedEventArgs, StackExchange.Redis]]
MethodTable: 00007f44046ef988
EEClass:     00007f44046f8b58
Tracked Type: false
Size:        64(0x40) bytes
File:        /usr/share/dotnet/shared/Microsoft.NETCore.App/6.0.6/System.Private.CoreLib.dll
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
00007f4400015290  40001bd        8        System.Object  0 instance 00007f419d2f0fd0 _target
00007f4400015290  40001be       10        System.Object  0 instance 0000000000000000 _methodBase
00007f44000c3eb8  40001bf       18        System.IntPtr  1 instance 00007F43FF4ED1E0 _methodPtr
00007f44000c3eb8  40001c0       20        System.IntPtr  1 instance 00007F4403BEF508 _methodPtrAux
00007f4400015290  4000243       28        System.Object  0 instance 0000000000000000 _invocationList
00007f44000c3eb8  4000244       30        System.IntPtr  1 instance 0000000000000000 _invocationCount

抽查几个后发现,都是一样。那既然这些对象一直不被GC回收,肯定有什么原因,使用 gcroot 查看一下都被谁引用:

0:000> !sos gcroot 7f419d2f0fd0
Caching GC roots, this may take a while.
Subsequent runs of this command will be faster.

HandleTable:
    00007f447a911310 (strong handle)
          -> 7f43e0008c28     System.Object[] 
          -> 7f43c81a4aa0     StackExchange.Redis.ConnectionMultiplexer (static variable: System.Object._locker)
          -> 7f423d33c828     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 
          -> 7f41f3fed020     System.Object[] 
          -> 7f419d2f0fd0     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 

Thread 1f4f:
    7f44724de9b0 7f440488ac93 StackExchange.Redis.PhysicalBridge+<ProcessBacklogAsync>d__97.MoveNext()
        rbp-78: 00007f44724de9c8
          -> 7f43c81b7e30     StackExchange.Redis.PhysicalBridge 
          -> 7f43c81a4aa0     StackExchange.Redis.ConnectionMultiplexer 
          -> 7f423d33c828     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 
          -> 7f41f3fed020     System.Object[] 
          -> 7f419d2f0fd0     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 

        rbp-80: 00007f44724de9c0
          -> 7f43c81b7e30     StackExchange.Redis.PhysicalBridge 
          -> 7f43c81a4aa0     StackExchange.Redis.ConnectionMultiplexer 
          -> 7f423d33c828     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 
          -> 7f41f3fed020     System.Object[] 
          -> 7f419d2f0fd0     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 

    7f44724dea50 7f44048888f9
        rbp-8: 00007f44724dea78
          -> 7f43c81b7e30     StackExchange.Redis.PhysicalBridge 
          -> 7f43c81a4aa0     StackExchange.Redis.ConnectionMultiplexer 
          -> 7f423d33c828     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 
          -> 7f41f3fed020     System.Object[] 
          -> 7f419d2f0fd0     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 

    7f44724dea90 7f44048882fb
        rbp-10: 00007f44724dea90
          -> 7f43c81b7e30     StackExchange.Redis.PhysicalBridge 
          -> 7f43c81a4aa0     StackExchange.Redis.ConnectionMultiplexer 
          -> 7f423d33c828     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 
          -> 7f41f3fed020     System.Object[] 
          -> 7f419d2f0fd0     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 

    7f44724deab0 7f44048882ac StackExchange.Redis.PhysicalBridge.ProcessBacklogAsync()
        rbp-30: 00007f44724deab0
          -> 7f43c81b7e30     StackExchange.Redis.PhysicalBridge 
          -> 7f43c81a4aa0     StackExchange.Redis.ConnectionMultiplexer 
          -> 7f423d33c828     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 
          -> 7f41f3fed020     System.Object[] 
          -> 7f419d2f0fd0     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 

        rbp-8: 00007f44724dead8
          -> 7f43c81b7e30     StackExchange.Redis.PhysicalBridge 
          -> 7f43c81a4aa0     StackExchange.Redis.ConnectionMultiplexer 
          -> 7f423d33c828     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 
          -> 7f41f3fed020     System.Object[] 
          -> 7f419d2f0fd0     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 

    7f44724deaf0 7f4404887f3f StackExchange.Redis.PhysicalBridge+<>c.<StartBacklogProcessor>b__93_0(System.Object)
        rbp-10: 00007f44724deaf0
          -> 7f43c81b7e30     StackExchange.Redis.PhysicalBridge 
          -> 7f43c81a4aa0     StackExchange.Redis.ConnectionMultiplexer 
          -> 7f423d33c828     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 
          -> 7f41f3fed020     System.Object[] 
          -> 7f419d2f0fd0     System.EventHandler<StackExchange.Redis.ConnectionFailedEventArgs> 

Found 8 unique roots.

注意:因为对象太多,遍历查找引用链需要一点儿时间,请耐心等待!

我们发现,它们都被 StackExchange.Redis.ConnectionMultiplexer 引用,这是一个 redis 连接对象。再经过大胆猜测和简单分析,其余几个巨量对象列表都是这个 redis 对象的事件。说明程序中引入了 StackExchange 的 redis 扩展包,并在项目中某处使用了 redis 操作,这个对象到底在何处,可能出问题的代码又在哪儿?

定位代码

有经验的朋友可能会知道,redis 这个对象大概率是一个静态变量。现在我们来验证一下,试图查找这个对象对应的静态变量所在位置,使用 s-q 命令查找是哪个内存地址(B)上保存此这个 redis 对象地址(A)。

首先缩小内存查找范围:

0:000> !sos dumpobj /d 7f43e0008c28
Name:        System.Object[]
MethodTable: 00007f440001b0f8
EEClass:     00007f440001b070
Tracked Type: false
Size:        32664(0x7f98) bytes
Array:       Rank 1, Number of elements 4080, Type CLASS (Print Array)
Fields:
None

我们需要用到这个 Object 对象数组的起始位置及数量用作如下命令的偏移:

0:000> s-q 7f43e0008c28 L?0x7f98 7f43c81a4aa0
00007f43`e000aaa0  00007f43`c81a4aa0 00007f43`ca4922a0

这样,我们就找到了静态变量的位置(B):

00007f43`e000aaa0

让我们继续查找是哪些代码在使用这个静态变量:

0:000> s-b 0 L?0xffffffffffffffff a0 aa 00 e0 43 7f 00 00
00007f44`044f9f81  a0 aa 00 e0 43 7f 00 00-33 ff 48 89 38 48 b8 6c  ....C...3.H.8H.l
00007f44`044fb96a  a0 aa 00 e0 43 7f 00 00-48 83 3e 00 40 0f 94 c6  ....C...H.>.@...
00007f44`044fb9b3  a0 aa 00 e0 43 7f 00 00-48 83 3f 00 74 38 48 bf  ....C...H.?.t8H.
00007f44`044fb9c3  a0 aa 00 e0 43 7f 00 00-48 8b 3f 48 b8 28 b0 6e  ....C...H.?H.(.n
00007f44`044fba71  a0 aa 00 e0 43 7f 00 00-48 8b b5 50 ff ff ff e8  ....C...H..P....
00007f44`044fbaa9  a0 aa 00 e0 43 7f 00 00-48 8b 3f 48 89 7d b8 48  ....C...H.?H.}.H
00007f44`044fbb03  a0 aa 00 e0 43 7f 00 00-48 8b 3f 48 89 7d a8 48  ....C...H.?H.}.H
00007f44`044fbb5d  a0 aa 00 e0 43 7f 00 00-48 8b 3f 48 89 7d 98 48  ....C...H.?H.}.H
00007f44`044fbbb7  a0 aa 00 e0 43 7f 00 00-48 8b 3f 48 89 7d 88 48  ....C...H.?H.}.H
00007f44`044fbc11  a0 aa 00 e0 43 7f 00 00-48 8b 3f 48 89 bd 78 ff  ....C...H.?H..x.
00007f44`044fbc74  a0 aa 00 e0 43 7f 00 00-48 8b 3f 48 89 bd 68 ff  ....C...H.?H..h.
00007f44`044fbcc7  a0 aa 00 e0 43 7f 00 00-48 8b 00 48 89 45 d0 90  ....C...H..H.E..

OK 我们找到不少,抽几个看一下反汇编代码:

0:000> !sos u 00007f44`044fb96a
Normal JIT generated code
Wisder.xRiver.BaseCore.Util.xRedis.get_Instance()
ilAddr is 00007F447142F990 pImport is 00000143049FEE00
Begin 00007F44044FB890, size 485
00007f44`044fb890 55              push    rbp
00007f44`044fb891 4881ecd0000000  sub     rsp,0D0h
00007f44`044fb898 488dac24d0000000 lea     rbp,[rsp+0D0h]
00007f44`044fb8a0 33c0            xor     eax,eax
00007f44`044fb8a2 48898538ffffff  mov     qword ptr [rbp-0C8h],rax
00007f44`044fb8a9 c4413857c0      vxorps  xmm8,xmm8,xmm8
00007f44`044fb8ae 48b840ffffffffffffff mov rax,0FFFFFFFFFFFFFF40h
00007f44`044fb8b8 c5797f0428      vmovdqa xmmword ptr [rax+rbp],xmm8
00007f44`044fb8bd c5797f440510    vmovdqa xmmword ptr [rbp+rax+10h],xmm8
00007f44`044fb8c3 c5797f440520    vmovdqa xmmword ptr [rbp+rax+20h],xmm8
00007f44`044fb8c9 4883c030        add     rax,30h
00007f44`044fb8cd 75e9            jne     00007f44`044fb8b8
00007f44`044fb8cf 4889a530ffffff  mov     qword ptr [rbp-0D0h],rsp
00007f44`044fb8d6 48b870e26402447f0000 mov rax,7F440264E270h
00007f44`044fb8e0 833800          cmp     dword ptr [rax],0
00007f44`044fb8e3 7405            je      00007f44`044fb8ea
00007f44`044fb8e5 e88659dd74      call    libcoreclr!JIT_DbgIsJustMyCode (00007f44`792d1270)
00007f44`044fb8ea 90              nop
00007f44`044fb8eb 48bf90aa00e0437f0000 mov rdi,7F43E000AA90h
00007f44`044fb8f5 488b3f          mov     rdi,qword ptr [rdi]
00007f44`044fb8f8 393f            cmp     dword ptr [rdi],edi
00007f44`044fb8fa e829ccb2fb      call    00007f44`00028528 (System.String.get_Length(), mdToken: 0000000006000764)
00007f44`044fb8ff 8945cc          mov     dword ptr [rbp-34h],eax
00007f44`044fb902 837dcc00        cmp     dword ptr [rbp-34h],0
00007f44`044fb906 400f94c6        sete    sil
00007f44`044fb90a 400fb6f6        movzx   esi,sil
00007f44`044fb90e 8975fc          mov     dword ptr [rbp-4],esi
00007f44`044fb911 837dfc00        cmp     dword ptr [rbp-4],0
00007f44`044fb915 7451            je      00007f44`044fb968
00007f44`044fb917 90              nop
00007f44`044fb918 48bf90ec0c00447f0000 mov rdi,7F44000CEC90h (MT: System.Exception)
00007f44`044fb922 e809c8dc74      call    libcoreclr!JIT_NewS_MP_FastPortable (00007f44`792c8130)
00007f44`044fb927 48898540ffffff  mov     qword ptr [rbp-0C0h],rax
00007f44`044fb92e bf49220000      mov     edi,2249h
00007f44`044fb933 48be00de6402447f0000 mov rsi,7F440264DE00h
00007f44`044fb93d e87ecedc74      call    libcoreclr!JIT_StrCns (00007f44`792c87c0)
00007f44`044fb942 48898538ffffff  mov     qword ptr [rbp-0C8h],rax
00007f44`044fb949 488bb538ffffff  mov     rsi,qword ptr [rbp-0C8h]
00007f44`044fb950 488bbd40ffffff  mov     rdi,qword ptr [rbp-0C0h]
00007f44`044fb957 e89cd1b2fb      call    00007f44`00028af8 (System.Exception..ctor(System.String), mdToken: 00000000060003CB)
00007f44`044fb95c 488bbd40ffffff  mov     rdi,qword ptr [rbp-0C0h]
00007f44`044fb963 e8f832dd74      call    libcoreclr!IL_Throw (00007f44`792cec60)
00007f44`044fb968 48bea0aa00e0437f0000 mov rsi,7F43E000AAA0h
00007f44`044fb972 48833e00        cmp     qword ptr [rsi],0
00007f44`044fb976 400f94c6        sete    sil
00007f44`044fb97a 400fb6f6        movzx   esi,sil
00007f44`044fb97e 8975f8          mov     dword ptr [rbp-8],esi
00007f44`044fb981 837df800        cmp     dword ptr [rbp-8],0
00007f44`044fb985 0f8409010000    je      00007f44`044fba94
00007f44`044fb98b 90              nop
00007f44`044fb98c 48be98aa00e0437f0000 mov rsi,7F43E000AA98h
00007f44`044fb996 488b36          mov     rsi,qword ptr [rsi]
00007f44`044fb999 488975f0        mov     qword ptr [rbp-10h],rsi
00007f44`044fb99d 33f6            xor     esi,esi
00007f44`044fb99f 8975e8          mov     dword ptr [rbp-18h],esi
00007f44`044fb9a2 488d75e8        lea     rsi,[rbp-18h]
00007f44`044fb9a6 488b7df0        mov     rdi,qword ptr [rbp-10h]
00007f44`044fb9aa e811dbb2fb      call    00007f44`000294c0 (System.Threading.Monitor.Enter(System.Object, Boolean ByRef), mdToken: 0000000006002BA0)
00007f44`044fb9af 90              nop
00007f44`044fb9b0 90              nop
00007f44`044fb9b1 48bfa0aa00e0437f0000 mov rdi,7F43E000AAA0h
00007f44`044fb9bb 48833f00        cmp     qword ptr [rdi],0
00007f44`044fb9bf 7438            je      00007f44`044fb9f9
00007f44`044fb9c1 48bfa0aa00e0437f0000 mov rdi,7F43E000AAA0h
00007f44`044fb9cb 488b3f          mov     rdi,qword ptr [rdi]
00007f44`044fb9ce 48b828b06e04447f0000 mov rax,7F44046EB028h
00007f44`044fb9d8 393f            cmp     dword ptr [rdi],edi
00007f44`044fb9da ff10            call    qword ptr [rax] (StackExchange.Redis.ConnectionMultiplexer.get_IsConnected(), mdToken: 00000000060001A2)
00007f44`044fb9dc 89854cffffff    mov     dword ptr [rbp-0B4h],eax
00007f44`044fb9e2 83bd4cffffff00  cmp     dword ptr [rbp-0B4h],0
00007f44`044fb9e9 400f94c7        sete    dil
00007f44`044fb9ed 400fb6ff        movzx   edi,dil
00007f44`044fb9f1 89bd64ffffff    mov     dword ptr [rbp-9Ch],edi
00007f44`044fb9f7 eb0a            jmp     00007f44`044fba03
00007f44`044fb9f9 c78564ffffff01000000 mov dword ptr [rbp-9Ch],1
00007f44`044fba03 8bbd64ffffff    mov     edi,dword ptr [rbp-9Ch]
00007f44`044fba09 400fb6ff        movzx   edi,dil
00007f44`044fba0d 897de4          mov     dword ptr [rbp-1Ch],edi
00007f44`044fba10 837de400        cmp     dword ptr [rbp-1Ch],0
00007f44`044fba14 7470            je      00007f44`044fba86
00007f44`044fba16 90              nop
00007f44`044fba17 48bf90aa00e0437f0000 mov rdi,7F43E000AA90h
00007f44`044fba21 488b3f          mov     rdi,qword ptr [rdi]
00007f44`044fba24 e86ff6ffff      call    00007f44`044fb098 (StackExchange.Redis.ConfigurationOptions.Parse(System.String), mdToken: 0000000006000156)
00007f44`044fba29 48898558ffffff  mov     qword ptr [rbp-0A8h],rax
00007f44`044fba30 488bbd58ffffff  mov     rdi,qword ptr [rbp-0A8h]
00007f44`044fba37 48897dd8        mov     qword ptr [rbp-28h],rdi
00007f44`044fba3b 488b7dd8        mov     rdi,qword ptr [rbp-28h]
00007f44`044fba3f be10270000      mov     esi,2710h
00007f44`044fba44 393f            cmp     dword ptr [rdi],edi
00007f44`044fba46 e8edf7ffff      call    00007f44`044fb238 (StackExchange.Redis.ConfigurationOptions.set_ConnectTimeout(Int32), mdToken: 0000000006000121)
00007f44`044fba4b 90              nop
00007f44`044fba4c 488b7dd8        mov     rdi,qword ptr [rbp-28h]
00007f44`044fba50 be983a0000      mov     esi,3A98h
00007f44`044fba55 393f            cmp     dword ptr [rdi],edi
00007f44`044fba57 e82cf9ffff      call    00007f44`044fb388 (StackExchange.Redis.ConfigurationOptions.set_SyncTimeout(Int32), mdToken: 000000000600014B)
00007f44`044fba5c 90              nop
00007f44`044fba5d 488b7dd8        mov     rdi,qword ptr [rbp-28h]
00007f44`044fba61 33f6            xor     esi,esi
00007f44`044fba63 e838e3ffff      call    00007f44`044f9da0 (StackExchange.Redis.ConnectionMultiplexer.Connect(StackExchange.Redis.ConfigurationOptions, System.IO.TextWriter), mdToken: 00000000060001BC)
00007f44`044fba68 48898550ffffff  mov     qword ptr [rbp-0B0h],rax
00007f44`044fba6f 48bfa0aa00e0437f0000 mov rdi,7F43E000AAA0h
00007f44`044fba79 488bb550ffffff  mov     rsi,qword ptr [rbp-0B0h]
00007f44`044fba80 e80cb7f274      call    libcoreclr!JIT_CheckedWriteBarrier (00007f44`79427191)
00007f44`044fba85 90              nop
00007f44`044fba86 90              nop
00007f44`044fba87 90              nop
00007f44`044fba88 eb00            jmp     00007f44`044fba8a
00007f44`044fba8a 488bfc          mov     rdi,rsp
00007f44`044fba8d e854020000      call    00007f44`044fbce6 (Wisder.xRiver.BaseCore.Util.xRedis.get_Instance(), mdToken: 00000000060000B3)
00007f44`044fba92 90              nop
00007f44`044fba93 90              nop
00007f44`044fba94 48bf88f96e04447f0000 mov rdi,7F44046EF988h (MT: System.EventHandler`1[[StackExchange.Redis.ConnectionFailedEventArgs, StackExchange.Redis]])
00007f44`044fba9e e88dc6dc74      call    libcoreclr!JIT_NewS_MP_FastPortable (00007f44`792c8130)
00007f44`044fbaa3 488945c0        mov     qword ptr [rbp-40h],rax
00007f44`044fbaa7 48bfa0aa00e0437f0000 mov rdi,7F43E000AAA0h
00007f44`044fbab1 488b3f          mov     rdi,qword ptr [rdi]
00007f44`044fbab4 48897db8        mov     qword ptr [rbp-48h],rdi
00007f44`044fbab8 488b7dc0        mov     rdi,qword ptr [rbp-40h]
00007f44`044fbabc 33f6            xor     esi,esi
00007f44`044fbabe 48ba10f5be03447f0000 mov rdx,7F4403BEF510h
00007f44`044fbac8 48b9e0d14eff437f0000 mov rcx,7F43FF4ED1E0h
00007f44`044fbad2 e8b1b6b2fb      call    00007f44`00027188 (System.MulticastDelegate.CtorOpened(System.Object, IntPtr, IntPtr), mdToken: 00000000060004ED)
00007f44`044fbad7 488b7db8        mov     rdi,qword ptr [rbp-48h]
00007f44`044fbadb 488b75c0        mov     rsi,qword ptr [rbp-40h]
00007f44`044fbadf 48b818b16e04447f0000 mov rax,7F44046EB118h
00007f44`044fbae9 393f            cmp     dword ptr [rdi],edi
00007f44`044fbaeb ff10            call    qword ptr [rax] (StackExchange.Redis.ConnectionMultiplexer.add_ConnectionFailed(System.EventHandler`1<StackExchange.Redis.ConnectionFailedEventArgs>), mdToken: 00000000060001F9)
00007f44`044fbaed 90              nop
00007f44`044fbaee 48bf88f96e04447f0000 mov rdi,7F44046EF988h (MT: System.EventHandler`1[[StackExchange.Redis.ConnectionFailedEventArgs, StackExchange.Redis]])
00007f44`044fbaf8 e833c6dc74      call    libcoreclr!JIT_NewS_MP_FastPortable (00007f44`792c8130)
00007f44`044fbafd 488945b0        mov     qword ptr [rbp-50h],rax
00007f44`044fbb01 48bfa0aa00e0437f0000 mov rdi,7F43E000AAA0h
00007f44`044fbb0b 488b3f          mov     rdi,qword ptr [rdi]
00007f44`044fbb0e 48897da8        mov     qword ptr [rbp-58h],rdi
00007f44`044fbb12 488b7db0        mov     rdi,qword ptr [rbp-50h]
00007f44`044fbb16 33f6            xor     esi,esi
00007f44`044fbb18 48ba08f5be03447f0000 mov rdx,7F4403BEF508h
00007f44`044fbb22 48b9e0d14eff437f0000 mov rcx,7F43FF4ED1E0h
00007f44`044fbb2c e857b6b2fb      call    00007f44`00027188 (System.MulticastDelegate.CtorOpened(System.Object, IntPtr, IntPtr), mdToken: 00000000060004ED)
00007f44`044fbb31 488b7da8        mov     rdi,qword ptr [rbp-58h]
00007f44`044fbb35 488b75b0        mov     rsi,qword ptr [rbp-50h]
00007f44`044fbb39 48b838b16e04447f0000 mov rax,7F44046EB138h
00007f44`044fbb43 393f            cmp     dword ptr [rdi],edi
00007f44`044fbb45 ff10            call    qword ptr [rax] (StackExchange.Redis.ConnectionMultiplexer.add_ConnectionRestored(System.EventHandler`1<StackExchange.Redis.ConnectionFailedEventArgs>), mdToken: 00000000060001FF)
00007f44`044fbb47 90              nop
00007f44`044fbb48 48bf10fc6e04447f0000 mov rdi,7F44046EFC10h (MT: System.EventHandler`1[[StackExchange.Redis.RedisErrorEventArgs, StackExchange.Redis]])
00007f44`044fbb52 e8d9c5dc74      call    libcoreclr!JIT_NewS_MP_FastPortable (00007f44`792c8130)
00007f44`044fbb57 488945a0        mov     qword ptr [rbp-60h],rax
00007f44`044fbb5b 48bfa0aa00e0437f0000 mov rdi,7F43E000AAA0h
00007f44`044fbb65 488b3f          mov     rdi,qword ptr [rdi]
00007f44`044fbb68 48897d98        mov     qword ptr [rbp-68h],rdi
00007f44`044fbb6c 488b7da0        mov     rdi,qword ptr [rbp-60h]
00007f44`044fbb70 33f6            xor     esi,esi
00007f44`044fbb72 48ba00f5be03447f0000 mov rdx,7F4403BEF500h
00007f44`044fbb7c 48b9e0d14eff437f0000 mov rcx,7F43FF4ED1E0h
00007f44`044fbb86 e8fdb5b2fb      call    00007f44`00027188 (System.MulticastDelegate.CtorOpened(System.Object, IntPtr, IntPtr), mdToken: 00000000060004ED)
00007f44`044fbb8b 488b7d98        mov     rdi,qword ptr [rbp-68h]
00007f44`044fbb8f 488b75a0        mov     rsi,qword ptr [rbp-60h]
00007f44`044fbb93 48b878b16e04447f0000 mov rax,7F44046EB178h
00007f44`044fbb9d 393f            cmp     dword ptr [rdi],edi
00007f44`044fbb9f ff10            call    qword ptr [rax] (StackExchange.Redis.ConnectionMultiplexer.add_ErrorMessage(System.EventHandler`1<StackExchange.Redis.RedisErrorEventArgs>), mdToken: 000000000600020F)
00007f44`044fbba1 90              nop
00007f44`044fbba2 48bf70fe6e04447f0000 mov rdi,7F44046EFE70h (MT: System.EventHandler`1[[StackExchange.Redis.EndPointEventArgs, StackExchange.Redis]])
00007f44`044fbbac e87fc5dc74      call    libcoreclr!JIT_NewS_MP_FastPortable (00007f44`792c8130)
00007f44`044fbbb1 48894590        mov     qword ptr [rbp-70h],rax
00007f44`044fbbb5 48bfa0aa00e0437f0000 mov rdi,7F43E000AAA0h
00007f44`044fbbbf 488b3f          mov     rdi,qword ptr [rdi]
00007f44`044fbbc2 48897d88        mov     qword ptr [rbp-78h],rdi
00007f44`044fbbc6 488b7d90        mov     rdi,qword ptr [rbp-70h]
00007f44`044fbbca 33f6            xor     esi,esi
00007f44`044fbbcc 48baf8f4be03447f0000 mov rdx,7F4403BEF4F8h
00007f44`044fbbd6 48b9e0d14eff437f0000 mov rcx,7F43FF4ED1E0h
00007f44`044fbbe0 e8a3b5b2fb      call    00007f44`00027188 (System.MulticastDelegate.CtorOpened(System.Object, IntPtr, IntPtr), mdToken: 00000000060004ED)
00007f44`044fbbe5 488b7d88        mov     rdi,qword ptr [rbp-78h]
00007f44`044fbbe9 488b7590        mov     rsi,qword ptr [rbp-70h]
00007f44`044fbbed 48b848b16e04447f0000 mov rax,7F44046EB148h
00007f44`044fbbf7 393f            cmp     dword ptr [rdi],edi
00007f44`044fbbf9 ff10            call    qword ptr [rax] (StackExchange.Redis.ConnectionMultiplexer.add_ConfigurationChanged(System.EventHandler`1<StackExchange.Redis.EndPointEventArgs>), mdToken: 0000000006000202)
00007f44`044fbbfb 90              nop
00007f44`044fbbfc 48bfb0017004447f0000 mov rdi,7F44047001B0h (MT: System.EventHandler`1[[StackExchange.Redis.HashSlotMovedEventArgs, StackExchange.Redis]])
00007f44`044fbc06 e825c5dc74      call    libcoreclr!JIT_NewS_MP_FastPortable (00007f44`792c8130)
00007f44`044fbc0b 48894580        mov     qword ptr [rbp-80h],rax
00007f44`044fbc0f 48bfa0aa00e0437f0000 mov rdi,7F43E000AAA0h
00007f44`044fbc19 488b3f          mov     rdi,qword ptr [rdi]
00007f44`044fbc1c 4889bd78ffffff  mov     qword ptr [rbp-88h],rdi
00007f44`044fbc23 488b7d80        mov     rdi,qword ptr [rbp-80h]
00007f44`044fbc27 33f6            xor     esi,esi
00007f44`044fbc29 48ba18f5be03447f0000 mov rdx,7F4403BEF518h
00007f44`044fbc33 48b9e0d14eff437f0000 mov rcx,7F43FF4ED1E0h
00007f44`044fbc3d e846b5b2fb      call    00007f44`00027188 (System.MulticastDelegate.CtorOpened(System.Object, IntPtr, IntPtr), mdToken: 00000000060004ED)
00007f44`044fbc42 488bbd78ffffff  mov     rdi,qword ptr [rbp-88h]
00007f44`044fbc49 488b7580        mov     rsi,qword ptr [rbp-80h]
00007f44`044fbc4d 48b868b16e04447f0000 mov rax,7F44046EB168h
00007f44`044fbc57 393f            cmp     dword ptr [rdi],edi
00007f44`044fbc59 ff10            call    qword ptr [rax] (StackExchange.Redis.ConnectionMultiplexer.add_HashSlotMoved(System.EventHandler`1<StackExchange.Redis.HashSlotMovedEventArgs>), mdToken: 000000000600020C)
00007f44`044fbc5b 90              nop
00007f44`044fbc5c 48bf88047004447f0000 mov rdi,7F4404700488h (MT: System.EventHandler`1[[StackExchange.Redis.InternalErrorEventArgs, StackExchange.Redis]])
00007f44`044fbc66 e8c5c4dc74      call    libcoreclr!JIT_NewS_MP_FastPortable (00007f44`792c8130)
00007f44`044fbc6b 48898570ffffff  mov     qword ptr [rbp-90h],rax
00007f44`044fbc72 48bfa0aa00e0437f0000 mov rdi,7F43E000AAA0h
00007f44`044fbc7c 488b3f          mov     rdi,qword ptr [rdi]
00007f44`044fbc7f 4889bd68ffffff  mov     qword ptr [rbp-98h],rdi
00007f44`044fbc86 488bbd70ffffff  mov     rdi,qword ptr [rbp-90h]
00007f44`044fbc8d 33f6            xor     esi,esi
00007f44`044fbc8f 48ba20f5be03447f0000 mov rdx,7F4403BEF520h
00007f44`044fbc99 48b9e0d14eff437f0000 mov rcx,7F43FF4ED1E0h
00007f44`044fbca3 e8e0b4b2fb      call    00007f44`00027188 (System.MulticastDelegate.CtorOpened(System.Object, IntPtr, IntPtr), mdToken: 00000000060004ED)
00007f44`044fbca8 488bbd68ffffff  mov     rdi,qword ptr [rbp-98h]
00007f44`044fbcaf 488bb570ffffff  mov     rsi,qword ptr [rbp-90h]
00007f44`044fbcb6 48b828b16e04447f0000 mov rax,7F44046EB128h
00007f44`044fbcc0 393f            cmp     dword ptr [rdi],edi
00007f44`044fbcc2 ff10            call    qword ptr [rax] (StackExchange.Redis.ConnectionMultiplexer.add_InternalError(System.EventHandler`1<StackExchange.Redis.InternalErrorEventArgs>), mdToken: 00000000060001FC)
00007f44`044fbcc4 90              nop
00007f44`044fbcc5 48b8a0aa00e0437f0000 mov rax,7F43E000AAA0h
00007f44`044fbccf 488b00          mov     rax,qword ptr [rax]
00007f44`044fbcd2 488945d0        mov     qword ptr [rbp-30h],rax
00007f44`044fbcd6 90              nop
00007f44`044fbcd7 eb00            jmp     00007f44`044fbcd9
00007f44`044fbcd9 488b45d0        mov     rax,qword ptr [rbp-30h]
00007f44`044fbcdd 4881c4d0000000  add     rsp,0D0h
00007f44`044fbce4 5d              pop     rbp
00007f44`044fbce5 c3              ret
00007f44`044fbce6 55              push    rbp
00007f44`044fbce7 4883ec10        sub     rsp,10h
00007f44`044fbceb 488b2f          mov     rbp,qword ptr [rdi]
00007f44`044fbcee 48892c24        mov     qword ptr [rsp],rbp
00007f44`044fbcf2 488dadd0000000  lea     rbp,[rbp+0D0h]
00007f44`044fbcf9 8b7de8          mov     edi,dword ptr [rbp-18h]
00007f44`044fbcfc 400fb6ff        movzx   edi,dil
00007f44`044fbd00 85ff            test    edi,edi
00007f44`044fbd02 740a            je      00007f44`044fbd0e
00007f44`044fbd04 488b7df0        mov     rdi,qword ptr [rbp-10h]
00007f44`044fbd08 e83317dd74      call    libcoreclr!JIT_MonExit_Portable (00007f44`792cd440)
00007f44`044fbd0d 90              nop
00007f44`044fbd0e 90              nop
00007f44`044fbd0f 4883c410        add     rsp,10h
00007f44`044fbd13 5d              pop     rbp
00007f44`044fbd14 c3              ret

重点来了,Wisder.xRiver.BaseCore.Util.xRedis.get_Instance() 这个方法其实是 Instance 属性的 get 方法。

可以继续使用 ip2md 命令将指令地址转换出模块信息:

0:000> !sos ip2md 00007f44`044fb96a
MethodDesc:   00007f4403caf880
Method Name:          Wisder.xRiver.BaseCore.Util.xRedis.get_Instance()
Class:                00007f4403d1a278
MethodTable:          00007f4403cafe48
mdToken:              00000000060000B3
Module:               00007f440264de00
IsJitted:             yes
Current CodeAddr:     00007f44044fb890
Version History:
  ILCodeVersion:      0000000000000000
  ReJIT ID:           0
  IL Addr:            00007f447142f990
     CodeAddr:           00007f44044fb890  (MinOptJitted)
     NativeCodeVersion:  0000000000000000

找到模块后,查看一下信息就可以找到对应的 dll 文件:

0:000> !sos DumpModule /d 00007f440264de00
Name: /xxx/xRiver.BaseCore.dll
Attributes:              PEFile IsFileLayout 
TransientFlags:          00209011 
Assembly:                00005558fc05f540
BaseAddress:             00007F447142A000
PEAssembly:              00005558FC03ABE0
ModuleId:                00007F440264E990
ModuleIndex:             0000000000000064
LoaderHeap:              0000000000000000
TypeDefToMethodTableMap: 00007F4402650000
TypeRefToMethodTableMap: 00007F4402650560
MethodDefToDescMap:      00007F4402650EE8
FieldDefToDescMap:       00007F4402653550
MemberRefToDescMap:      0000000000000000
FileReferencesMap:       00007F4402655948
AssemblyReferencesMap:   00007F4402655950
MetaData start address:  00007F4471444540 (148124 bytes)

那么接下来就是找到这个 dll 文件对应的源码项目,重点关注一下里面 get_Instance 方法。

namespace Wisder.xRiver.BaseCore.Util
{
    public static class xRedis
    {
        private static ConnectionMultiplexer _instance = null;

        /// <summary>
        /// 使用一个静态属性来返回已连接的实例,如下列中所示。
        /// 这样,一旦 ConnectionMultiplexer 断开连接,便可以初始化新的连接实例。
        /// </summary>
        public static ConnectionMultiplexer Instance
        {
            get
            {
                if (Constr.Length == 0)
                {
                    throw new Exception("Redis连接字符串未设置!");
                }

                if (_instance == null)
                {
                    lock (_locker)
                    {
                        if (_instance == null || !_instance.IsConnected)
                        {
                            var options = ConfigurationOptions.Parse(Constr);
                            options.ConnectTimeout = 10000; // 设置连接超时时间为10秒
                            options.SyncTimeout = 15000; // 设置同步操作的超时时间为15秒

                            _instance = ConnectionMultiplexer.Connect(options); //Constr
                        }
                    }
                }

                //注册如下事件
                _instance.ConnectionFailed += MuxerConnectionFailed;
                _instance.ConnectionRestored += MuxerConnectionRestored;
                _instance.ErrorMessage += MuxerErrorMessage;
                _instance.ConfigurationChanged += MuxerConfigurationChanged;
                _instance.HashSlotMoved += MuxerHashSlotMoved;
                _instance.InternalError += MuxerInternalError;
                return _instance;
            }
        }
    }
}

解决思路:把事件注册挪到最里面的 if 内部,_instance 赋值的后面。后续修改后可以观察下情况。

总结分析

一个事件注册会产生一个 64 Byte 大小的对象,不要小看它,积少成多,照样会导致内存泄露问题。

这让我不由得想起了 PHP 语言,一个请求结束就会销毁进程,可有效避免内存泄露问题,实在不行再重启一下 php 服务,也可以解决内存泄露问题。回到 .net 这一类平台上,就可以好好写代码,提高代码质量,避免内存泄露等问题。

posted @ 2024-07-18 10:44  successgo  阅读(1170)  评论(10编辑  收藏  举报