【问题标题】:I need to call accurate CPU usage of a single process我需要调用单个进程的准确 CPU 使用率
【发布时间】:2012-01-17 17:44:56
【问题描述】:

诀窍是我还需要能够在多核机器上执行此操作。我的 C# 教育有点破。我已经管理了以下代码。谁能帮我吗? Iv 尝试使用“_Total”标志,并且尝试修改其他一些代码 sn-ps,这些代码看起来像是在尝试检测内核数量。但是有人告诉我,它们不包括 HT,只支持物理处理器而不是逻辑处理器。我试图让它两者兼得。显然他们是一种使用

手动执行此操作的方法
    ("Process", "% Processor Time", "1" process.ProcessName))
    ("Process", "% Processor Time", "2" process.ProcessName))
    ("Process", "% Processor Time", "3" process.ProcessName))

等等。但是我发现如果内核不存在,硬件就无法工作。我希望我能遇到更灵活的东西。我已经为此工作了好几天又好几个小时,我要把头发拔掉。

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Collections;
using System.IO;

namespace Program_CPU_Monitor
{
    class Program
    {
        static void Main(string[] args)
        {
            StreamWriter log;
            log = File.AppendText("c:\\CPUMON.txt");
            log.WriteLine("");
            log.WriteLine("**Started logging Program CPU Monitor (2.6.0.63)**");
            log.Close();
            Console.Title = "Program CPU Monitor 2.6.0.63";
            Console.WriteLine("Monitoring Program CPU & Memory usage...(1-min intervals)");
            Console.WriteLine("Monitoring will start when Program is detected as running.");
            Console.WriteLine("Please type in program name without the '.EXE', For example 'TESV' or 'calc'.");
            Console.WriteLine("The program name is case sensative. Without the proper case it will not work.");
            Console.WriteLine("This program will leave a log of the display called 'CPUMON.txt' on drive C:/.");
            Console.WriteLine("Please type program name...");
            Console.WriteLine(""); 
            string procName = Console.ReadLine();

            while (true)
            {

                Process[] runningNow = Process.GetProcesses();

                foreach (Process process in runningNow)
                {
                    using (PerformanceCounter pcProcess = new PerformanceCounter("Process", "% Processor Time", process.ProcessName))
                    using (PerformanceCounter memProcess = new PerformanceCounter("Memory", "Available MBytes"))
                    {
                        if (process.ProcessName == procName)
                        {
                            pcProcess.NextValue();
                            Thread.Sleep(60000);
                            StreamWriter OurStream;
                            OurStream = File.AppendText("c:\\CPUMON.txt");
                            Console.WriteLine("");
                            OurStream.WriteLine("");
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.WriteLine("Process: '{0}' CPU Usage: {1}%", process.ProcessName, pcProcess.NextValue());
                            OurStream.WriteLine("Process: '{0}' CPU Usage: {1}%", process.ProcessName, pcProcess.NextValue());
                            Console.ForegroundColor = ConsoleColor.Green;
                            Console.WriteLine("Process: '{0}' RAM Free: {1}MB", process.ProcessName, memProcess.NextValue());
                            OurStream.WriteLine("Process: '{0}' RAM Free: {1}MB", process.ProcessName, memProcess.NextValue());
                            Console.ForegroundColor = ConsoleColor.Cyan;
                            Console.WriteLine(string.Format("Recorded: '{0}' at {1}", procName, DateTime.Now.ToString()));
                            OurStream.WriteLine(string.Format("Recorded: '{0}' at {1}", procName, DateTime.Now.ToString()));
                            OurStream.Close();

                        }
                    }
                }

            }

        }

    }

}

