C# 应用程序 - 降低 CPU 使用率

6
我有一个多线程的C#应用程序,其中核心逻辑位于Timer.Elapsed事件处理程序中。该事件处理程序包含2个for循环,最多执行n * n = 5 * 5 = 25次
该应用程序在我的PC上表现良好。我使用VS 2010 Profiler对该应用程序进行了测试,CPU使用率平均为20%
公司的测试人员说,在他的PC上,这会跳到50%100%之间。这给他带来了性能问题。
  • 我能做些什么来解决这个问题吗?
  • 高CPU使用率真正意味着什么?
  • 这可能会影响他的PC吗?
  • 是否有可能告诉应用程序仅利用X数量的CPU?
任何帮助都将不胜感激。

循环执行的次数只有在其执行的上下文中才具有意义。如果你执行昂贵的操作25次,那可能会成为一个大问题。但如果你只是简单的对25求和,那就没关系了。 - rerun
你的计时器触发频率是多少?在操作完成之前,你是否等待计时器再次启动,还是不管上一个循环是否已经完成,都会一遍又一遍地启动循环? - Dan Puzey
计时器每秒执行一次。在计时器事件处理程序中,我在第一行代码中停止计时器,并在最后一行代码中重新启动它。实际上,这只是在事件之间创建了1秒的延迟。在启动和停止计时器之间的代码,在ConcurrentDictionary上进行一些内存计算,该字典可能会增长相当大。这些计算非常简单,但基于大量数据。在此事件处理程序中不涉及与UI的交互,因此我不使用DispatcherTimer或BackgroundWorker。ConcurrentDictionary由各种事件更新。 - c0D3l0g1c
我最初将这段代码放在一个线程中,该线程有一个while循环,循环控制变量,即while(variable) { //Some Code }。这种方法效率较低,因为它使用了更多的资源。因此,我切换到了一个计时器,从而减少了CPU利用率。 - c0D3l0g1c
5个回答

7
  • 减少定时器事件的频率
  • 将工作放在工作线程上(这样UI至少有响应)
  • 减少定时器中的工作量(或者更高效地完成工作)
  • 获得更多的CPU资源

我猜你是指第三个提示,但我们不知道代码在做什么才能给出具体答案;以下是一些没有任何上下文的随机提示:

  • 查看任何集合访问,看看是否可以使用字典、哈希集等替代
  • 检查是否正在进行大量IO操作(尤其是与数据库相关的操作),并尝试减少其数量
  • 检查是否因为使用 Invoke(或类似于UI的操作)而造成了大量的线程切换

3

你现在可能还处于猜测和疑惑的阶段。忘记CPU百分比吧。专业人士会找出程序为什么花费时间以及是否必要。

你可以做的是将代码放在一个长循环中运行,并对其进行采样。 我使用这种方法。 栈采样将优先落在调用树的重要分支上。 有可能你可以削减掉一些重要的分支,从而获得良好的加速效果。


@c0D3l0g1c:关于CPU使用率的事情。CPU总是在执行任务,当它不执行实际代码时,它会执行空闲进程。使用率只是短期内实际运行代码所花费时间的平均值。当您的进程等待I/O时,它并未运行,因此使用率会降低。如果它正在运算,则使用率会提高。这与代码效率几乎没有关系。需要做的就是像我说的那样。基本上,找到可以剪枝的调用树重要分支,加快代码运行速度。 - Mike Dunlavey
谢谢,很有道理!你之前发布的那篇文章非常有用。 - c0D3l0g1c
@c0D3l0g1c:不用客气,也请多宣传。性能调优很容易。找到错误很难,因为你必须一直跟踪程序直到出现问题。但是要找到“瓶颈”,基本上只需暂停它(几次),看看它在做什么即可。 - Mike Dunlavey

1
也许您的应用程序运行多个线程。我有同样的问题,运行多个线程,在每个线程中都有持续更新,这使得应用程序的使用率从50%增加到100%。
经过调查,我只是在线程的连续循环中引入了延迟(Thread(100))。这将使应用程序的使用率降至1%至3%。

1

只需在您的 for 循环中添加 Thread.Sleep(1);。这可以稳定 CPU 使用率并限制其使用最大速度。


1
在代码中添加 Thread.Sleep(int) 以减少 CPU 时间。即使只有30毫秒也可以节省处理器的能量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接