我正在开发一个工作项目,但代码存在性能问题。
我认为我会改进一些改进性能,但没有真正的方法来衡量我的改变如何影响它。
我编写了一个单元测试,按照当前实现的方式执行操作,使用Stopwatch
来监视函数的运行速度。我也写了一个类似的单元测试,它做的事情略有不同。
如果测试一起运行,则需要1秒才能完成,另一个需要73毫秒。 如果测试是单独运行的,那么它们都需要大约1秒来完成(是的......我所做的改变似乎没有太大变化)。
如果测试相同,我有同样的问题,一个比另一个跑得快。
Visual studio是否在幕后做些什么来提高性能?我可以把它关掉吗?
我已经尝试将测试移动到不同的文件中,但这并没有解决我遇到的问题。
我希望能够运行所有测试,但让它们运行就好像一次只运行一个测试一样。
答案 0 :(得分:3)
我的猜测:它可能是dll加载和JIT编译
.NET懒洋洋地加载程序集(dll)。如果添加对FooLibrary的引用,则并不意味着在加载代码时会加载它。
相反,会发生的事情是,第一次调用函数或从FooLibrary实例化一个类,然后然后 CLR将加载它所在的dll。这包括在文件系统中搜索它,可能安全检查等。
如果你的代码甚至是中等复杂的,那么“第一次测试”通常会导致数十个程序集被加载,这显然需要一些时间。
后续测试显得很快,因为所有内容都已加载。
请记住,您的.NET程序集不包含CPU可以直接执行的代码。无论何时调用任何.NET函数,CLR都会获取MSIL字节码并将其编译为可执行的机器代码,然后运行此机器代码。它是基于每个功能执行此操作
所以,如果你认为第一次调用任何函数时,JIT编译时会有一个小的延迟,这些东西会加起来。如果您正在调用大量功能或初始化大型第三方库(想想实体框架等),这可能会特别糟糕。
如上所述,后续测试看起来很快,因为许多函数已经被JIT编译,并缓存在内存中。
您可以通过减少装配来改善装配加载时间。这意味着更少的文件搜索等。 The microsoft .NET performance guidelines详细介绍。 另外,我认为在全局程序集缓存中安装它们可能会有帮助,但是我还没有测试过,所以请大量使用它。 安装到GAC需要管理权限,这是一项非常重要的操作。您不希望在开发期间执行此操作,因为将导致您出现问题(程序集从GAC加载而不是文件系统,因此您最终可以加载代码的旧副本而不会实现它。)
您可以使用ngen预编译程序集来改善JIT时间。但是,与GAC一样,这需要管理权限并需要一些时间,因此您不希望在开发期间执行此操作。
我的建议?
首先,在单元测试中测量性能并不是一件特别好或可靠的事情。谁知道视觉工作室在后台做了什么,可能会或可能不会影响您的测试。
一旦你获得了代码,你就会尝试将其作为独立应用程序的基准测试,让它循环并运行所有测试两次,并丢弃第一个结果: - )
答案 1 :(得分:0)
“过早优化是万恶之源。”
如果您之前没有测量过,您怎么知道现在正在修理任何东西?你怎么知道你有一个需要解决的问题?
单元测试用于操作正确性。它们可以用于性能,但我不会依赖它,因为许多其他因素在运行时发挥作用。
您最好的选择是获取一个分析器(或使用VS附带的分析器)并开始测量。