一:背景

1. 讲故事

年前有位朋友找到我,说他们的程序会偶发性卡慢 10s 钟,在某些组合下会正常,某些组合下就会出现问题,解释不了其中的原因,让我帮忙看下怎么回事?截图如下:


private void TestRun()
{
int encposUpy = 0;
Logger Log = new Logger();
Task.Factory.StartNew(delegate
{
Log.Info("GTN_GetEcatEncPos.上探头Y------start。");
while (runFlag)
{
Log.Info($"GTN_GetEcatEncPos.上探头Y --{encposUpy}");
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
mc.GTN_GetEcatEncPos(nCore, 2, out encposUpy);
if (stopwatch.ElapsedMilliseconds > 500)
{
Log.Info($"GTN_GetEcatEncPos.上探头y超时报警------{stopwatch.ElapsedMilliseconds}");
MessageBox.Show("卡顿现象出现,测试停止.");
runFlag = false;
}
Thread.Sleep(10);
}
MessageBox.Show("测试结束.");
});
}

这种问题还是挺有意思的,即 GTN_GetEcatEncPos 方法会有 10s 的卡慢情况,接下来我们就来探究下。

二:为什么会卡慢

1. 使用 perfview

像 GTN_GetEcatEncPos 这种动态性的卡死,首先看dump不是一个好的策略,最好的方式就是给程序安装摄像头,采集程序的运行状态,这里推荐的自然是 PerfView,开启墙钟模式,即定期的采集线程栈数据。

朋友按照建议拿到了 etl 文件,拿到 etl 文件之后,搜索 TestRun 方法,搜索内部匿名函数,截图如下:

从卦中看果然给捕获到了,那个所谓的 10s 卡满,原来是在 gts(固高运动卡) 下的 kernelbase!WaitForSingleObject 上,由于 gts 是闭源的,拿不到 pdb 符号所以显示不出内部函数,虽然没有直接找到祸根,但还是有一点进展的。

有些朋友可能会好奇,这个 perfview 到底追踪了多久,这个可以通过 TraceInfo 选项卡观察,截图如下:

从卦中可知,当前追踪了 65s。

2. 路在何方

只知道在 kernelbase!WaitForSingleObject 上等待了10s并不能解决问题,那怎么办呢?刚好朋友也给了我一份当时故障时的dump,这时候就要结合起来一起看,争取找到突破口。

首先通过 ~*e k 寻找 TestRun 函数的调用栈,输出如下:

...
0:011:x86> k
# ChildEBP RetAddr
00 0a1ef350 76a024e9 ntdll_77760000!NtWaitForSingleObject+0xc
01 0a1ef350 76a02442 KERNELBASE!WaitForSingleObjectEx+0x99
02 0a1ef364 594a13d8 KERNELBASE!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
03 0a1ef388 721d284d gts!PvSplit+0x3b8
04 0a1ef3c0 06ead2f8 clr!PInvokeStackImbalanceHelper+0x22
05 0a1ef404 06c74476 System_Windows_Forms!DomainBoundILStubClass.IL_STUB_PInvoke(Int16, Int16, Int32 ByRef)+0x78
06 0a1ef4a8 66bad0ab xxx!xxx.xxx+<>c__DisplayClass136_0.<TestRun>b__0()+0x10e
07 0a1ef4b4 66baa0b1 mscorlib_ni!System.Threading.Tasks.Task.InnerInvoke()+0x4b
08 0a1ef4d8 66baa07c mscorlib_ni!System.Threading.Tasks.Task.Execute()+0x31
09 0a1ef540 66b48e34 mscorlib_ni!System.Threading.Tasks.Task.ExecutionContextCallback(System.Object)+0x1c
0a 0a1ef540 66b48d67 mscorlib_ni!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0xc4
...
1e 0a1efb5c 777c806e ntdll_77760000!__RtlUserThreadStart+0x2f
...

