我的团队使用一个大型模拟应用程序的COM API。大多数模拟文件都有几百兆字节大小,并且在打开时似乎会完全加载到内存中。
我们的主要任务是遍历文件对象模型中的所有元素,然后对每个元素执行“某些操作”。
我们最近将代码从VS 2005 .NET 2移植到了VS 2010 .NET 4,并发现迭代速度下降了约40倍(从约10秒变为约8分钟)。我们已将其简化为最小可能的代码示例(大约10行),在VS 2005中编译并运行,然后在VS 2010中打开项目并编译(我们正在使用制造商提供的COM互操作组件),同时保留框架为2。
在2005年测试应用程序完成需要10秒,在2010年需要8分钟。
这是什么原因?
更新
该代码等效于:
var server = new Server();
var elements = server.Elements;
var elementCount = elements.Count;
for(int i = 0; i < elementsCount; ++i)
{
var element = elements[i];
}
这段代码在VS 2010中运行的时间比在VS 2005中慢40倍。
更新2
我推断造成一个版本比另一个版本运行速度显著下降的唯一原因是数据在不同的版本上通过COM传输方式存在差异。
我们记录了两种情况下的绑定日志,发现在快速版本中未找到CustomMarshalers的本机映像(这些是由FUSLOGVW捕获的绑定日志)。
mscorlib
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.HTM
快速版本
LOG: Start binding of native image mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
LOG: Start validating native image mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
WRN: Native image does not satisfy request. Looking for next native image.
WRN: No matching native image found.
缓慢
LOG: Start binding of native image mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
LOG: Start validating native image mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
LOG: Bind to native image succeeded.
自定义编组器
CustomMarshalers,版本=2.0.0.0,文化=中性,PublicKeyToken=b03f5f7f11d50a3a
快速
LOG: Start binding of native image CustomMarshalers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.
LOG: Start validating native image CustomMarshalers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.
WRN: Native image does not satisfy request. Looking for next native image.
WRN: No matching native image found.
缓慢
LOG: Start binding of native image CustomMarshalers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.
LOG: Start validating native image CustomMarshalers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.
LOG: Start validating all the dependencies.
LOG: [Level 1]Start validating native image dependency mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
LOG: Dependency evaluation succeeded.
LOG: [Level 1]Start validating IL dependency Microsoft.VisualC, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.
LOG: Dependency evaluation succeeded.
LOG: Validation of dependencies succeeded.
LOG: Start loading all the dependencies into load context.
LOG: Loading of dependencies succeeded.
LOG: Bind to native image succeeded.
Native image has correct version information.
Attempting to use native image C:\WINDOWS\assembly\NativeImages_v2.0.50727_32\CustomMarshalers\3e6deccf191ab943d3a0812a38ab5c97\CustomMarshalers.ni.dll.
Native image successfully used.
看起来当不使用本地映像时,性能会得到很大提升。
为什么这个绑定会在一个情况下失败,在另一个情况下成功,我们如何强制应用程序不使用本地映像?
更新3
奇怪的事情还在继续。如果我在VS 2010中使用R#测试运行器或内置的Visual Studio测试运行器在一个测试方法中运行此代码,那么它会以快速的速度运行。
我已经尝试将此代码包装在程序集中,然后动态加载它,但没有任何区别。
var t = new Thread()
并设置t.SetApartmentState(ApartmentState.STA)
;默认情况下,所有线程都是MTA线程 - 你不能使用线程池(即bgworker),因为所有线程池线程都是MTA线程。 - satnhak