编辑:: 我对代码进行了以下更改,以根据建议和一般的摆弄来解决我的问题。

    foreach (Process process in runningNow)
            {
                using (PerformanceCounter cpuUsage = new PerformanceCounter("Process", "% Processor Time", "_Total"))
                using (PerformanceCounter pcProcess = new PerformanceCounter("Process", "% Processor Time", process.ProcessName))
                using (PerformanceCounter memProcess = new PerformanceCounter("Memory", "Available MBytes"))
                {
                    if (process.ProcessName == procName)
                    {
                        StreamWriter OurStream;
                        OurStream = File.AppendText("c:\\CPUMON.txt");
                        Console.WriteLine("");
                        OurStream.WriteLine("");

                        // Prime the Performance Counters
                        pcProcess.NextValue();
                        cpuUsage.NextValue();
                        Thread.Sleep(100);
                        isprimed = true;

                        double cpuUse = Math.Round(pcProcess.NextValue() / cpuUsage.NextValue() * 100, 2);

                        // Check for Not-A-Number (Division by Zero)
                        if (Double.IsNaN(cpuUse))
                            cpuUse = 0;

                        //Get CPU Usage
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine("Process: `{0}' CPU Usage: {1}%", process.ProcessName, Convert.ToInt32(cpuUse));
                        OurStream.WriteLine("Process: `{0}' CPU Usage: {1}%", process.ProcessName, Convert.ToInt32(cpuUse));

                        // Get Process Memory Usage
                        Console.ForegroundColor = ConsoleColor.Green;
                        double memUseage = process.PrivateMemorySize64 / 1048576;
                        Console.WriteLine("Process: `{0}' Memory Usage: {1}MB", process.ProcessName, memUseage);
                        OurStream.WriteLine("Process: `{0}' Memory Usage: {1}MB", process.ProcessName, memUseage);

                        // Get Total RAM free
                        Console.ForegroundColor = ConsoleColor.Cyan;
                        float mem = memProcess.NextValue();
                        Console.WriteLine("During: `{0}' RAM Free: {1}MB", process.ProcessName, mem);
                        OurStream.WriteLine("During: `{0}' RAM Free: {1}MB", process.ProcessName, mem);

                        //Record and close stream
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        System.DateTime newDate = System.DateTime.Now;
                        Console.WriteLine("Recorded: {0}", newDate);
                        OurStream.WriteLine("Recorded: {0}", newDate);
                        OurStream.Close();
                        Thread.Sleep(59900);

【问题讨论】:

    标签: c# console multicore cpu-speed


    【解决方案1】:

    您只能每 100 毫秒读取一次性能计数器,否则 timesilce 将太小而无法获得准确的读数,如果您每 100 毫秒读取一次以上,它将始终报告 0 或 100% 的使用率。因为您调用NextValue() 两次(一次用于文件,一次用于您的流),所以第二次读取将是自上次读取之前的行以来的用法。

    将您的代码更改为:

    foreach (Process process in runningNow.Where(x => x.ProcessName == procName)
    {
        using (PerformanceCounter pcProcess = new PerformanceCounter("Process", "% Processor Time", process.ProcessName))
        using (PerformanceCounter memProcess = new PerformanceCounter("Memory", "Available MBytes"))
        {
            pcProcess.NextValue();
            Thread.Sleep(60000);
            StreamWriter OurStream;
            OurStream = File.AppendText("c:\\CPUMON.txt");
            Console.WriteLine("");
            OurStream.WriteLine("");
            Console.ForegroundColor = ConsoleColor.Red;
            float cpuUseage = pcProcess.NextValue();
            Console.WriteLine("Process: '{0}' CPU Usage: {1}%", process.ProcessName, cpuUseage);
            OurStream.WriteLine("Process: '{0}' CPU Usage: {1}%", process.ProcessName, cpuUseage);
            Console.ForegroundColor = ConsoleColor.Green;
            float memUseage = memProcess.NextValue();
            Console.WriteLine("Process: '{0}' RAM Free: {1}MB", process.ProcessName, memUseage);
            OurStream.WriteLine("Process: '{0}' RAM Free: {1}MB", process.ProcessName, memUseage);
        }
    }
    

    可能还有其他问题导致您出现问题,但两次调用 NextValue 是第一个跳出来的。


    说明:

    当您请求 NextValue 太快时,NextValue 仅报告 0 或 100% 的原因是 您当前是否正在执行代码是一个布尔因素

    所以性能计数器正在做的是问这个问题:

    从上次性能计数器读取数据到现在,从进程 X 执行代码的时间片百分比是多少?

    性能计数器使用的这些时间片的大小是 100 毫秒,所以如果你低于 100 毫秒,你基本上是在问

    性能计数器记录的最后一个时间片是否有来自进程 X 的代码正在执行?

    对于该问题,您唯一能得到的两个答案是“否”(0%)或“是”(100%)。

    【讨论】:

    • 非常感谢!我说这篇文章很有帮助我不确定代表系统在这里是如何工作的,所以我不确定他们是否无论如何我可以给你信用。我想知道您所说的将我的内容从循环中移出是什么意思?老实说,对不起,我可能会用问题轰炸你。就像我说的那样,当涉及到一些过时的书籍和章节以及他们的语言时,我的教育被打破了。
    • 嗯,上次打扰您了。我在 4 核机器上试过这个,使用率更高的进程仍然报告使用率超过 100% 是他们解决这个问题的方法吗?
    • 对不起,我最近没有使用性能计数器,我最近了解了我自己关于 100ms 的事实并对其进行了更多研究。我建议创建一个可以重现问题的小示例程序,然后在此站点上使用示例程序的代码提出一个新问题,以便人们可以看到您的问题。
    • 我编辑了原始帖子以包含我更正的更改。程序现在运行良好。感谢所有的帮助。
    • 看起来不错,很高兴我能帮上忙。我唯一可以推荐的另一件事可能是比Sleep(100)(可能是110?)高一点,以确保您超过100毫秒的要求。此外,如果您查看如何执行Parallel.ForEach 并将写入文件放在 localFinally 中(您需要为文件写入添加一点锁定,因为多个线程将尝试一次写入文件)您无需等待每个进程依次枚举完,可以同时获取所有进程的快照。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    • 2017-06-11
    • 1970-01-01
    相关资源
    最近更新 更多