.net 难以置信的逻辑线程数量;windbg can';你没看见他们吗?
我有一个进程显示了约4294965900个“当前逻辑线程”(根据性能计数器)和约400个物理线程 我已经使用ADPlus(-hang)创建了一个内存转储,windbg(!threads)只显示物理线程.net 难以置信的逻辑线程数量;windbg can';你没看见他们吗?,.net,debugging,windbg,.net,Debugging,Windbg,我有一个进程显示了约4294965900个“当前逻辑线程”(根据性能计数器)和约400个物理线程 我已经使用ADPlus(-hang)创建了一个内存转储,windbg(!threads)只显示物理线程 如何找出所有这些逻辑线程的来源?这在我看来似乎是一个可疑的高数字 表示为无符号32位整数的数字-1396是4294965900,1396看起来更合理 某个地方可能有bug?因为您的进程正在运行托管代码,所以逻辑线程计数很可能是指CLR线程。Net在CLR逻辑线程和物理线程之间进行映射。要进一步调查
如何找出所有这些逻辑线程的来源?这在我看来似乎是一个可疑的高数字 表示为无符号32位整数的数字-1396是4294965900,1396看起来更合理
某个地方可能有bug?因为您的进程正在运行托管代码,所以逻辑线程计数很可能是指CLR线程。Net在CLR逻辑线程和物理线程之间进行映射。要进一步调查此问题,您可以使用!Windbg中的threads命令。以下是此命令的输出示例:
0:028> !threads
ThreadCount: 25
UnstartedThread: 0
BackgroundThread: 22
PendingThread: 0
DeadThread: 3
Hosted Runtime: yes
PreEmptive GC Alloc Lock
ID OSID ThreadOBJ State GC Context Domain Count APT Exception
0 1 12b0 007b69d0 4220 Enabled 120337b4:12034a3c 007afef8 0 STA
6 2 1f70 007c2688 b220 Enabled 11ed2a84:11ed4a3c 007afef8 0 MTA (Finalizer)
7 3 2340 007c8ac8 1220 Enabled 00000000:00000000 007afef8 0 Ukn
11 4 1c4c 0aaf3380 7220 Enabled 00000000:00000000 007afef8 0 STA
13 8 2414 0d4932f0 220 Enabled 00000000:00000000 007afef8 0 Ukn
3 a 2780 0d4d08e8 1009220 Enabled 00000000:00000000 007afef8 0 MTA (Threadpool Worker)
15 7 970 0d4d0df0 1009220 Enabled 11ed4ad8:11ed6a3c 007afef8 0 MTA (Threadpool Worker)
19 9 2510 0d4d12f8 200b220 Enabled 00000000:00000000 007afef8 0 MTA
20 b 80c 0d4d1800 200b220 Enabled 00000000:00000000 007afef8 0 MTA
21 c 2490 0d4d1d08 200b220 Enabled 00000000:00000000 007afef8 0 MTA
23 d 2724 0d4d2210 1009220 Enabled 00000000:00000000 007afef8 0 MTA (Threadpool Worker)
24 e 2200 0d4d2718 1009220 Enabled 00000000:00000000 007afef8 0 MTA (Threadpool Worker)
26 f 1f3c 0d4d2c20 1009220 Enabled 00000000:00000000 007afef8 0 MTA (Threadpool Worker)
25 10 200c 0d4d3128 1009220 Enabled 00000000:00000000 007afef8 0 MTA (Threadpool Worker)
27 11 2708 0d4d3630 1009220 Enabled 00000000:00000000 007afef8 0 MTA (Threadpool Worker)
17 6 21b4 0d4d3b38 1009220 Enabled 00000000:00000000 007afef8 0 MTA (Threadpool Worker)
18 5 2148 0d4d4548 220 Enabled 00000000:00000000 007afef8 0 MTA
XXXX 16 0d4d6378 19820 Enabled 00000000:00000000 007afef8 0 MTA
XXXX 15 0d4d5e70 19820 Enabled 00000000:00000000 007afef8 0 MTA
30 14 112c 0d4d5968 200b220 Enabled 00000000:00000000 007afef8 0 MTA
32 13 2734 0d4d5460 b220 Enabled 00000000:00000000 007afef8 0 MTA
33 12 11ec 0d4d4a50 100a220 Enabled 00000000:00000000 007afef8 0 MTA (Threadpool Worker)
34 17 166c 0d4d6880 8009220 Enabled 00000000:00000000 007afef8 0 MTA (Threadpool Completion Port)
35 18 24f4 0d4d6d88 8009220 Enabled 00000000:00000000 007afef8 0 MTA (Threadpool Completion Port)
XXXX 19 0d4d7798 19820 Enabled 00000000:00000000 007afef8 0 Ukn
注意:在输出的顶部,它打印出统计数据。如果您发现大量的死线程,这可能表明资源泄漏。签出此类型的资源泄漏
在这个世界上!线程输出左列是非托管线程ID(与~
命令显示的相同),第二列是CLR线程ID,第三列是OS线程ID
如何找出所有这些逻辑线程的来源
他们不是。他们不存在。你不可能有任何类型的40亿个线程,除非你运行在一台64位的机器上,至少有几PB的RAM
每个线程,无论是“物理”操作系统线程还是由某个框架提供的线程,都至少需要某种标识符。如果这是一个32位的数字,那么仅仅存储这些标识符将占用近16GB的RAM。(当然,还剩下大约1600个未使用的标识符)。如果标识符为64位宽,则需要32GB RAM。除此之外,每个线程都需要一些堆栈空间(一个常见的默认值是1MB,这使我们最多有4 PB的内存)
这是一只虫子。线程不存在,性能计数器出于某种原因向您报告垃圾值
例如,它可能是一个负错误代码,当转换为无符号整数时,它会变成这个巨大的数字
或者可能是其他一些错误情况。我这周也有同样的问题,同样的症状。这是真的。是的,我的服务器令人印象深刻,128G Ram和24核 这里的问题确实是逻辑线程。如果CLR可以避免,它就不会创建真正的线程。我有一个定期重新激活的计时器,比如
Timer.Change(10000,10000)
,在计时器回调中,我的代码挂在网络上,这让CLR运行时知道这个“物理线程”可以重用。10秒后,计时器再次触发,并创建一个新的逻辑线程,依此类推。下一个问题是,我的其余代码完全使用了任务,而这些任务也使用了逻辑线程。将所有这些结合起来,您将在一两周内产生数十亿个逻辑线程的连锁反应
我的解决方法很简单:使计时器不再重复,但只在前一个计时器触发器完成后重新安排下一个计时器触发器:
timer.Change(10000,Timeout.Infinite)
并进行计时器回调,以便在某个合理的超时时取消io。并且重申,是的,当然这是一个可疑的高数字。这就是为什么我要找出他们在哪里。记住,WinDbg只显示了约400个物理线程,所以不,我认为实际上没有约1400个线程。我没有得到升级票?你怎么会有负数的线程?这个数字来自Windows性能计数器,它是一个64位的数字。@马克:因为这个小小的负数是报告这个高得离谱数字的合理解释-例如,1396可能是一个错误代码。@jalf:现在你提到它,错误代码听起来确实是一个合理的解释。第一个数字看起来像是一个bug,但即使是400个线程也太多了,除非它运行在一个巨大的多核服务器上。我在项目中包括MS SQL Express 2005时看到了这一点,您的代码中是否有MS SQL访问权限,是否可以删除这些权限以查看逻辑线程是否是由于这些权限造成的?它运行在一台令人印象深刻的服务器上。@Mark您是否知道为什么会发生这种情况?@StephanRyer我没有,对不起。好的,您会注意到我这样做了,并且只显示了物理线程。