代码之家  ›  专栏  ›  技术社区  ›  Drake

如何解决VB.NET 1.1应用程序的性能衰减问题?

  •  2
  • Drake  · 技术社区  · 16 年前

    我有用它编写的单线程Windows窗体应用程序 VB.NET 靶向性 框架1.1 . 软件通过串行接口与外部板通信,主要由 状态机 它运行一些测试,在一个循环中用一个计时器和50毫秒的间隔驱动。

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

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

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

    我知道不看代码很难做到这一点,但是您有没有建议我如何处理这个问题?

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

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

    编辑3 :我发现 句柄问题是由C++库生成的 我们正在使用与串行设备通信。然后在.NET 1.1和.NET 2.0中都会发生。不同之处在于,如果目标.NET 1.1应用程序在.NET 2.0中减速/冻结,我就可以在不丧失性能的情况下达到30000多个句柄。现在我不知道这个问题是否真的是由这个丢失的句柄引起的,我会尝试向C++库的开发人员请求纠正这个问题,看看它是否解决了我在.NET 1.1上遇到的问题。

    full image here

    alt text http://img341.imageshack.us/img341/6923/process.png

    4 回复  |  直到 16 年前
        1
  •  2
  •   Binary Worrier    16 年前

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

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

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

    其中getathing()返回实现IDispose的对象。

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

    希望这有帮助:)

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

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

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

        2
  •  2
  •   Chris Schmich    16 年前

    完全公开:我是Visual Studio探查器团队的成员。

    编辑:由于vs profiler不适用于.NET 1.1,因此以下内容无效。 你试过在分析器下运行你的代码吗?Visual Studio 2005/2008(开发人员版/团队套件)和Visual Studio 2010 Premium/Ultimate具有内置的探查器。还有第三方.NET配置文件可用。

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

    或者,您可以模拟廉价的分析:调试您的应用程序并周期性地进入它,以查看调用堆栈上正在执行的操作。


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

        3
  •  1
  •   Flory    16 年前

    首先,我会像Tess建议的那样使用Windows中包含的性能分析器。 here .

    那我就照她说的那样多用windbg here .

    我只建议温德伯格第二次,因为如果你没有使用它,你会在一个小的WTF会议,直到你得到它(这是完全值得得到)。也许通过玩弄柜台,你可以找到问题所在。

        4
  •  1
  •   Darknight    16 年前

    六羟甲基三聚氰胺六甲醚

    由于信息有限,可能会有一百万件事。

    使用一点 “禅” 编程,我会说,摆脱计时器,开始使用线程。

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

    推荐文章