为啥我的应用程序随着时间的推移变得反应迟钝?

Posted

技术标签:

【中文标题】为啥我的应用程序随着时间的推移变得反应迟钝?【英文标题】:Why is my application becoming less responsive over time?为什么我的应用程序随着时间的推移变得反应迟钝? 【发布时间】:2018-12-15 22:28:49 【问题描述】:

我正在调试一个几天后几乎没有响应的 C# 应用程序。应用程序每秒计算一次内存/CPU 使用率并将其显示在主 UI 的页脚中。

无响应的原因是获取PerformanceCounterRawValue 所需的时间(“Working Set - Private”)。几天后,获取RawValue 需要将近一秒钟,从而冻结了主 UI 线程。如果我重新启动计算机,几天后一切都会再次快速,直到它慢慢变得不那么响应。如果我在没有PerformanceCounter 代码(它是开源的)的情况下重新编译这个应用程序,它会立即正常运行。

为了排除它是应用程序,这里有一些执行完全相同的示例代码:

static void Main(string[] args)

    using (var memoryWorkingSetCounter = new PerformanceCounter("Process", "Working Set - Private", Process.GetCurrentProcess().ProcessName, true))
    
        while (!Console.KeyAvailable)
        
            var memoryWorkingSetSw = new Stopwatch();
            memoryWorkingSetSw.Start();
            var memoryWorkingSetValue = memoryWorkingSetCounter.RawValue;
            memoryWorkingSetSw.Stop();
            Console.WriteLine(memoryWorkingSetValue.ToString());
            Console.WriteLine(memoryWorkingSetSw.Elapsed.ToString());
            Thread.Sleep(TimeSpan.FromSeconds(1));
        
    
    Console.Read();

我让这个运行了大约 2.5 天,并以毫秒为单位绘制了 Elapsed 时间:

什么会导致 Windows 中的性能计数器随着时间的推移变慢?其他应用程序不能清理它吗?有没有办法调试哪些应用程序也在查看这个性能计数器?我在 Windows 10 上。

【问题讨论】:

如果将PerformanceCounter 变量的范围缩小到.RawValue 调用附近会发生什么?也许该对象会随着时间的推移保留数据。 从技术上讲,这可能是由您的程序以外的其他原因引起的,例如反复启动且不会终止的行为不端的进程。页面映射表的碎片化在技术上是可行的。这不是一个便宜的柜台,很难鼓起足够的耐心。一旦被咬,两次害羞,这是一个非常无用的统计数据,所以放弃它。 Process.WorkingSet64 值得注意,它使用一种非常不同的方式来获取信息。但是要测量程序施加的内存压力,您总是倾向于 Process.PrivateMemorySize64。 @NathanWerry 好吧,这可能是问题所在,除了构造这个PerformanceCounter 每次需要大约6+秒... @HansPassant 当然,但它不是我说的我的程序。这是一个开源应用程序,他们并不真正接受贡献。您有任何想法如何在 Windows 上进行较低级别的调试吗?我没有看到任何进程重复启动/不要终止。 您持有该对象很长时间,直到您停止应用程序范围不会超出using 并且它不会破坏该对象;尝试在方法中移动此块并在 while 循环中调用该方法。 【参考方案1】:

为什么要在循环中声明 Stopwatch? 删除循环内可能出现的任何新声明。

当你这样做时,内存会随着时间的推移而增加,你指望垃圾收集器来完成这项工作

【讨论】:

static void Main(string[] args) // 这是你在循环外的声明 var memoryWorkingSetSw = new Stopwatch(); using (var memoryWorkingSetCounter = new PerformanceCounter("Process", "Working Set - Private", Process.GetCurrentProcess().ProcessName, true)) while (!Console.KeyAvailable) // 你的代码 Console.Read() ;

以上是关于为啥我的应用程序随着时间的推移变得反应迟钝?的主要内容,如果未能解决你的问题,请参考以下文章

Play 2.5应用程序(deadbolt?)变得反应迟钝

Plotly-Dash:反应迟钝的情节

随着时间的推移,重复的 SwiftUI 动画变得不稳定

如何弄清楚为啥垃圾收集器使用了我 90% 的 CPU?

markdown 当Gnome shell冻结或变得反应迟钝时要尝试的事情

随着时间的推移对 (UI) 事件的模式作出反应