CPU LIMITER - LIMITEZ L'UTILISATION DU PROCESSEUR DE CHAQUE PROCESSUS

cs_MPi Messages postés 3877 Date d'inscription mardi 19 mars 2002 Statut Membre Dernière intervention 17 août 2018 - 3 août 2008 à 10:35
Fraer9 Messages postés 1 Date d'inscription mardi 20 janvier 2009 Statut Membre Dernière intervention 3 février 2009 - 3 févr. 2009 à 15:22
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/47480-cpu-limiter-limitez-l-utilisation-du-processeur-de-chaque-processus

Fraer9 Messages postés 1 Date d'inscription mardi 20 janvier 2009 Statut Membre Dernière intervention 3 février 2009
3 févr. 2009 à 15:22
Merci pour ce code !

Voici la meme chose en c#, c'est une variante plus simple (qu'un seul timer) a utiliser avec l'api JobObjectWrapper (voir http://www.codeplex.com/JobObjectWrapper) pour la limitation d'un ensemble de processus (1 limite pour n processus).

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Timers;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Process[] par = Process.GetProcessesByName("ProcessLauncher");
CPULimiter cpuLimiter = new CPULimiter(10);

cpuLimiter.addProcessToWatchList(par[0]);

// Wait a little
System.Threading.Thread.Sleep(5000);

cpuLimiter.addProcessToWatchList(par[1]);

Console.ReadLine();
}
}

class ProcessWatcher
{
private readonly Process _watchedProcess;
private readonly PerformanceCounter _performanceCounter;
private bool _isSuspended;

public ProcessWatcher(Process processToWatch)
{
this._watchedProcess = processToWatch;
this._performanceCounter = new PerformanceCounter(
"Process",
"% Processor Time",
processToWatch.ProcessName);
// Init the perf counter
this._performanceCounter.NextValue();
this._isSuspended = false;
}

public Process watchedProcess
{
get { return this._watchedProcess; }
}

public PerformanceCounter performanceCounter
{
get { return this._performanceCounter; }
}

public bool isSuspended
{
get { return this._isSuspended; }
set { this._isSuspended = value; }
}
}

class CPULimiter
{
[DllImport("ntdll.dll", EntryPoint = "NtResumeProcess", SetLastError = true)]
private static extern uint NtResumeProcess(IntPtr processHandle);

[DllImport("ntdll.dll", EntryPoint = "NtSuspendProcess", SetLastError = true)]
private static extern uint NtSuspendProcess(IntPtr processHandle);

// see if 1sec based rate in ms is not too often
public const int REFRESH_RATE_BASE_MS = 100;

private readonly List watchList;

private readonly float maxCpuUsagePercetage;
private readonly Timer watchingTimer;

public CPULimiter(int maxCpuUsagePercentageBase100)
{
// Initialize the list
this.watchList = new List();
// Convert to processor count based percentage
this.maxCpuUsagePercetage = maxCpuUsagePercentageBase100 * Environment.ProcessorCount;
// Create the watching timer
this.watchingTimer = new Timer();
// Hook up the Elapsed event for the timer.
this.watchingTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the timer refresh rate
this.watchingTimer.Interval = REFRESH_RATE_BASE_MS;
}

public void addProcessToWatchList(Process processToWatch)
{
// Stop the timer...
this.watchingTimer.Enabled = false;
// Add this watcher to the watch list
this.watchList.Add(new ProcessWatcher(processToWatch));
// Restart the timer
this.watchingTimer.Enabled = true;
}

// Executed by a timer every REFRESH_RATE_BASE_MS
public void OnTimedEvent(object source, ElapsedEventArgs e)
{
// Manually stop the timer...
this.watchingTimer.Enabled = false;
// Save the last exceeding cpu usage
float lastExceedingCpuUsage = 0;
bool cpuUsageLimitExceeded = false;
for (int i = this.watchList.Count - 1; i >= 0; i--)
{
ProcessWatcher processWatcher = this.watchList[i];
// Check if the process has exited
if (processWatcher.watchedProcess.HasExited)
{
// Remove this process watcher from the watch list
this.watchList.RemoveAt(i);
}
else
{
// If the process is suspended resume it
if (processWatcher.isSuspended)
{
// Re init the perf counter since the process was suspended
processWatcher.performanceCounter.NextValue();
if (NtResumeProcess(processWatcher.watchedProcess.Handle) == 0)
{
processWatcher.isSuspended = false;
}
else
{
// Something bad happended so remove this watcher
this.watchList.RemoveAt(i);
}
}
else
{
lastExceedingCpuUsage = processWatcher.performanceCounter.NextValue();
if (lastExceedingCpuUsage > this.maxCpuUsagePercetage)
{
//Console.WriteLine("Process reached the limit Process:{0} CPU% {1}", processWatcher.performanceCounter.InstanceName, lastExceedingCpuUsage);
cpuUsageLimitExceeded = true;
break;
}
}
}
}

int nextInterval = REFRESH_RATE_BASE_MS;

// If cpu usage has been reached
if (cpuUsageLimitExceeded)
{
for (int i = this.watchList.Count - 1; i >= 0; i--)
{
ProcessWatcher processWatcher = this.watchList[i];
// Check if the process has exited
if (processWatcher.watchedProcess.HasExited)
{
// Remove this process watcher from the watch list
this.watchList.RemoveAt(i);
}
else
{
// Since some process watchers can already be suspended we need to check the state
if (!processWatcher.isSuspended)
{
// Suspend the process
if (NtSuspendProcess(processWatcher.watchedProcess.Handle) == 0)
{
processWatcher.isSuspended = true;
}
else
{
// Something bad happended so remove this watcher
this.watchList.RemoveAt(i);
}
}
}
}
// Compute the time to wait in order to reach the given percentage
// formula : TimeToWait = BASE * ((previous_percentage / wanted_percentage) - 1)
nextInterval = Convert.ToInt32(REFRESH_RATE_BASE_MS * ((lastExceedingCpuUsage / this.maxCpuUsagePercetage) - 1));
if (nextInterval < 20) {
nextInterval = 20;
}
}

// Change the next start
this.watchingTimer.Interval = nextInterval;
this.watchingTimer.Enabled = true;
}
}
}
MadM@tt Messages postés 2167 Date d'inscription mardi 11 novembre 2003 Statut Membre Dernière intervention 16 juillet 2009 1
16 sept. 2008 à 13:01
Pour ceux que ça intéresse, une version plus complète est disponible ici :
http://www.vbfrance.com/codes/WIN-OPTIONS-AVANCEES-SUR-FENETRES-PROCESSUS-WINDOWS-CPU_47970.aspx
MadM@tt Messages postés 2167 Date d'inscription mardi 11 novembre 2003 Statut Membre Dernière intervention 16 juillet 2009 1
13 sept. 2008 à 20:59
Merci pour les compliments !

