Performance 第二次运行托管应用程序显示的性能与第一次不同

Performance 第二次运行托管应用程序显示的性能与第一次不同,performance,api,benchmarking,performancecounter,Performance,Api,Benchmarking,Performancecounter,我有一个基准测试应用程序来测试我编写的一些API的性能。在这个基准测试应用程序中,我基本上使用QueryPerformanceCounter,并通过将调用API前后QPC值的差值除以频率来获取时间。但是,如果我从不同的驱动器运行应用程序(在同一组DLL上运行相同的可执行文件),基准测试结果似乎会有所不同。此外,在特定驱动器上,第一次运行应用程序、关闭应用程序并再次重新运行会产生不同的基准测试结果。有人能解释这种行为吗?我是不是遗漏了什么 一些更有用的信息: 其行为是这样的:运行应用程序,关闭它,

我有一个基准测试应用程序来测试我编写的一些API的性能。在这个基准测试应用程序中,我基本上使用QueryPerformanceCounter,并通过将调用API前后QPC值的差值除以频率来获取时间。但是,如果我从不同的驱动器运行应用程序(在同一组DLL上运行相同的可执行文件),基准测试结果似乎会有所不同。此外,在特定驱动器上,第一次运行应用程序、关闭应用程序并再次重新运行会产生不同的基准测试结果。有人能解释这种行为吗?我是不是遗漏了什么

一些更有用的信息:

其行为是这样的:运行应用程序,关闭它,然后再次运行,基准测试结果在第二次运行时似乎有所改善,此后保持不变。在从C驱动器运行的情况下,这种行为更加突出。 我还想提到的是,我的基准应用程序可以选择重新运行/重新测试特定的API,而无需关闭应用程序。我确实理解其中涉及到jitting,但我不理解的是,在应用程序的第一次运行中,当您在不关闭应用程序的情况下多次重新运行API时,性能会在几次运行后稳定下来,然后当您关闭并重新运行同一测试时,性能似乎会提高


另外,当从不同的驱动器运行时,您如何解释性能变化

[信息更新]

我做了一个ngen,现在来自同一地点的不同跑步之间的性能差异消失了。i、 e.如果我打开基准测试应用程序,运行一次,关闭它,然后从同一位置重新运行,它会显示相同的值

但我现在遇到了另一个问题。当我从D驱动器启动应用程序并运行几次(在同一次基准测试程序启动中进行了几次API迭代),然后从第三次迭代开始,所有API的性能似乎都下降了20%左右。然后,如果关闭并重新启动应用程序并运行它,在前2次迭代中,它会给出正确的值(与从C中获得的值相同),然后性能会再次下降。当从C驱动器运行时,不会看到此行为。从C驱动,无论你跑了多少次,它都是相当一致的

我正在使用大型双数组来测试我的API性能。我担心GC会在测试之间起作用,所以我在每次测试前后明确地调用GC.Collect()&GC.WaitForPendingFinalizers()。所以我不认为这与GC有任何关系

我尝试使用AQ时间来了解从第三次迭代开始发生了什么,但有趣的是,当我使用AQ时间分析运行应用程序时,性能根本不会下降

性能计数器as不建议任何有趣的IO活动

谢谢 尼兰詹是的。它叫。基本上,您的应用程序部署为MSIL(Microsoft中间语言),第一次运行时会转换为本机代码


您可以始终运行NGen(参见上述文章),或者在性能测试脚本中进行一段预热期,在实际测试性能之前,它会在场景中运行几次。

运行应用程序会将其可执行文件和其他文件从硬盘驱动器带到操作系统的磁盘缓存(RAM中)。如果很快再次运行,这些文件中的许多可能仍在缓存中。RAM比磁盘快得多


当然,一个磁盘可能比另一个磁盘快。

我认为这里有多种效果:

首先,在测试线束中多次运行相同的功能,每次使用相同的数据,可能会有所改善,因为:

  • JIT编译将优化最频繁运行的代码以提高性能(如Cory Foy所述)
  • 程序代码将在磁盘缓存中(由于崩溃)
  • 如果CPU缓存足够小且执行频率足够高,则某些程序代码将位于CPU缓存中
如果测试线束中每次运行功能的数据都不同,这可以解释为什么关闭并再次运行测试线束会改善结果:数据现在也将位于磁盘缓存中,而不是第一次


最后,是的,即使两个“驱动器”位于同一个物理磁盘上,它们的性能也会不同:从磁盘外部读取数据的速度比从磁盘内部读取数据的速度更快。如果它们是不同的物理磁盘,那么很可能会出现性能差异。此外,一个磁盘可能比另一个磁盘碎片更多,导致更长的寻道时间和较慢的数据传输速率。

此外,其他因素也可能起作用。计算机上的文件系统缓存、最近使用的数据的缓冲等


最好运行几个测试(或几百个!),并在整个测试集中取平均值,除非您专门测量冷启动时间。

Cory对一个可能的问题给出了正确的答案。然而,如果你能详细说明结果,它会有更多的帮助。例如,如果第二次跑得更糟,那么情况就不同了。:)抱歉没有提前说明。其行为是这样的:运行应用程序,关闭它,然后再次运行,基准测试结果在第二次运行时似乎有所改善,此后保持不变。这种行为在从C驱动器运行的情况下更加突出。真的吗?它是否真的在运行之间存储JIT代码?从该网页上看,情况似乎并非如此。我认为更可能的是DLL已经加载到内存中。我想在这里提到,我的基准应用程序可以选择在不关闭应用程序的情况下重新运行/重新测试特定的API。我确实了解jitting部分,但我不明白的是,在第一次运行应用程序时,当您多次重新运行API而不关闭