在VS 2010和VS 2005中编译客户端时,为什么COM互操作层会慢40倍?

bri*_*ler 30 c# com visual-studio-2005 visual-studio-2010 visual-studio

我的团队使用大型模拟应用程序的COM API.大多数模拟文件都会运行到数百兆字节,并且在打开时似乎会完全加载到内存中.

我们执行的主要任务是遍历文件的对象模型中的所有元素,然后对每个元素执行"某事".

我们最近将我们的代码库从.NET 2迁移到VS 2010中的.NET 4,并且已经看到迭代速度下降了大约40倍(从大约10秒到大约8分钟).我们已将其减少到最小的代码示例(10行左右); 在VS 2005中编译它,运行它然后在VS 2010中打开项目并编译,将框架保留为2(我们使用制造商提供的COM互操作程序集).

在2005年,测试应用程序在2010年完成10秒,需要8分钟.

可能是什么导致了这个?

UPDATE

代码相当于:

var server = new Server();
var elements = server.Elements;
var elementCount = elements.Count;

for(int i = 0; i < elementsCount; ++i)
{
    var element = elements[i];
}
Run Code Online (Sandbox Code Playgroud)

运行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.
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

CustomMarshalers

CustomMarshalers, Version=2.0.0.0, Culture=neutral, 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.
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

所以看起来我们在使用原生图像时会获得很大的性能提升.

为什么这种绑定在一种情况下失败并在另一种情况下成功,我们如何强制应用程序不使用本机映像?

更新3

奇怪的是继续.如果我使用R#test runner或内置的Visual Studio测试运行器在测试方法中在VS 2010中运行此代码,那么它将以快速运行.

我已经尝试将这个代码包装在一个程序集中,然后动态加载它并没有任何区别.

小智 5

这是一个很长的镜头.很高兴我能帮助你.

在对任何COM对象进行大量不同的调用时,匹配MTA与STA(线程模型)非常重要.[STAThread]方法顶部的指令是确保该方法中每个调用的线程模型的一种方法.

看起来像是Thread.SetApartmentState(ApartmentState.STA)适用于整个线程,但对于线程池线程来说似乎并不明显.