一:背景1.讲故事在分析的众多dump中,经常会遇到各种奇葩的问题,仅通过dump这种快照形式还是有很多问题搞不定,而通过 perfview 这种粒度又太粗 , 很难找到问题之所在,真的很头疼,比如本篇的 短命线程
问题,参考图如下:
文章插图
我们在 t2 时刻抓取的dump对查看
短命线程
毫无帮助 , 我根本就不知道这个线程生前执行了什么代码,为什么这么短命,还就因为这样的短命让 线程池 的线程暴增 。为了能尽最大努力解决此类问题,武器库中还得再充实一下,比如本系列要聊的
Time Travel Debug
,即时间旅行调试 。二: Time Travel Debug1. 什么是 时间旅行调试如果说 dump 是程序的一张照片,那 TTD 就是程序的一个短视频,很显然短视频的信息量远大于一张照片,因为视频记录着疑难杂症的前因后果,参考价值巨大,简直就是银弹般的存在 。
三:案例演示1. 参考代码这是我曾经遇到的一个真实案例,在没有 TTD 的协助下最终也艰难的找到了问题 , 但如果有 TTD 的协助简直就可以秒杀 , 为了方便说明,先上一个测试代码 。
internal class Program{static void Main(string[] args){for (int i = 0; i < 200; i++){Task.Run(() =>{Test();});}Console.ReadLine();}public static int index = 1;static void Test(){Thread.Sleep(1000);var i = 10;var j = 20;var sum = i + j;Console.WriteLine($"i={index++},sum={sum}");}}
程序跑完之后,我们抓一个dump文件,输出如下 。0:000> !tThreadCount:20UnstartedThread:0BackgroundThread: 7PendingThread:0DeadThread:13Hosted Runtime:noLock DBGIDOSID ThreadOBJState GC ModeGC Alloc ContextDomainCount Apt Exception0112f8 00C4AF2080030220 Preemptive03C3FFAC:03C40000 00c462f8 -00001 Ukn626a70 00C5BBD82b220 Preemptive03C521B8:03C53FE8 00c462f8 -00001 MTA (Finalizer)XXXX40 00C9FEB01039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)756694 00CA0990302b220 Preemptive03C40314:03C41FE8 00c462f8 -00001 MTA (Threadpool Worker)XXXX60 00CB53B81039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)XXXX70 00CB59581039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)XXXX80 00CB43381039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)XXXX90 00CB4C581039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)XXXX100 088792781039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)8115d10 08879E90102b220 Preemptive03C2AC2C:03C2BFE8 00c462f8 -00001 MTA (Threadpool Worker)XXXX120 0887D1F81039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)XXXX130 0887C0D81039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)XXXX140 0887AB701039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)XXXX150 0887B4001039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)XXXX160 0887D6401039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)XXXX170 0887A7281039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)9185658 0887C520102b220 Preemptive03C46684:03C47FE8 00c462f8 -00001 MTA (Threadpool Worker)1019564 0887C968102b220 Preemptive03C4A664:03C4BFE8 00c462f8 -00001 MTA (Threadpool Worker)XXXX200 0887AFB81039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)113547c 0887A2E02b220 Preemptive03C50008:03C51FE8 00c462f8 -00001 MTA
2. 为什么会有很多短命线程从 windbg
的输出看有很多的 XXX,那原因是什么呢? 还得先观察下代码,可以看到代码会给 ThreadPool 分发 100 次任务,每个任务也就 1s 的运行时间,这样的代码会造成 ThreadPool 的工作线程处理不及继而会产生更多的工作线程,在某一时刻那些 Sleep 后的线程又会规模性唤醒,ThreadPool 为了能够平衡工作者线程,就会灭掉很多的线程,造成 ThreadPool 中的暴涨暴跌现象 。因果关系是搞清楚了,但对于落地是没有任何帮助的,比如线程列表倒数第二行已死掉的线程:
XXXX200 0887AFB81039820 Preemptive00000000:00000000 00c462f8 -00001 Ukn (Threadpool Worker)
你是没法让它起死回生的,对吧?这时候就必须借助 TTD 录制一个小视频 。3. TTD 录制录制非常简单,选择
Lauch executable (advanced)
项再勾选 Record
即可,截图如下:文章插图
【第一篇 TTD 专题 :C# 那些短命线程都在干什么?】等程序执行完了或者你觉得时机合适再点击
Stop and Debug
停止录制,截图如下:推荐阅读
- 第五周 python实验报告
- 自定义View6 -塔防小游戏:第三篇防御塔随意放置+多组野怪
- 2021年Q4手机用户偏好榜-2021年安兔兔第四季度用户偏好榜
- 龙王五子饕餮怎么念(龙王第五个儿子饕餮之死)
- 保卫萝卜4阿波道长第24关怎么过
- 保卫萝卜4阿波道长第23关怎么过
- 一篇文章带你掌握主流基础框架——Spring
- 斗罗大陆:武魂觉醒荒野行纪第八章怎么过
- 斗罗大陆:武魂觉醒荒野行纪第七章怎么过
- ipad分屏怎么打开(ipad第九代分屏功能)