web-dev-qa-db-fra.com

Obtenez le CPU et RAM usage

J'ai besoin d'obtenir la mémoire RAM et l'utilisation du processeur pendant l'exécution d'un processus (le processus peut s'exécuter parfois et plus de 30 minutes). Je suis en mesure d'obtenir gratuitement RAM mais l'utilisation du processeur n'est pas correcte, par rapport à la valeur du gestionnaire de tâches. Suis-je en train de faire quelque chose de mal? Voici mon code:

class Program
{
    static List<float> AvailableCPU = new List<float>();
    static List<float> AvailableRAM = new List<float>();

    protected static PerformanceCounter cpuCounter;
    protected static PerformanceCounter ramCounter;
    static void Main(string[] args)
    {
        cpuCounter = new PerformanceCounter();
        cpuCounter.CategoryName = "Processor";
        cpuCounter.CounterName = "% Processor Time";
        cpuCounter.InstanceName = "_Total";

        ramCounter = new PerformanceCounter("Memory", "Available MBytes");

        try
        {
            System.Timers.Timer t = new System.Timers.Timer(1200);
            t.Elapsed += new ElapsedEventHandler(TimerElapsed);
            t.Start();
            Thread.Sleep(10000);
        }
        catch (Exception e)
        {
            Console.WriteLine("catched exception");
        }
        Console.ReadLine();

    }

    public static void TimerElapsed(object source, ElapsedEventArgs e)
    {
        float cpu = cpuCounter.NextValue();
        float ram = ramCounter.NextValue();
        Console.WriteLine(string.Format("CPU Value: {0}, ram value: {1}", cpu, ram));
        AvailableCPU.Add(cpu);
        AvailableRAM.Add(ram);
    }

}

Mais lorsque j'exécute le programme, voici ce qu'il est imprimé sur la console, par rapport aux valeurs du gestionnaire de tâches: cpu usage

Qu'est-ce que je fais mal?

12
Buda Gavril

Il n'y a rien de mal avec vos valeurs.

La raison pour laquelle vous voyez des différences avec ce que le gestionnaire de tâches renvoie est que la valeur "Utilisation du processeur" est quelque chose de calculé pour un intervalle donné, c'est-à-dire entre deux appels NextValue(). Si le gestionnaire de tâches "n'appelle pas sa propre NextValue" (si nous simplifions son fonctionnement) en même temps que vous, vous ne retournerez pas les mêmes résultats.

Imaginez le scénario suivant:

Time 0: 0% actual CPU usage
Time 1: 50% actual CPU usage
Time 2: 70% actual CPU usage
Time 3: 2% actual CPU usage
Time 4: 100% actual CPU usage
  • Si vous vérifiez la valeur entre le temps 1 et le temps 3, vous retournerez quelque chose basé sur "50% et 2%".
  • Si le gestionnaire de tâches vérifie la valeur entre le temps 2 et le temps 4, il renverra quelque chose de différent, c'est-à-dire une valeur basée sur "70% et 100%".

Vous pouvez essayer de générer plusieurs processus de votre propre application, vous devriez également voir des résultats différents.

9
ken2k

Voici ce que j'ai trouvé: j'ai créé une liste avec PerformanceCounter objets pour chaque cœur, j'ajoute le pourcentage et divise le résultat en nombre de cœurs physiques:

    class Program
    {
        static List<float> AvailableCPU = new List<float>();
        static List<float> AvailableRAM = new List<float>();

        protected static PerformanceCounter cpuCounter;
        protected static PerformanceCounter ramCounter;
        static List<PerformanceCounter> cpuCounters = new List<PerformanceCounter>();
        static int cores = 0;
        static void Main(string[] args)
        {
            cpuCounter = new PerformanceCounter();
            cpuCounter.CategoryName = "Processor";
            cpuCounter.CounterName = "% Processor Time";
            cpuCounter.InstanceName = "_Total";

            foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get())
            {
                cores = cores + int.Parse(item["NumberOfCores"].ToString());
            }

            ramCounter = new PerformanceCounter("Memory", "Available MBytes");

            int procCount = System.Environment.ProcessorCount;
            for(int i = 0; i < procCount; i++)
            {
                System.Diagnostics.PerformanceCounter pc = new System.Diagnostics.PerformanceCounter("Processor", "% Processor Time", i.ToString());
                cpuCounters.Add(pc);
            }

            Thread c = new Thread(ConsumeCPU);
            c.IsBackground = true;
            c.Start();

            try
            {
                System.Timers.Timer t = new System.Timers.Timer(1200);
                t.Elapsed += new ElapsedEventHandler(TimerElapsed);
                t.Start();
                Thread.Sleep(10000);
            }
            catch (Exception e)
            {
                Console.WriteLine("catched exception");
            }
            Console.ReadLine();

        }

        public static void ConsumeCPU()
        {
            int percentage = 60;
            if (percentage < 0 || percentage > 100)
                throw new ArgumentException("percentage");
            Stopwatch watch = new Stopwatch();
            watch.Start();
            while (true)
            {
                // Make the loop go on for "percentage" milliseconds then sleep the 
                // remaining percentage milliseconds. So 40% utilization means work 40ms and sleep 60ms
                if (watch.ElapsedMilliseconds > percentage)
                {
                    Thread.Sleep(100 - percentage);
                    watch.Reset();
                    watch.Start();
                }
            }
        }

        public static void TimerElapsed(object source, ElapsedEventArgs e)
        {
            float cpu = cpuCounter.NextValue();
            float sum = 0;
            foreach(PerformanceCounter c in cpuCounters)
            {
                sum = sum + c.NextValue();
            }
            sum = sum / (cores);
            float ram = ramCounter.NextValue();
            Console.WriteLine(string.Format("CPU Value 1: {0}, cpu value 2: {1} ,ram value: {2}", sum, cpu, ram));
            AvailableCPU.Add(sum);
            AvailableRAM.Add(ram);
        }

    }

Voici la capture d'écran avec les résultats (comme vous pouvez le voir, la première méthode est plus précise):

enter image description here

8
Buda Gavril