从卦中数据看果然是在 event 事件上等待,使用 kb 5 观察 event 参数,再使用 !handle 观察。


0:011:x86> kb 5
# ChildEBP RetAddr Args to Child
00 0a1ef350 76a024e9 00000818 00000000 00000000 ntdll_77760000!NtWaitForSingleObject+0xc
01 0a1ef350 76a02442 00000818 ffffffff 00000000 KERNELBASE!WaitForSingleObjectEx+0x99
02 0a1ef364 594a13d8 00000818 ffffffff 0a1ef3ac KERNELBASE!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
03 0a1ef388 721d284d 00000001 00000002 0288a9c8 gts!PvSplit+0x3b8
04 0a1ef3c0 06ead2f8 00000001 00000002 0288a9c8 clr!PInvokeStackImbalanceHelper+0x22 0:011:x86> !handle 00000818f
Handle 0000818f
Type <Error retrieving type>
0:011:x86> !handle 00000818 f
Handle 00000818
Type Event
Attributes 0
GrantedAccess 0x1f0003:
Delete,ReadControl,WriteDac,WriteOwner,Synch
QueryState,ModifyState
HandleCount 3
PointerCount 65540
Name \BaseNamedObjects\MultiProcess
Object specific information
Event Type Auto Reset
Event is Waiting

从卦中可以看到当前是一个名为 \BaseNamedObjects\MultiProcess 的 AutoResetEvent 事件,正处于等待状态,验证了 perfview 的数据,那到底是在等待谁呢?

3. 在绝望中寻找希望

分析dump就是这样,一步一个坎。。。所以不抛弃不放弃,因为这个程序是一个窗体程序,朋友又提到了卡死的关键词,所以本能的想看看此时的主线程正在做什么,使用 ~0s ; k 命令。


0:000:x86> ~0s; k
# ChildEBP RetAddr
00 006fe638 76a024e9 ntdll_77760000!NtWaitForSingleObject+0xc
01 006fe638 76a02442 KERNELBASE!WaitForSingleObjectEx+0x99
02 006fe64c 75501328 KERNELBASE!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
03 006fe668 75544ac5 sysfer+0x1328
04 006fe878 755449c9 sysfer+0x44ac5
05 006fe910 755448ff sysfer+0x449c9
06 006fe98c 75542ec6 sysfer+0x448ff
07 006fe9d0 777d324c sysfer+0x42ec6
08 006fea30 76a1ac32 ntdll_77760000!NtSetInformationFile+0xc
09 006fea30 594a1bcc KERNELBASE!SetFilePointer+0x72
0a 006fea54 594a1fff gts!PvSplit+0xbac
0b 006fea68 5948164a gts!PvSplit+0xfdf
0c 006fea88 59442e78 gts!GTN_SetHookSubModuleActive+0x70a
0d 006feaa4 721d284d gts!GTN_GetDo+0x38
0e 006feadc 06ead2f8 clr!PInvokeStackImbalanceHelper+0x22
0f 006feb20 06ead89b System_Windows_Forms!DomainBoundILStubClass.IL_STUB_PInvoke(Int16, Int16, Int32 ByRef)+0x78
10 006fec08 06eacfe6 xxx!xxx.xxx.CompareSts()+0x1eb
11 006fed6c 06eacb35 xxx!xxx.xxx.timerSts_Tick(System.Object, System.EventArgs)+0x49e
12 006fed80 06eac3ae System_Windows_Forms!System.Windows.Forms.Timer.OnTick(System.EventArgs)+0x15
...

不看不知道,一看卦吓一跳,除了刚才已经熟悉的 gts!PvSplit ,还发现了一个未知的 sysfer.dll ,这是啥玩意,一下子就提起了兴趣,使用 lmvm sysfer 观察。


