zoukankan      html  css  js  c++  java
  • PerformanceCounter蛋痛的设计

    在.NET下对进程的性能计数可以使用PerformanceCounter,通过该对象可以对进程的CPU,内存等信息进行统计.对于正常使用来说这个对象还是很方便,但对于同一名称的多个进程进行性能计数那真是可以无比蛋痛...详细说一下PerformanceCounter对多个同一名称的进程计数所面对的问题.

    应用情况

    PerformanceCounter是通过进程实例名来监控计数,但这个实例名是操作系统实时动态分配的,如果同一名称的进程只有一个那就比较好处理.如果同一名称的进程有多个那悲剧的事情就来的,随着同一名称的进程创建和关闭会影响到其他同一名称进程的实例名.这样会导致相应的PerformanceCounter和进程的对应关系完全错乱...(真是无法理解.NET对这个的实现为什么不用PID)

    假设现在有个ams-p.exe应用程序,依次分别打开三次,那对应的进程实例名是:

    1)ams-p.exe [pid:7012]

    2)ams-p.exe#1 [pid:7013]

    3)ams-p.exe#2 [pid:7014]

    由于实例名windows系统实时分配的,一旦同一名称的进程数量发现变化那对应进程的实例名也会变.针对上面情况当2被关闭后那实例对应的关系可以是.

    1)ams-p.exe [pid:7012]

    3)ams-p.exe#1 [pid:7014]

    这样就会导致3对应的实例名不存在,从而导致PerformanceCounter上的统计错误,如果对应同一名称的进程数量更多,中间其中一个进程关闭那就会有大量的PerformanceCounter统计和进程对应关系就都会存在错误的.

    解决办法

    虽然有解决方法,但做法都是非常蛋痛的,监控Process的Exite事件然后根据退出情况来调整实例名和PID的对应关系,不过这种方式是存在一些问题,如果其他应用也是这个进程名又是通过其他渠道打开你未及时捕抓绑定Exite事件,那就会导致计数错误的悲剧事件发生.而另一种解决方法就比较全面点,在执行所有PerformanceCounter前行把当前系统该名称的进程信息获取上载并建立一个实时的实例名和PID对应关系,然后在执行PerformanceCounter后记录对应实例名的PID计数情况.具体代码如下:

        class CPUCounter:IDisposable
        {
            public CPUCounter(string processName)
            {
                mProcessName = processName;
                mTimer = new System.Threading.Timer(GetUsage, null, 1000, 1000);
            }
    
            private System.Threading.Timer mTimer;
    
            private string mProcessName;
    
            private Dictionary<int, float> mProcessCpuUsage = new Dictionary<int, float>();
    
            private List<CounterItem> mCounters = new List<CounterItem>();
    
            private Dictionary<string, int> mProcessIDs = new Dictionary<string, int>();
    
            public float ProcessUsage(int pid)
            {
                float result = 0;
                mProcessCpuUsage.TryGetValue(pid, out result);
                return result;
            }
    
            private void OnCreateCounter(string processname)
            {
                CounterItem item = mCounters.Find(e => e.ProcessName == processname);
                if (item == null)
                {
                    item = new CounterItem();
                    item.Counter = new PerformanceCounter();
                    item.Counter.CategoryName = "Processor";
                    item.Counter.CounterName = "% Processor Time";
                    item.Counter.InstanceName = processname;
                }
                item.Enabled = true;
            }
    
            private void GetUsage(object state)
            {
                mProcessIDs.Clear();
                Process[] ps = Process.GetProcessesByName(mProcessName);
                List<CounterItem> disposeditems = new List<CounterItem>();
                if (ps.Length == 1)
                {
                    mProcessIDs.Add(mProcessName, ps[0].Id);
                    OnCreateCounter(mProcessName);
                }
                else
                {
                    for (int i = 1; i < ps.Length; i++)
                    {
                        mProcessIDs.Add(mProcessName + "#" + i, ps[i].Id);
                        OnCreateCounter(mProcessName + "#" + i);
                    }
                }
                foreach (CounterItem item in mCounters)
                {
                    if (item.Enabled)
                    {
                        mProcessCpuUsage[mProcessIDs[item.ProcessName]] = item.Counter.NextValue();
                        item.Enabled = false;
                    }
                    else
                    {
                        disposeditems.Add(item);
                    }
                }
                if(disposeditems.Count>0)
                    foreach (CounterItem item in disposeditems)
                    {
                        mCounters.Remove(item);
                    }
            }
    
            class CounterItem
            {
                public string ProcessName { get; set; }
    
                public System.Diagnostics.PerformanceCounter Counter
                {
                    get;
                    set;
                }
               
                public bool Enabled
                {
                    get;
                    set;
                }
            }
    
            public void Dispose()
            {
                if (mTimer != null)
                    mTimer.Dispose();
            }
        }

     如果有更好办法的同学不防分享一下.

  • 相关阅读:
    “北斗人”梦想成真!星间链路新技术探索,ThingJS 3D 可视化 效果图
    如何从道路BIM模型中提取数据?分三步超简单!ThingJS 3D 可视化
    ThingJS: 做一个数据可视化项目的难点在什么地方?3D 可视化 three.js
    震撼来袭 | ThingJS 3D城市应用双11钜惠,低至688元>>官方优惠
    ThingJS 和three.js开发有何不同,让开发早点下班回家!3D 可视化
    NASA样本实验室之3D渲染图,和宇航员一样的上帝视角!3D 可视化 ThingJS
    三维建模国内外技术对比:和SketchUp、Revit建模软件相媲美 3D 地图 可视化 ThingJS
    CSS两列及三列自适应布局方法整理
    前端进阶-每日一练(3)
    前端进阶-每日一练(2)
  • 原文地址:https://www.cnblogs.com/smark/p/3557421.html
Copyright © 2011-2022 走看看