Мне нужно назвать точное использование процессора одним процессом - PullRequest
7 голосов
/ 11 декабря 2011

Хитрость в том, что мне также нужно уметь это делать на многоядерных машинах. Мое образование в C # немного сломано. Я справился со следующим кодом. Может кто-нибудь мне помочь? Iv пытался использовать флаг "_Total", и я пытался изменить некоторые другие фрагменты кода, которые выглядели так, как будто они пытались определить количество ядер. Однако мне сказали, что они не включают 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);

1 Ответ

17 голосов
/ 11 декабря 2011

Вы можете читать счетчики производительности только каждые 100 мс, иначе временное время будет слишком маленьким для точного считывания, если вы читаете более одного раза каждые 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 сообщает только 0 или 100%, когда вы запрашиваете NextValue слишком быстро, заключается в том, что , если вы выполняете код в данный момент или нет, является логическим фактором .

Итак, что делает счетчик производительности, задает вопрос:

Между тем, как в последний раз счетчик производительности брал показания, и каков сейчас, в каком% временных интервалов был код, выполняемый из процесса X?

Размер этих временных интервалов, с которыми работает счетчик производительности, составляет 100 мс, поэтому, если вы опускаетесь ниже 100 мс, вы в основном спрашиваете

Имел ли последний отрезок времени, который был записан счетчиком производительности, код из выполняемого процесса X?

и на этот вопрос вы можете получить только два ответа: «Нет» (0%) или «Да» (100%).

...