0:000:x86> lmvm sysfer
Browse full module list
start end module name
75500000 7557e000 sysfer (no symbols)
Loaded symbol image file: sysfer.dll
Image path: C:\Windows\SysWOW64\sysfer.dll
Image name: sysfer.dll
Browse all global symbols functions data Symbol Reload
Timestamp: Sat Apr 20 02:38:55 2019 (5CBA15BF)
CheckSum: 0006E5AE
ImageSize: 0007E000
File version: 14.2.3329.1000
Product version: 14.2.3329.1000
File flags: 0 (Mask 0)
File OS: 40004 NT Win32
File type: 1.0 App
File date: 00000000.00000000
Translations: 0409.04e4
Information from resource tables:
CompanyName: Symantec Corporation
ProductName: Symantec CMC Firewall
InternalName: sysfer
OriginalFilename: sysfer.dll
ProductVersion: 14.2.3329.1000
FileVersion: 14.2.3329.1000
FileDescription: Symantec CMC Firewall sysfer
LegalCopyright: Copyright (c) 2006-2019 Symantec Corporation. All rights reserved. Use of this product is subject to license terms.

Symantec CMC Firewall sysfer 来看,应该是赛门铁克的一个 客户端防火墙组件,再回头看调用栈,大概就是 gts 在内部设置文件偏移指针(SetFilePointer) 的时候被 赛门铁克 拦截了。

到这里基本上就弄清楚了卡死 10s 的来龙去脉,11号线程在 gts 中等待 0号线程 唤醒它的 event 事件。 而 0号线程不巧在设置文件指针的时候被 赛门铁克 拦截了,在这拦截的10s内,导致 0 号线程没有及时的唤醒 11 号线程所等待的事件,最终导致悲剧的发生。。。

三:总结

这次卡慢事故是由于 赛门铁克 导致,其实杀毒软件对我们程序来说真的是一个特别不稳定的因素,在我的分析旅程中,我见过杀毒软件导致的崩溃,卡死,卡慢,内存泄露 等等奇葩情况,无语了。。。

记一次 .NET某固高运动卡测试 卡慢分析的更多相关文章

  1. AD15高版软件卡不卡,问题解决大讨论

    AD高版软件很卡(包括13 14 15版),这是我遇到过的问题,大家都遇到过的问题, 这里我分享一个解决办法:也请给位有什么好的方法也一起分享. 问题1卡:打开AD15软件, 按住鼠标中键 放大 或 ...

  2. 单点登录CAS使用记(七):关于服务器超时以及客户端超时的分析

    我的预想情况 一般情况下,当用户登录一个站点后,如果长时间没有发生任何动作,当用户再次点击时,会被强制登出并且跳转到登录页面, 提醒用户重新登录.现在我已经为站点整合了CAS,并且已经实现了单点登录以 ...

  3. Redis高可用之主从复制原理演进分析

    Redis高可用之主从复制原理演进分析 在很久之前写过一篇 Redis 主从复制原理的简略分析,基本是一个笔记类文章. 一.什么是主从复制 1.1 什么是主从复制 主从复制,从名字可以看出,至少需要 ...

  4. 【原创】记一次MySQL大表高并发写入引发CPU飙升的排障过程

    目录 一.故障现象... 1 二.初步分析... 2 三.排障过程... 2 1.排查是否QPS或insert并发请求上升导致问题发生... 2 2.排查是否锁资源等待或block导致了insert变 ...

  5. 再记一次 应用服务器 CPU 暴高事故分析

    一:背景 1. 前言 大概有2个月没写博客了,不是不想写哈

  6. 记一次mogodb占用cpu高问题

    公司服务器上安装了contly,是一个开源的node.js项目,用于统计手机app使用情况,后端数据储存使用的mongodb,使用的时候经常发现mongodb占用cpu非常高,打到了210%的爆表值 ...

  7. 足球运动训练心得及经验分析-c语言学习调查

    在准备预备作业02之前,我参考娄老师的提示,阅读了<[做中学(Learning By Doing)]之乒乓球刻意训练一年总结>一文. 在文章描述的字里行间,给予我的印象是系统.负责,娄老师 ...

  8. 记一次 .NET 某电商交易平台Web站 CPU爆高分析

    一:背景 1. 讲故事 已经连续写了几篇关于内存暴涨的真实案例,有点麻木了,这篇换个口味,分享一个 CPU爆高 的案例,前段时间有位朋友在 wx 上找到我,说他的一个老项目经常收到 CPU > ...

  9. 记一次 .NET 某纺织工厂 MES系统 API 挂死分析

    一:背景 1. 讲故事 这个月中旬,有位朋友加我wx求助他的程序线程占有率很高,寻求如何解决,截图如下: 说实话,和不同行业的程序员聊天还是蛮有意思的,广交朋友,也能扩大自己的圈子,朋友说他因为这个b ...

  10. 谈论高并发(十二)分析java.util.concurrent.atomic.AtomicStampedReference看看如何解决源代码CAS的ABA问题

    于谈论高并发(十一)几个自旋锁的实现(五岁以下儿童)中使用了java.util.concurrent.atomic.AtomicStampedReference原子变量指向工作队列的队尾,为何使用At ...

