如何解决 VB.NET 1.1 应用程序的性能下降?

Posted

技术标签:

【中文标题】如何解决 VB.NET 1.1 应用程序的性能下降?【英文标题】:How to solve the performance decay of a VB.NET 1.1 application? 【发布时间】:2010-05-20 07:23:21 【问题描述】:

我有一个用 VB.NET 编写并针对 Framework 1.1 的单线程窗体应用程序。该软件通过串行接口与外部板卡通信,它主要由一个运行一些测试的状态机组成,在一个循环中驱动,由一个定时器和一个 50 毫秒的间隔完成。

用户界面的反馈是通过测试期间引发的一些自定义事件来完成的。

让我抓狂的问题是性能会随着时间的推移而略有下降,尤其是在 1200/1300 测试操作之后。占用的内存不会随着时间的推移而增加,似乎只有 CPU 对此问题感兴趣。

奇怪的是,针对框架 2.0 并使用相同的代码,我没有这个问题。

我知道不看代码就很难,但是你有什么建议可以解决这个问题吗?

编辑:我真的迷路了,经过几次密集的工作后,应用程序开始变慢。所选行与其进程相关,如果有帮助的话。

EDIT2:使用 Windows 任务管理器,我检测到 Handles 计数器在每次操作结束时增加 1。我不知道这是否是原因,但是当句柄计数器达到大约 1500 个句柄时,应用程序开始变慢。我检查了每次操作后是否调用了所有必要的 RemoveHandler。有什么想法吗?

EDIT3:我发现handles 问题是由我们用来与串行设备通信的C++ 库 产生的。然后它会在 .NET 1.1 和 .NET 2.0 中发生。不同的是,这很奇怪,如果目标 .NET 1.1 应用程序减慢/冻结而不是 .NET 2.0 我达到了超过 30000 个句柄而不会失去性能。现在我不知道问题是否真的是由这个丢失的句柄引起的,我会尝试要求 C++ 库的开发人员纠正问题,看看它是否解决了我在 .NET 1.1 上遇到的问题。

full image here

【问题讨论】:

@Chris。如果它适用于 2.0,为什么需要使用 1.1?您是否尝试过 Red-gate 性能分析器(非常棒)。 该工具已在 1.1 中编写,并且 1.1 是所需的框架。也许有一些可能迁移到框架 2.0,但不确定。我会检查红色门分析器,希望对您有所帮助 内存使用峰值列告诉你什么?另外,您似乎正在阅读 250MB 的信息,您是怎么做到的? @roygbiv 内存峰值告诉我 204MB。读取量大是由于PC和外部设备使用串口进行数据交换 任何可能泄漏 Win32 句柄的本机代码? (并不是说 .net 库中不可能存在错误/竞争条件)每次执行计时器循环时,句柄的数量是否会增加? 【参考方案1】:

好的,既然你不能使用性能分析器,我可以想两件事来尝试。

1) 这是一个愚蠢/显而易见的问题。您绝对确定要处置实现 IDispose 的所有内容吗? 即使您确定返回并再次检查,也要留意不会被丢弃的临时对象,例如

   string s = objA.GetAThing().ToString()

GetAThing() 返回一个实现 IDispose 的对象。

2) 您是否尝试过强制垃圾回收? 阅读Rico Mariani's Performance Tidbits,有时不仅可以拨打GC.Collect(),有时还需要。 我们有一个大型丰富的 .Net winforms 应用程序,我们需要每隔十分钟左右强制收集一次。如果我们不这样做,应用程序会在几个小时后开始运行。

希望这会有所帮助:)

更新 真可惜。你有 C++ 源代码吗?或者你被这个问题困住了?

如果卡住了,您可以让应用程序在终止当前实例的同时定期启动一个新实例。

您可以使用锁定的文件或 Mutex 来确保新实例在第一个实例终止之前不会开始处理。

【讨论】:

感谢您的回答,但我发现句柄问题是由我们用于与串行设备通信的C++库产生的。然后它会在 .NET 1.1 和 .NET 2.0 中发生。不同的是,这很奇怪,如果目标 .NET 1.1 应用程序减慢/冻结而不是 .NET 2.0,我会在不损失性能的情况下达到超过 30000 个句柄。【参考方案2】:

完全披露:我是 Visual Studio Profiler 团队的一员。

编辑:以下内容没有用,因为 VS Profiler 不适用于 .NET 1.1。 您是否尝试过在分析器下运行代码? Visual Studio 2005/2008 (Developmen Edition/Team Suite) 和 Visual Studio 2010 Premium/Ultimate 有一个内置的分析器。还有第 3 方 .NET 分析器可用。

在分析器下运行您的代码将显示您的 CPU 在哪里做了大量工作。如果您仅在性能下降的时间进行分析,结果应该可以帮助您了解原因。

或者,您可以模拟廉价的分析:调试您的应用程序并定期中断它以查看调用堆栈上正在执行的内容。


另外,您的机器是否安装了.NET Framework 1.1 SP1?你能在其他机器上重现这个问题吗?

【讨论】:

感谢您的支持。该问题可以在不同的机器上重现,并且在所有机器中都安装了 SP1。我做了你建议的廉价分析,还打印了例程的堆栈级别,但似乎堆栈级别很低并且没有增长,总是小于 50。您认为 VS Premium Profiler 在运行时可以附加到 .NET 1.1 吗? 抱歉,我实际上忘记了,VS Profiler 不适用于 .NET 1.1。所以不,你不能使用它。对于“便宜的分析方法”,不必担心堆栈的深度,只需定期中断(10 次左右),并跟踪正在执行的内容。如果您始终看到在堆栈顶部执行相同的方法,那么这应该有助于缩小问题所在。【参考方案3】:

首先,我会按照 Tess 的建议 here 使用 Windows 中包含的性​​能分析器。

然后我会像她建议的那样使用windbg here。

我只建议第二个使用windbg,因为如果你还没有使用它,你会在你得到它之前参加一个小小的WTF会话(尽管它完全值得得到)。也许通过玩计数器你可以找到问题。

【讨论】:

【参考方案4】:

在信息如此有限的情况下,它可能是一百万件事。

使用一点 'Zen' 编程我会说,摆脱计时器并开始使用线程。

使用具有取消标志的常用模式,并让测试在一个 while 循环中运行(如果需要的话)。

【讨论】:

以上是关于如何解决 VB.NET 1.1 应用程序的性能下降?的主要内容,如果未能解决你的问题,请参考以下文章

在 vb.net 中为 .net 1.1 框架动态创建 pdf 文件 [关闭]

如何用VB.NET StringBuilder优化字符串操作性能

C#/VB.NET 将HTML转为XPS

如何解决 vb.net 应用程序中的 mysql 定义错误?

VB.NET程序界面假死如何解决

用C#编写的asp.net 和 vb.net编写的asp.net 有性能上的差异吗?