令人难以置信的逻辑线程数; windbg看不到他们?

时间:2011-05-18 17:40:51

标签: .net debugging windbg

我有一个显示~4,294,965,900“当前逻辑线程”的进程(根据性能计数器)和~400个物理线程。

我使用ADPlus(-hang)创建了一个内存转储,而windbg(!threads)只显示了物理线程。

如何找出所有这些逻辑线程的来源?

4 个答案:

答案 0 :(得分:4)

对我来说这看起来很可疑。

以无符号32位整数表示的数字-1396为4,294,965,900,而1396看起来更合理。

某处可能是某个错误?

答案 1 :(得分:0)

由于您的进程正在运行托管代码,因此逻辑线程计数可能是指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

请注意,在输出顶部会打印出统计信息。如果发现过多的死线程,可能表明资源泄漏。查看此类资源泄漏的one example

在!threads输出中,左列是非托管线程ID(与~命令显示的相同),第二列是CLR线程ID,第三列是OS线程ID。

答案 2 :(得分:0)

  

如何找出所有这些逻辑线程的来源?

他们不是。它们不存在。你根本不能拥有40亿个任何种类的线程,除非你在64位机器上运行,哦,至少说几个PB的RAM / em>的

每个线程,无论是“物理”OS线程还是由某个框架提供,至少需要某种标识符。如果这是一个32位数字,那么只存储这些标识符将占用近16GB的RAM。 (当然,你还剩下大约1600个未使用的标识符)。如果标识符是64位宽,则需要32GB RAM。最重要的是,每个线程都需要一些堆栈空间(常见的默认值是1MB,这会带来高达4 PB的内存)。

这是一个错误。线程不存在,性能计数器由于某种原因向您报告垃圾值。

例如,它可能是一个负面的错误代码,当转换为无符号整数时,它会变成这个巨大的数字。

或者可能是其他一些错误情况。

答案 3 :(得分:0)

这周我遇到了同样的问题,同样的症状。是真的是的,我的服务器令人印象深刻,具有128G Ram和24核。

这里的问题确实是逻辑线程。如果可以避免,CLR不会创建真实线程。我有一个像timer.Change(10000, 10000)这样的具有定期重新激活功能的计时器,并且在计时器回调内部,我的代码挂在网络上,这使CLR运行时知道可以重用此“物理线程”。然后10秒钟后,再次触发计时器,并创建一个新的逻辑线程,依此类推。下一个问题是我的其余代码彻底使用了Tasks,并且这些任务也会拉逻辑线程。结合所有这些,您将在一两周内产生数十亿个逻辑线程的连锁反应。

我的解决方法很简单:使计时器不再重复运行,而是仅在前一个计时器完成后才重新安排下一个计时器触发器: timer.Change(10000,Timeout.Infinite)并进行计时器回调,以便在合理的超时后取消io。