zoukankan      html  css  js  c++  java
  • 通过分析内存来优化.NET程序

    最近在做一个MSMQ的Agent服务,在这里分享一下这个服务在优化的一点经验,通过分析内存更准确地定位出程序中存在的性能问题,从而让程序的性能以倍数的提升.

    问题的引发

    由于通过.NET MSMQ的Client实现消息分布和故障转移实在测试效果并不理想..所以决定实现一个MSMQ的Agent服务,由于有网络编写的经验所以对实现的效果还有很有信心的.可惜最终实现出来的效果实在惨不忍睹...4个连接并发消息写入只有150/秒,实在是完全坑爹的结果!在架构上的设计并不存在问题,所以问题一定存在程序实现过程中,以往的经验告诉自己做内存分析是最直接的办法.

    问题排查一Buffer没正常回收到Pool

    由于在测试过程CPU使用率并不高,所以怀疑是Buffer没有回收到Pool导致

    从分析的结果来说,的确是自己在写代码的时候犯错了...存在大量的buffer被Pop出来导致大量内存被创建.但从代码流程上来看找不到任何原因.

    public override void MessageWrite(IMessage msg, BufferWriter writer)
            {
                HttpData hb = msg as HttpData;  
                try
                {
                    using (hb.Message)
                    {
                        msg.Save(writer);
                    }
                }
                finally
                {
                    
                    if (hb != null)
                    {
                        hb.Message = null;
                        HttpDataPackage.HttpDataPool.Push(hb);
                    }
                }
            }

    分析结果已经说明了问题所在,所以调试了一下程序,发现问题的根源是HttpData的Message为空,但using不会报错坑爹啊...

    public void ToProtocolData(HttpData httpbase)
            {
                httpbase.Action = Action;
                httpbase.Message = this;
                OnToProtocolData(httpbase);
                ;
            }

    适当地修改一处程序问题解决.

    吐能力提高但CPU占用资源过高

    经过上面程序的修复4连接的秒吞吐能力由原来每秒150左右,上升到每秒2100/秒.得到的效果是非常的明显的,但总的来说CPU占用资源还有点过高,为了验证上一次修复的问题又进行了一次内存分析,分析的结果如下:

    分析说明了一个问题由于Assembly.GetName()导致了大量的string创建,代码如下:

    value = string.Format("{0},{1}={2}", type.FullName, type.Assembly.GetName().Name, JsonConvert.SerializeObject(Message));

    适当地修改一下

            value = string.Format("{0}={1}", GetTypeName(type), JsonConvert.SerializeObject(Message));
    
            private static System.Collections.Hashtable mNames = new System.Collections.Hashtable(1024);
    
            private static string GetTypeName(Type type)
            {
                string name = (string)mNames[type];
                if (name == null)
                {
                    lock (mNames)
                    {
                        name = (string)mNames[type];
                        if (name == null)
                        {
                            name = string.Format("{0},{1}", type.FullName, type.Assembly.GetName().Name);
                            mNames[type] = name;
                        }
                    }
                }
                return name;
            }

    经过以上的进一步优化后,服务的效果算是比较理想,完全满足了现阶段的需要.

    意外的发现

    从测试分析的结果看来,Newtonsoft.Json这个组件还有针对性优化的空间

    针对以上分析,Newtonsoft.Json存在的问题应该如何优化,那就要留大家思考了.

    总结

    其实很多朋友喜欢通过CPU计时来看程序的快慢,但得到的结果只能说明问题,但对于如何解决这些问题,测试运行时间的结果似乎起不到什么作用.其实.NET程序有一个东西往往没有得到关注,MS在一些文档中要强调我们没有必要关心,这个东西其实就是GC!的确我们对GC的工作直接可控性是没有,但有一点可以肯定的就是GC的工作由对象的创建导致,如果想控制GC我们最好是从设计层面上控制对象的创建,这是最直接有效的办法.

    访问Beetlex的Github
  • 相关阅读:
    Palindrome Linked List 解答
    Word Break II 解答
    Array vs Linked List
    Reverse Linked List II 解答
    Calculate Number Of Islands And Lakes 解答
    Sqrt(x) 解答
    Find Median from Data Stream 解答
    Majority Element II 解答
    Binary Search Tree DFS Template
    188. Best Time to Buy and Sell Stock IV
  • 原文地址:https://www.cnblogs.com/smark/p/3054448.html
Copyright © 2011-2022 走看看