记一次 .NET某固高运动卡测试 卡慢分析

一:背景

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+0x220:011:x86> !handle 00000818f
Handle 0000818fType         	<Error retrieving type>
0:011:x86> !handle 00000818 f
Handle 00000818Type         	EventAttributes   	0GrantedAccess	0x1f0003:Delete,ReadControl,WriteDac,WriteOwner,SynchQueryState,ModifyStateHandleCount  	3PointerCount 	65540Name         	\BaseNamedObjects\MultiProcessObject specific informationEvent Type Auto ResetEvent 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.dllImage path: C:\Windows\SysWOW64\sysfer.dllImage name: sysfer.dllBrowse all global symbols  functions  data  Symbol ReloadTimestamp:        Sat Apr 20 02:38:55 2019 (5CBA15BF)CheckSum:         0006E5AEImageSize:        0007E000File version:     14.2.3329.1000Product version:  14.2.3329.1000File flags:       0 (Mask 0)File OS:          40004 NT Win32File type:        1.0 AppFile date:        00000000.00000000Translations:     0409.04e4Information from resource tables:CompanyName:      Symantec CorporationProductName:      Symantec CMC FirewallInternalName:     sysferOriginalFilename: sysfer.dllProductVersion:   14.2.3329.1000FileVersion:      14.2.3329.1000FileDescription:  Symantec CMC Firewall sysferLegalCopyright:   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 号线程所等待的事件,最终导致悲剧的发生。。。

三:总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/78928.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

硬件知识积累 单片机+ 光耦 + 继电器需要注意的地方

1. 电路图 与其数值描述 1.1 单片机引脚信号为 OPtoCoupler_control_4 PC817SB 为 光耦 继电器 SRD-05VDC-SL-A 的线圈电压为 67Ω。 2. 需注意的地方 1. 单片机的推挽输出的电流最大为 25mA 2. 注意光耦的 CTR 参数 3. 注意继电器线圈的 内阻 4. 继电器的开启电压。 因为光耦…

IP组播技术与internet

1.MAC地址分为三类&#xff1a;广播地址&#xff1b;组播地址&#xff1b;单播地址 2.由一个源向一组主机发送信息的传输方式称为组播。 3.组播MAC地址&#xff0c;第一个字节的最后一位为1&#xff1b; 单播MAC地址&#xff0c;第一个字节的最后一位为0&#xff1b; 4.不能…

vue3+vite+ts使用daisyui/tailwindcss