Concernant la version compilée avec un installeur, c'est déjà fait :
http://www.mnapoli.fr/programmes/cpulimiter.php
zavier666 Messages postés 266 Date d'inscription mardi 7 septembre 2004 Statut Membre Dernière intervention 30 avril 2009 1
12 sept. 2008 à 21:33
Si il y avait une élection du code de l'année, je crois que l'on tiendrait le gagnant et de loin. Il faut absolument que tu compiles et que tu distribues. J'ai longtemps cherché et même pensé que cela n'étais pas possible!
cs_adamama Messages postés 2 Date d'inscription mercredi 5 mars 2008 Statut Membre Dernière intervention 9 août 2008
9 août 2008 à 01:11
good job
;)
killer123456789 Messages postés 11 Date d'inscription lundi 4 avril 2005 Statut Membre Dernière intervention 3 août 2008
3 août 2008 à 16:28
Félicitation! Très bon programme. Justement je cherchais un programme de ce genre pour laisser rouler un programme sur mon ordi sans que celui-ci utilise 100% du CPU mais j'avais pas trouver de programme semblable au tien.
MadM@tt Messages postés 2167 Date d'inscription mardi 11 novembre 2003 Statut Membre Dernière intervention 16 juillet 2009 1
3 août 2008 à 12:40
Ah content que ça puisse intéresser quelqu'un.

Alors oui, ça pourrait faire ce que tu veux : à savoir limiter ton appli gourmande à 50% maximum d'utilisation CPU. Par contre ça influe forcément sur le rendement de cette application : à 50%, elle sera 2 fois moins productive.

Mais ton problème ne pourrait-il pas être (en partie) réglé en définissant ton processus à une priorité faible, comme ça ça ne gênerait pas l'exécution d'autres taches ? Après, si tu veux vraiment que son exécution soit transparente tu peux utiliser en complément mon programme, pour être sur qu'il y'aura toujours du temps processeur de libre pour n'importe quelle autre appli... A voir.
cs_MPi Messages postés 3877 Date d'inscription mardi 19 mars 2002 Statut Membre Dernière intervention 17 août 2018 23
3 août 2008 à 10:35
Salut MadM@tt,

Tu viens de toucher une de mes cordes sensibles... :)

Au bureau, j'utilise justement une application qui prend 100% du CPU, ce qui occasionne des problèmes lorsqu'on veut utiliser d'autres applis comme Excel ou Outlook... Je dois donc utiliser 2 ordis pour être efficace.

Est-ce à dire que ton programme pourrait limiter mon application gourmande à utiliser seulement 50% du CPU, disons, et laisser un peu de place pour les autres applis ? Et est-ce que ça ne nuira pas au rendement de cette application ?

Intéressant, en tout cas, comme projet.