调用.NET Serviced Component引发的性能问题及其解决
在企业用户环境里,.NET Serviced Component使用广泛。它比较好的把传统COM+封装和.NET应用逻辑衔接了起来,在服务器端应用起到重要作用。.NET Serviced Component 的使用需要注意到很多方面,特别是要做到对象资源合理应用(pooling)和及时释放(Dispose)。现有文章就这方面有很多具体讨论。
在这里,我要分析的是一种以前处理过的特定情况下.NET Serviced Component的引发的High CPU的问题。不只一个客户遇到此类问题,觉得有必要和大家分享一下。
如果程序出现High CPU,这个应用程序线程一定出现了繁忙的运算,比如重复的计算或者长时间的循环,而不是等待数据库,锁,或其它资源。如果这个程序是.NET程序,频繁Garbage Collection导致High CPU就必须要重点考虑。因为每次GC都需要检查.NET 对象树和调整.NET堆, 是繁重的操作。我们可以通过捕捉性能日志(perfmon),查看.NET CLR Memory 对象下的%Time in GC 和 Induced GC 这两个性能计数器指标,来判断High CPU是不是和GC有关。
在这个例子里面,通过查看性能监视器,可以看到Induced GC增长非常的快速,表明是这次High CPU的直接原因:
通常情况下,Induced GC 出现是客户代码里面直接调用了GC.Collect 。然而,在查看客户代码后,发现根本没有GC.Collect出现。
我们注意到这个程序里面使用了.NET Enterprise Serviced Components, 开始便建议客户使用Dispose方法释放这些Components, 而不是用DisposeObject:
并且尝试启用对象池,, 发现改善并不明显:
http://www.codeproject.com/Articles/579/COM-Object-Pooling
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684273(v=vs.85).aspx
于是在这个程序High CPU的时候抓取了Memory Dump。
注:抓取Memory Dump的方法很多,可以用WinDBG, procdump或者DebugDiag
通过仔细分析Memory Dump,发现Induced GC逻辑出现在以下Call Stack里面:
非托管 Call Stack:
- Child-SP RetAddr Call Site
- `0f59bbe8 `7704ce00 ntdll!ZwWaitForSingleObject+0xa
- `0f59bbf0 000007fe`f52fa74a kernel32!WaitForSingleObjectEx+0x9c
- `0f59bcb0 000007fe`f52fa83b mscorwks!CLREventWaitHelper+0x42
- `0f59bd10 000007fe`f53cee38 mscorwks!CLREvent::WaitEx+0x63
- `0f59bdc0 000007fe`f53c1cb7 mscorwks!SVR::gc_heap::wait_for_gc_done+0x88
- `0f59be00 000007fe`f542913b mscorwks!SVR::GCHeap::GarbageCollectGeneration+0x147
- `0f59be90 000007fe`f5412ac3 mscorwks!SVR::GCHeap::GarbageCollect+0x5b
- `0f59bee0 000007fe`f57301a5 mscorwks!GCInterface::AddMemoryPressure+0x13b
- `0f59bf70 000007fe`f57b9beb mscorwks!RCW::AddMemoryPressure+0x15
- `0f59bfb0 000007fe`f57dbbf4 mscorwks!RCW::CreateRCW+0x17b
- `0f59c030 000007fe`f57dbdea mscorwks!COMInterfaceMarshaler::CreateObjectRef+0x74
- `0f59c130 000007fe`f58843f4 mscorwks!COMInterfaceMarshaler::WrapWithComObject+0x3a
- `0f59c1a0 000007fe`f0268995 mscorwks!MarshalNative::WrapIUnknownWithComObject+0x134
- `0f59c3c0 000007fe`f0270933 System_EnterpriseServices_ni!System.EnterpriseServices.RemoteServicedComponentProxy..ctor(System.Type, IntPtr, Boolean)+0xd5
- `0f59c420 000007fe`f0270213 System_EnterpriseServices_ni!System.EnterpriseServices.FastRSCPObjRef.GetRealObject(System.Runtime.Serialization.StreamingContext)+0x33
- `0f59c470 000007fe`f37254db System_EnterpriseServices_ni!System.EnterpriseServices.ServicedComponentProxyAttribute.CreateProxy(System.Runtime.Remoting.ObjRef, System.Type, System.Object, System.Runtime.Remoting.Contexts.Context)+0x133
- `0f59c500 000007fe`f37253ff mscorlib_ni!System.Runtime.Remoting.RemotingServices.SetOrCreateProxy(System.Runtime.Remoting.Identity, System.Type, System.Object)+0x9b
- `0f59c560 000007fe`f372466f mscorlib_ni!System.Runtime.Remoting.RemotingServices.GetOrCreateProxy(System.Runtime.Remoting.Identity, System.Object, Boolean)+0xbf
- `0f59c5c0 000007fe`f027050a mscorlib_ni!System.Runtime.Remoting.RemotingServices.InternalUnmarshal(System.Runtime.Remoting.ObjRef, System.Object, Boolean)+0x12f
- `0f59c650 000007fe`f40e3edf System_EnterpriseServices_ni!System.EnterpriseServices.ServicedComponentProxyAttribute.CreateInstance(System.Type)+0x2ba
- `0f59c7c0 000007fe`f5416e61 mscorlib_ni!System.Runtime.Remoting.Activation.ActivationServices.IsCurrentContextOK(System.Type, System.Object[], Boolean)+0x9ba81f
对应的.NET 托管 Call Stack:
- Child-SP RetAddr Call Site
- 000000000f59c3c0 000007fef0270933 System.EnterpriseServices.RemoteServicedComponentProxy..ctor(System.Type, IntPtr, Boolean)
- 000000000f59c420 000007fef0270213 System.EnterpriseServices.FastRSCPObjRef.GetRealObject(System.Runtime.Serialization.StreamingContext)
- 000000000f59c470 000007fef37254db System.EnterpriseServices.ServicedComponentProxyAttribute.CreateProxy(System.Runtime.Remoting.ObjRef, System.Type, System.Object, System.Runtime.Remoting.Contexts.Context)
- 000000000f59c500 000007fef37253ff System.Runtime.Remoting.RemotingServices.SetOrCreateProxy(System.Runtime.Remoting.Identity, System.Type, System.Object)
- 000000000f59c560 000007fef372466f System.Runtime.Remoting.RemotingServices.GetOrCreateProxy(System.Runtime.Remoting.Identity, System.Object, Boolean)
- 000000000f59c5c0 000007fef027050a System.Runtime.Remoting.RemotingServices.InternalUnmarshal(System.Runtime.Remoting.ObjRef, System.Object, Boolean)
- 000000000f59c650 000007fef40e3edf
System.EnterpriseServices.ServicedComponentProxyAttribute.CreateInstance
- (System.Type)
通过上面的调用栈信息,可以得知当serviced componnet被创建的时候,.NET RCW 逻辑会在mscorwks!RCW::CreateRCW 里调用GC.AddMemoryPressure 对可能的额外内存需要做提前预估. 当内存在不停扩展时, AddMemoryPressure会增加 Induced GC 的计数(如我们在性能监视器里发现的), 并且调用GarbageCollect。
为了解决这种问题,我们需要在应用程序里减少创建Serviced Component的次数。光在COM+里面修改成Object Pooling是不够的,因为这种Induced GC是在每次应用程序调用RCW的时候都会发生。通过研究代码和测试,如在每次调用创建Serviced Component之前使用 RemoveMemoryPressure(4004) 用来抵消RCW里的相同bytes的AddMemoryPressure(4004)可以临时解决这个问题.
最终解决方法是我们在应用程序本身创建了自己的对象池(建立一组全局对象,简单管理它们的存在周期),以彻底减少CreateInsance和CreateRCW的调用。这样处理以后,即使在大压力情况下, 程序运行也是良好的。
调用.NET Serviced Component引发的性能问题及其解决的更多相关文章
- Mysql中where条件一个单引号引发的性能损耗
日常写SQL中可能会有一些小细节忽略了导致整个sql的性能下降了好几倍甚至几十倍,几百倍.以下这个示例就是mysql语句中的一个单引号('')引发的性能耗损,我相信很多朋友都遇到过,甚至还在这样写. ...
- 记一次Task抛异常,调用线程处理而引发的一些随想
记一次Task抛异常,调用线程处理而引发的一些随想 多线程调用,任务线程抛出异常如何在另一个线程(调用线程)中捕获并进行处理的问题. 1.任务线程在任务线程执行语句上抛出异常. 例如: private ...
- Redis核心知识之—— 时延问题分析及应对、性能问题和解决方法【★★★★★】
参考网址: Redis时延问题分析及应对:http://www.cnblogs.com/me115/p/5032177.html Redis常见的性能问题和解决方法:http://www.search ...
- 探讨:crond 引发大量sendmail进程的解决办法
某服务器账号comm无法登录,说是资源消耗完毕.于是用另一个账号登陆到服务器,检查common账号到底启动了哪些dd引起资源耗尽:ps -u common发现有个 sendmail的启动特别多例如:c ...
- ArcGIS API for Silverlight 调用WebService出现跨域访问报错的解决方法
原文:ArcGIS API for Silverlight 调用WebService出现跨域访问报错的解决方法 群里好几个朋友都提到过这样的问题,说他们在Silverlight中调用了WebServi ...
- java 调用bash shell脚本阻塞的小问题的解决
java 调用bash shell脚本阻塞的小问题的解决 背景 使用java实现的web端,web端相应用户的界面操作,使用java调用bash实现的shell脚本进行实际的操作,操作完成返回执行结 ...
- SpringBoot 内部方法调用,事务不起作用的原因及解决办法
在做业务开发时,遇到了一个事务不起作用的问题.大概流程是这样的,方法内部的定时任务调用了一个带事务的方法,失败后事务没有回滚.查阅资料后,问题得到解决,记录下来分享给大家. 场景 我在这里模拟一个场景 ...
- 浅谈,seata在使用feign-url通过域名调用时分布式事务不生效的问题及解决
浅谈,seata在使用feign-url通过域名调用时分布式事务不生效的问题及解决 在前几个月时,我们项目出现了分布式事务的问题,那么什么是分布式事务问题呢,简单的说,我们有俩服务A和B,它们对应 ...
- try catch引发的性能优化深度思考
关键代码拆解成如下图所示(无关部分已省略): 起初我认为可能是这个 getRowDataItemNumberFormat 函数里面某些方法执行太慢,从 formatData.replace 到 une ...
随机推荐
- cogs——908. 校园网
908. 校园网 ★★ 输入文件:schlnet.in 输出文件:schlnet.out 简单对比 时间限制:1 s 内存限制:128 MB USACO/schlnet(译 by Fe ...
- Pivotal-tc-Server与Tomcat区别
Pivotal-tc-Server之前叫做SpringSource tc Server,包含三个版本分别是:Spring版.标准版和开发版,但其中只有开发版是免费的.比如在STS中包含的版本就是开发板 ...
- Centos: Screen tips
Install yum install screen Useful screen commands List a particular users screen sessions: screen -l ...
- Vim 经常使用快捷键及键盘图
Vim经常使用的快捷键 h - 光标左移一个字符 j - 光标下移一个字符 k - 光标上移一个字符 l - 光标右移一个字符 下移15行 - 15j Ctrl + f - 屏幕向下移动一页 ...
- 2014年最简单、快捷的美股Scottrade开户攻略
[开篇重点提示] 1.scottrade是国内用户用得最多的美股证券交易平台. 2.不用邮寄纸质资料,网上开户全搞定. 3.申请表格填写优惠代码,获取免费3次交易费用,鄙人的推荐优惠代码是 87195 ...
- 数据库操作语句大全(sql)
一.基础 1.说明:创建数据库CREATE DATABASE database-name 2.说明:删除数据库drop database dbname3.说明:备份sql server--- 创建 备 ...
- JPA学习笔记(13)——查询缓存
使用hibernate的查询缓存 运行下面代码: String jpql = "FROM User u WHERE u.id = ?"; Query query = entityM ...
- Vue相关开源项目库汇总 http://www.opendigg.com/tags/front-vue
awesome-github-vue 是由OpenDigg整理并维护的Vue相关开源项目库集合.我们会定期同步OpenDigg上的项目到这里,也欢迎各位提交项目给我们. 如果收录的项目有错误,可以通过 ...
- ZOJ2334 Monkey King 左偏树
ZOJ2334 用左偏树实现优先队列最大的好处就是两个队列合并可以在Logn时间内完成 用来维护优先队列森林非常好用. 左偏树代码的核心也是两棵树的合并! 代码有些细节需要注意. #include&l ...
- Angular.forEach用法总结
}; }]; var so=[]; var so2=[]; var so3=[]; var so4=[]; var so5=[]; var so6=[]; ; ; angular.forEach(so ...