vite创建vue3脚手架 npm init vitelatest myVue3 – --template vue cd .\myVue3\ npm i npm run dev 安装tailwindcss/daisyui 依赖安装 npm install -D tailwindcss postcss autoprefixer daisyui npx tailwindcss init -p 这条命令将生成postcss.config.js(因为加了…

大数据(7)Kafka核心原理揭秘:从入门到企业级实战应用

目录 一、大数据时代的技术革命1.1 消息中间件演进史1.2 Kafka核心设计哲学 二、架构深度解构2.1 核心组件拓扑2.1.1 副本同步机制&#xff08;ISR&#xff09; 2.2 生产者黑科技2.3 消费者演进路线 三、企业级应用实战3.1 金融行业实时风控3.2 物联网数据管道 四、生产环境优化…

spring boot大文件与多文件下载

一、简单大文件下载&#xff1a; /*** 下载大文件* param path 路径* param fileName 文件名* return* throws IOException*/ public static ResponseEntity<InputStreamResource> downloadFile(String path, String fileName) throws IOException {Path filePath Path…

第二节:React 基础篇-受控组件 vs 非受控组件

一、场景题&#xff1a;设计一个实时搜索输入框&#xff0c;说明选择依据 受控组件 vs 非受控组件 核心区别 特征受控组件非受控组件数据管理由React状态&#xff08;state&#xff09;控制通过DOM元素&#xff08;ref&#xff09;直接访问更新时机每次输入触发onChange提交…

局部路由守卫

局部路由守卫为我们提供了更细粒度的路由控制&#xff0c;允许我们在特定的路由或组件级别添加鉴权和逻辑处理。局部路由守卫分为 path 守卫和 component 守卫&#xff0c;它们分别适用于不同的场景。 path 守卫&#xff08;路由守卫&#xff09; path 守卫用于在进入特定路由…

Android 16应用适配指南

Android 16版本特性介绍 https://developer.android.com/about/versions/16?hlzh-cn Android 16 所有功能和 API 概览 https://developer.android.com/about/versions/16/features?hlzh-cn#language-switching Android 16 发布时间 Android 16 适配指南 Google开发平台&…

android display 笔记(十二)CPU,GPU,DPU的区别

CPU&#xff08;Central Processing Unit&#xff09;通用计算&#xff1a;处理复杂逻辑、分支预测、多任务调度。 低延迟&#xff1a;优先快速响应单线程任务。 GPU&#xff08;Graphics Processing Unit&#xff09; 高吞吐量并行计算&#xff1a;适合大规模数据并行处理。…

音频转文本:如何识别音频成文字

Python脚本:MP4转MP3并语音识别为中文 以下是一个完整的Python脚本,可以将MP4视频转换为MP3音频,然后使用语音识别模型将音频转换为中文文本。 准备工作 首先需要安装必要的库: pip install moviepy pydub SpeechRecognition openai-whisper完整脚本 import os from m…

理解 MCP 协议的数据传递:HTTP 之上的一层“壳子

以下是以 CSDN 博客的风格记录你对 MCP 协议数据传递的理解和发现&#xff0c;内容涵盖了 MCP 协议基于 HTTP 的本质、JSON-RPC 的“壳子”作用&#xff0c;以及为什么熟悉 HTTP 协议就足以理解 MCP 的数据传递。文章面向技术社区&#xff0c;结构清晰&#xff0c;适合分享。 理…

基于ssm网络游戏推荐系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 当今社会进入了科技进步、经济社会快速发展的新时代。国际信息和学术交流也不断加强&#xff0c;计算机技术对经济社会发展和人民生活改善的影响也日益突出&#xff0c;人类的生存和思考方式也产生了变化。传统网络游戏管理采取了人工的管理方法&#xff0c;但这种管理方…

vue入门:指令

文章目录 vue的内置指令说明&#xff1a; 自定义指令 vue的内置指令 Vue 指令的本质是&#xff1a; 声明式的 DOM 操作接口&#xff08;隐藏底层 JavaScript 代码&#xff09;。响应式数据的绑定媒介&#xff08;连接数据和视图&#xff09;。模板编译的标记&#xff08;最终…

oracle 索引失效

在 Oracle 11g 中&#xff0c;索引失效的常见原因包括函数修改列、隐式类型转换、统计信息过时等&#xff0c;解决方法需结合版本特性&#xff08;如虚拟列、索引跳跃扫描&#xff09;。通过执行计划分析、统计信息维护和合理使用提示&#xff08;Hints&#xff09;&#xff0c…

k8s蓝绿发布

k8s蓝绿发布 什么是蓝绿部署K8S中如何实现蓝绿部署k8s蓝绿部署流程图 什么是蓝绿部署 参考: https://youtu.be/CLq_hA0lAd0 https://help.coding.net/docs/cd/best-practice/blue-green.html 蓝绿部署最早是由马丁福勒 2010年在他的博客中提出. 蓝绿部署是一种软件部署策略,用…

stm32面试

数据结构相关问题 stm32面试 数据结构相关问题 目录基础数据结构树与图排序与查找算法 Linux相关问题Linux系统基础Linux命令与脚本Linux网络与服务 操作系统相关问题操作系统基础概念操作系统调度算法操作系统同步与通信 STM32相关问题STM32硬件基础STM32编程与开发STM32应用与…

Mybatis 中 mappers标签 package的使用

MyBatis 的配置文件中&#xff0c;<mappers> 标签用于指定 MyBatis 应该加载哪些映射器&#xff08;Mapper&#xff09;。其中 package 属性是一种便捷的方式来批量注册多个映射器接口 package 属性允许你指定一个包名&#xff0c;MyBatis 会自动扫描该包下的所有映射器…

设计模式 --- 访问者模式

访问者模式是一种行为设计模式&#xff0c;它允许在不改变对象结构的前提下&#xff0c;定义作用于这些对象元素的新操作。 优点&#xff1a; 1.​​符合开闭原则&#xff1a;新增操作只需添加新的访问者类&#xff0c;无需修改现有对象结构。 ​​2.操作逻辑集中管理​​&am…

监控docker中的java应用

1)进入指定的容器 docker exec -it demo /bin/bash 2)下载curl root89a67e345354:/# apt install curl -y 3)下载arthas root89a67e345354:/# curl -O https://arthas.aliyun.com/arthas-boot.jar 4)运行 root89a67e345354:/# java -jar arthas-boot.jar 5)监控 […

最新版RubyMine超详细图文安装教程,带补丁包(2025最新版保姆级教程)

目录 前言 一、RubyMine最新版下载 二、RubyMine安装 三、RubyMine补丁 四、运行RubyMine 前言 RubyMine是由JetBrains开发的集成开发环境&#xff08;IDE&#xff09;&#xff0c;专为Ruby和Ruby on Rails开发者设计&#xff0c;提供智能代码补全、调试、测试、版本控制集…