我有一个大型(500K行).NET CF(C#)程序,运行在CE6 / .NET CF 3.5(v.3.5.10181.0)上。这是在FreeScale i.Mx31(ARM)@ 400MHz上运行的。它有128MB RAM,大约80MB可用于应用程序。我的应用程序是唯一运行的应用程序(这是一个专用的嵌入式系统)。正在使用的托管内存(由GC.Collect报告)大约为18MB。 为了更好地了解应用程序大小,这里有一些统计数据在启动应用程序后从.NET CF远程性能监视器中剔除:
GC: Garbage Collections 131 Bytes Collected by GC 97,919,260 Managed Bytes in use after GC 17,774,992 Total Bytes in use after GC 24,117,424 GC Compactions 41 JIT: Native Bytes Jitted: 10,274,820 Loader: Classes Loaded 7,393 Methods Loaded 27,691
最近,我一直试图追查性能问题。我发现在两个不同的启动配置中运行应用程序后,我的基准测试将在大约2秒(慢速情况)和1秒(快速情况)下运行。在慢速情况下,基准测试的时间可以从EXE运行到EXE运行从1.1秒到2秒随机变化,但对于任何给定的EXE运行,在应用程序的生命周期内都不会改变。换句话说,您可以重新运行基准测试,并且测试的时间保持不变,直到您重新启动EXE,此时建立新的时间并保持一致。
我无法通过任何传统机制解释1.1到2倍的减速,或者通过缩减基准代码的任何特定部分的减速。似乎整个过程运行得很慢,几乎就像一个线程正在旋转并带走了一些“我的”CPU。
然后,我随机发现,只需将我的应用程序(GUI失去前景)切换到另一个应用程序,我的性能问题就会消失。即使将我的应用程序返回到前台后它仍然消失。我现在有一个试验性的解决方法,我的应用程序在启动后启动一个具有1x1大小窗口的辅助应用程序,在5ms后自杀。因此,aux应用程序占据前景,然后放弃它。
问题是,为什么这会加速我的申请?
我知道当.NET CF应用程序丢失前景时,代码会被调整。我还注意到,当使用.NET CF远程性能监视器执行“GC堆”捕获时,会记录代码间距 - 这也会触发我的应用程序中的性能改进。所以我怀疑代码投放与修复性能有关甚至负责。但我不知道如何确定是否真的如此,或者甚至解释为什么投球代码可以帮助这种方式。抛出大量代码会不会显着地帮助代码页的引用位置(重新JIT,可能在内存中彼此接近)足以帮助这么多? (我的基准测试可能包含3个例程和数百行代码。)
最重要的是,我可以在我的应用中做些什么来可靠地避免这种较慢的情况。任何指向相关.NET CF / JIT / Code投球信息的指针都将不胜感激。
答案 0 :(得分:1)
你的应用程序进入后台会自动触发GC.Collect,它会收集,可能压缩GC堆并可能会调整代码。你有没有检查手册GC.Collect没有去往后台给出相同的行为?它可能不会提供给予性能增益,它可能是收集或压缩。如果大量的死根被扫除,走根树的速度可能会越来越快。不能说我特意看到了这个问题,所以这都是猜想。
答案 1 :(得分:1)
在性能循环之前向你的应用发送wm_hibernate。会清理东西
答案 2 :(得分:0)
我们的.NET CF应用程序存在类似的问题。
随着时间的推移,我们的应用程序逐渐减速,最终因为CPU负载过高而停止运行,或者正如@ wil-s所说,好像线程正在消耗CPU。我到目前为止所做的唯一假设 /结论要么是我们的代码中有一个流氓线程,要么是.NET CF中的封面问题,也许是JITter。
关闭应用程序并重新启动会使我们的应用程序恢复正常的预期性能。
我还没有实现代码更改以测试发布WM_HIBERNATE或启动一个自我退出的虚拟应用程序(如上所述)强制代码间距,但我相当肯定这将根据上述注释解决我们的问题。 (非常感谢你)
然而,我后来有兴趣知道是否曾找到这个特定问题的根本原因?
顺便提一下,看似偏离主题(但请耐心等待),我们正在使用飞思卡尔i.MX28处理器,并且遇到不可预测的FlashDisk损坏。在位于NAND Flash上的随机文件中看到2K块0xFF(擦除块)。
我提到这一点,因为我现在认为CPU和FlashDisk损坏问题是链接的,因为这篇文章以及这篇文章: https://electronics.stackexchange.com/questions/26720/flash-memory-corruption-due-to-electricals
在文章中,@ jwygralak67评论:
我最近在WinCE系统上解决了一个闪存腐败问题, 作为开发团队的一部分。我们偶尔会发现2K块 擦除的闪光灯。 (所有字节0xFF)我们测试了大约6个月 从ESD,脏电到EMI和RFI干扰的一切,我们 购买了全新的设备和跟踪使用情况,以确保我们没有 超过了擦除周期限制并消除了阻塞,我们经历了 我们的(应用程序级别)软件,带有精细的梳齿。
最后,它被证明是一个非常低级别的模糊错误 闪存驱动程序代码,仅在繁重的CPU期间发生 加载。司机来自第三方。我们告诉他们这个问题 我们发现了,但我不知道他们是否发布了补丁。
不幸的是,我们尚未与他联系。
考虑到所有这些,可能如果我们解决高CPU负载,可能,将不再存在损坏。另一个猜想案例! 然而,在这个假设下,这并没有为这两种情况提供坚实的根本原因,而我正在拼命寻求!
非常感谢任何知识或见解,无论多么小,都会非常感激。
@ctacke - 我们之前通过电子邮件发表了关于OpenNETCF的演讲,所以我很高兴看到你的名字!