随机推荐

  1. 安装K8s集群

    因阿里云加速服务调整,镜像加速服务自2024年7月起不再支持,拉取镜像,下载网络插件等操作,需要国际联网访问DockerHub. 安装全过程均使用ROOT权限. 1.安装前准备工作 这里采用3台Cen ...

  2. 缓冲流的使用:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter

    处理流之一 :缓冲流    当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区 当使用BufferedInputStream读取字节文件时,BufferedInputStream会一次 ...

  3. VScode配置X11转发!让你彻底摆脱显示屏!!!

    作者:SkyXZ CSDN:SkyXZ--CSDN博客 博客园:SkyXZ - 博客园 在我们远程SSH使用开发板或者是服务器开发的时候,你是否总是苦于没有图像显示环境导致OpenCV的cv2.sho ...

  4. 2025春秋杯部分wpDAY1

    2025春秋杯 DAY1 WEB easy_flask 直接fenjing一把梭 file_copy 下载github上的脚本 MISC 简单算术 题目提示了异或 简单镜像提取 formost提取到镜 ...

  5. angularjs和ajax的结合使用 (四)

    知道的朋友了解 我不是属于讲按部就班技术的那种人.什么xx入门 ,入门到精通,入门到入土. 其实非要严格说的话已经跟angularjs 什么ajax 偏的有点远了,之所以还是叫这个名称,因为都属于we ...

  6. tomcat配置用户名密码

    1.配置tomcat-user.xml<role rolename="manager-gui"/><role rolename="manager-scr ...

  7. 洛谷P2789 直线交点数 题解

    解题思路 考虑将直线分组,每组内直线互相平行,任意两组直线间交点数量等于两组内直线数量乘积. 分组操作使用dfs,求出交点数量后加入set去重,输出set大小. 时间复杂度O(2NN2)有点鬼畜但是可 ...

  8. 创建Graphics对象的三种方法

    参考链接:https://www.cnblogs.com/wax01/p/4982691.html 方法一.利用控件或窗体的Paint事件中的PainEventArgs 在窗体或控件的Paint事件中 ...

  9. 零基础使用AI辅助编写易简历小程序的一些心得体会

    春节期间利用了一点时间体验了Copilot开发了一个小程序,先说结论: AI只是AI,并不能取代程序员. 你能做的,AI能做的更快:你不能做的,AI就大概率会糊弄你. 开发小程序的背景就是本身有一个易 ...

  10. 什么是A型或者B型剩余电流保护器?

    我国的剩余电流保护装置(RCD)指导性标准GB/Z 6829-2008(IEC/TR 60755:2008,MOD)<剩余电流动作保护器的一般要求> 从产品的基本结构.剩余电流类型.脱扣方 ...