C# 如何以编程方式将程序的 CPU 使用率限制在 70% 以下?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/989281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I programmatically limit my program's CPU usage to below 70%?
提问by Nidhi
Of late, I'm becoming more health oriented when constructing my program, I have observed that most of programs take 2 or 3 minutes to execute and when I check on the task scheduler, I see that they consume 100% of CPU usage, can I limit this usage programatically in code? This will certainly enable me to run multiple programs at a given time.
最近,我在构建我的程序时变得更加注重健康,我观察到大多数程序需要 2 或 3 分钟来执行,当我检查任务调度程序时,我发现它们消耗了 100% 的 CPU 使用率,可以我在代码中以编程方式限制了这种用法?这肯定会让我在给定的时间运行多个程序。
Thanks, Nidhi
谢谢,尼迪
采纳答案by Shog9
That's not your concern... It's the job of the operating system to distribute processor time between running processes. If you'd like to give other processes first crack at getting their stuff done, then simply reduce the priority of your own process by modifying the Process.PriorityClass
value for it.
这不是你关心的……操作系统的工作是在运行的进程之间分配处理器时间。如果您想让其他进程首先完成他们的工作,那么只需通过修改Process.PriorityClass
它的值来降低您自己进程的优先级。
See also: Windows Equivalent of ‘nice'
另请参阅:Windows 等效于“nice”
回答by Carra
You can run your program in a thread with a lower threadpriority, the rest is up to your operating system. Having a process eat up 100% of your CPU is not bad. My SETI is usually taking up all my remaining CPU time without bothering my other programs. It only gets a problem when your thread gets priority over more important programs.
您可以在具有较低threadpriority的线程中运行您的程序,其余的取决于您的操作系统。让一个进程占用 100% 的 CPU 也不错。我的 SETI 通常会占用我所有剩余的 CPU 时间,而不会打扰我的其他程序。只有当您的线程优先于更重要的程序时才会出现问题。
回答by itsmatt
I honestly think rather than worry about trying to limit CPU utilization by your app, you should focus more of your energies on profiling the application to uncover and correct bottlenecks and inefficiencies that may exist.
老实说,我认为与其担心尝试限制您的应用程序的 CPU 使用率,您应该将更多的精力集中在分析应用程序上,以发现和纠正可能存在的瓶颈和低效率。
回答by Mike Dunlavey
If you code is running at all, it is at 100%
如果您的代码正在运行,则为 100%
I suppose slipping in some sleeps might have an effect.
我想在一些睡眠中滑倒可能会产生影响。
I have to wonder about that 2-3 minute figure. I've seen it too, and I suppose it's loading and initializing lots of stuff I probably don't really need.
我不得不怀疑那个 2-3 分钟的数字。我也见过它,我想它正在加载和初始化很多我可能并不真正需要的东西。
回答by Treb
If there is no other task running, is it wrong for your app to use all the cpu capacity that is available? It is available, as in it's there and it is free to use. So use it!
如果没有其他任务在运行,您的应用程序使用所有可用的 CPU 容量是错误的吗?它是可用的,因为它就在那里并且可以免费使用。所以使用它!
If you somehow limit the cpu usage of your task, it will take longer to complete. But it will still take the same number of cpu cycles, so you gain nothing. You just slow down your application.
如果您以某种方式限制了任务的 CPU 使用率,则需要更长的时间才能完成。但是它仍然需要相同数量的 cpu 周期,所以你一无所获。你只是减慢了你的应用程序。
Don't do it. Don't even try it. There's no reason why you should.
不要这样做。甚至不要尝试。没有理由你应该这样做。
回答by mfawzymkh
I think what you need to do is to understand the performance problem in your application instead of trying to put a cap on the CPU usage. You Can use Visual Studio Profiler to see why you application is taking 100% CPU for 2-3 minutes in the first place. This should reveal the hot spot in your app, and then you can be able to address this issue.
我认为您需要做的是了解应用程序中的性能问题,而不是试图限制 CPU 使用率。您可以使用 Visual Studio Profiler 来查看为什么您的应用程序在 2-3 分钟内占用 100% CPU。这应该会显示您的应用程序中的热点,然后您就可以解决此问题。
If you are asking in general regarding how to do resource throttling in windows, then you can look at the "Task" objects, Job objects allows you to set limits such as Working set, process priority...etc.
如果您一般询问如何在 Windows 中进行资源限制,那么您可以查看“任务”对象,作业对象允许您设置限制,例如工作集、进程优先级等。
You can check out the Job objects documentation here http://msdn.microsoft.com/en-ca/library/ms684161(VS.85).aspxHope this helps. Thanks
您可以在此处查看作业对象文档 http://msdn.microsoft.com/en-ca/library/ms684161(VS.85).aspx希望这会有所帮助。谢谢
回答by mal
You could write a Governor
class that throttles the CPU usage. This class would contain a utility method that should be called on a regular basis (e.g. calling this utility function within a while loop of your function) by your CPU bound function. The governor would check if the amount of time elapsed exceeded a particular threshold, and then sleep for a period of time so as to not consume all the CPU.
您可以编写一个Governor
限制 CPU 使用率的类。此类将包含一个实用程序方法,该方法应由 CPU 绑定函数定期调用(例如,在函数的 while 循环中调用此实用程序函数)。调控器会检查经过的时间量是否超过特定阈值,然后休眠一段时间以免消耗所有 CPU。
Here's a simple Java implementation off the top of my head (just so you get the idea) that will throttle the CPU usage to 50% if you have a single threaded CPU bound function.
这是一个简单的 Java 实现(只是为了让您了解这个想法),如果您有一个单线程 CPU 绑定函数,它将把 CPU 使用率限制到 50%。
public class Governor
{
long start_time;
public Governor()
{
this.start_time = System.currentTimeMillis();
}
public void throttle()
{
long time_elapsed = System.currentTimeMillis() - this.start_time;
if (time_elapsed > 100) //throttle whenever at least a 100 millis of work has been done
{
try { Thread.sleep(time_elapsed); } catch (InterruptedExceptione ie) {} //sleep the same amount of time
this.start_time = System.currentTimeMillis(); //reset after sleeping.
}
}
}
Your CPU bound function would instantiate a Governor
, and then just call throttle
on a regular basis within the function.
您的 CPU 绑定函数将实例化 a Governor
,然后throttle
在函数内定期调用。
回答by Scott Hunt
If you have a multi core processor, you can set the Affinity on each process to only use which cores you want it to use. This is the closest method I know of. But it will only allow you to assign percentages that are a factor of 50% on a dual core, and 25% on a quad core.
如果您有一个多核处理器,您可以将每个进程的 Affinity 设置为仅使用您希望它使用的内核。这是我所知道的最接近的方法。但它只允许您分配双核上 50% 和四核上 25% 的百分比。
回答by Ryan
This thread is over four years old, and it still annoys me that the accepted answer criticizes the question rather than answering it. There are many valid reasons you would want to limit the CPU time taken by your program, I can list a few off the top of my head.
这个帖子已经四年多了,接受的答案批评问题而不是回答问题,这仍然让我很恼火。您希望限制程序占用的 CPU 时间的正当理由有很多,我可以列出一些我的想法。
It might seem like a waste not to use all free CPU cycles available, but this mentality is flawed. Unlike older CPUs, most modern CPUs do not run at a fixed clock speed - many have power saving modes where they drop the clock speed and cpu voltage when load is low. CPUs also consume more power when performing calculations than they do running NOOPs. This is especially relevant to laptops that require fans to cool the CPU when it is under high load. Running a task at 100% for a short time can use far more energy than running a task at 25% for four times as long.
不使用所有可用的空闲 CPU 周期似乎是一种浪费,但这种心态是有缺陷的。与较旧的 CPU 不同,大多数现代 CPU 不以固定时钟速度运行——许多具有省电模式,当负载低时,它们会降低时钟速度和 CPU 电压。与运行 NOOP 相比,CPU 在执行计算时消耗的电量也更多。这对于需要风扇在高负载下冷却 CPU 的笔记本电脑尤其重要。在短时间内以 100% 的速度运行任务比以 25% 的速度运行四倍的时间消耗的能量要多得多。
Imagine you are writing a background task that is designed to index files periodically in the background. Should the indexing task use as much of the CPU as it can at a lower priority, or throttle itself to 25% and take as long as it needs? Well, if it were to consume 100% of the CPU on a laptop, the CPU would heat up, the fans would kick in, and the battery would drain fairly quickly, and the user would get annoyed. If the indexing service throttled itself, the laptop may be able to run with completely passive cooling at a very low cpu clock speed and voltage.
假设您正在编写一个后台任务,该任务旨在在后台定期索引文件。索引任务应该以较低的优先级使用尽可能多的 CPU,还是将自身限制为 25% 并根据需要使用尽可能多的时间?好吧,如果它在笔记本电脑上消耗 100% 的 CPU,CPU 会发热,风扇会启动,电池会很快耗尽,用户会很生气。如果索引服务自我限制,笔记本电脑可能能够以非常低的 CPU 时钟速度和电压以完全被动冷却的方式运行。
Incidentally, the Windows Indexing Service now throttles itself in newer versions of Windows, which it never did in older versions. For an example of a service that still doesn't throttle itself and frequently annoys people, see Windows Installer Module.
顺便说一句,Windows 索引服务现在在较新版本的 Windows 中自我限制,而在旧版本中从未这样做过。有关仍不限制自身并经常惹恼人们的服务的示例,请参阅 Windows 安装程序模块。
An example of how to throttle part of your application internally in C#:
如何在 C# 中内部限制部分应用程序的示例:
public void ThrottledLoop(Action action, int cpuPercentageLimit) {
Stopwatch stopwatch = new Stopwatch();
while(true) {
stopwatch.Reset();
stopwatch.Start();
long actionStart = stopwatch.ElapsedTicks;
action.Invoke();
long actionEnd = stopwatch.ElapsedTicks;
long actionDuration = actionEnd - actionStart;
long relativeWaitTime = (int)(
(1/(double)cpuPercentageLimit) * actionDuration);
Thread.Sleep((int)((relativeWaitTime / (double)Stopwatch.Frequency) * 1000));
}
}
回答by Marc
First of all, I agree with Ryan that the question is perfectly valid and there are cases where thread priorities are not at all sufficient. The other answers appear highly theoretical and of no practical use in situations where the application is properly designed but still needs to be throttled. Ryan offers a simple solution for cases in which a relatively short task is performed in high frequency. There are cases, however, when the task takes a verylong time (say a minute or so) and you cannot or don't want to break it into smaller chunks between which you can do the throttling. For these cases the following solution might be helpful:
首先,我同意 Ryan 的观点,这个问题是完全有效的,并且在某些情况下线程优先级根本不够用。其他答案似乎过于理论化,在应用程序设计合理但仍需要限制的情况下没有实际用途。Ryan 为高频率执行相对较短的任务的情况提供了一个简单的解决方案。然而,在某些情况下,当任务需要很长时间(比如一分钟左右)并且您不能或不想将其分解为更小的块时,您可以在这些块之间进行节流。对于这些情况,以下解决方案可能会有所帮助:
Rather that implementing throttling into the business code, you can design the algorithm itself to work at full steam and simply throttle the thread which runs the operation "from the outside". The general approach is the same as in Ryan's answer: Calculate a suspension time based on the current usage and suspend the thread for this timespan before resuming it again. Given a process which you want to throttle, this is the logic:
与其在业务代码中实施节流,您还可以将算法本身设计为全速工作,并简单地节流“从外部”运行操作的线程。一般方法与 Ryan 的回答相同:根据当前使用情况计算暂停时间并在此时间跨度内暂停线程,然后再次恢复它。给定要限制的进程,这是逻辑:
public static class ProcessManager
{
[Flags]
public enum ThreadAccess : int
{
TERMINATE = (0x0001),
SUSPEND_RESUME = (0x0002),
GET_CONTEXT = (0x0008),
SET_CONTEXT = (0x0010),
SET_INFORMATION = (0x0020),
QUERY_INFORMATION = (0x0040),
SET_THREAD_TOKEN = (0x0080),
IMPERSONATE = (0x0100),
DIRECT_IMPERSONATION = (0x0200)
}
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
static extern uint SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int ResumeThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int CloseHandle(IntPtr hThread);
public static void ThrottleProcess(int processId, double limit)
{
var process = Process.GetProcessById(processId);
var processName = process.ProcessName;
var p = new PerformanceCounter("Process", "% Processor Time", processName);
while (true)
{
var interval = 100;
Thread.Sleep(interval);
var currentUsage = p.NextValue() / Environment.ProcessorCount;
if (currentUsage < limit) continue;
var suspensionTime = (currentUsage-limit) / currentUsage * interval;
SuspendProcess(processId);
Thread.Sleep((int)suspensionTime);
ResumeProcess(processId);
}
}
private static void SuspendProcess(int pid)
{
var process = Process.GetProcessById(pid);
if (process.ProcessName == string.Empty)
return;
foreach (ProcessThread pT in process.Threads)
{
IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
{
continue;
}
SuspendThread(pOpenThread);
CloseHandle(pOpenThread);
}
}
private static void ResumeProcess(int pid)
{
var process = Process.GetProcessById(pid);
if (process.ProcessName == string.Empty)
return;
foreach (ProcessThread pT in process.Threads)
{
IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
{
continue;
}
var suspendCount = 0;
do
{
suspendCount = ResumeThread(pOpenThread);
} while (suspendCount > 0);
CloseHandle(pOpenThread);
}
}
}
The benefit of this solution is that the checking interval becomes independent of the duration of your "long running task". Furthermore, business logic and throttling logic are separated. The suspense/resume code is inspired by this thread. Please note that disposal and ending the throttling needs to be implemented in the solution above, it is not production code.
此解决方案的好处是检查间隔与“长时间运行的任务”的持续时间无关。此外,业务逻辑和节流逻辑是分离的。悬念/简历代码的灵感来自这个线程。请注意,处理和结束节流需要在上面的解决方案中实现,它不是生产代码。