Подтвердить что ты не робот

Почему уровень взаимодействия COM-интерфейса в 40 раз медленнее, когда клиент компилируется в VS 2010 vs VS 2005?

Моя команда работает с COM API большого приложения моделирования. Большинство файлов моделирования запускаются сотнями мегабайт и, как представляется, полностью загружаются в память при их открытии.

Основная задача, которую мы выполняем, - это повторение всех элементов в объектной модели файла, а затем выполнение "чего-то" для каждого элемента.

Недавно мы переместили нашу базу кода из .NET 2 в .NET 4 в VS 2010 и увидели, что скорость итерационной скорости снижается примерно в 40 раз (от ~ 10 секунд до 8 минут). Мы сократили это до наименьшего возможного примера кода (10 строк или около того); скомпилировал это в VS 2005, запустил его, а затем открыл проект в VS 2010 и скомпилировал, оставив фреймворк как 2 (мы используем поставляемые изготовителем сборки COM-соединений).

В 2005 году тестовое приложение завершается за 10 секунд в 2010 году, это занимает 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];
}

Этот код занимает 40 раз дольше, чем VS VS, чем VS 2005.

ОБНОВЛЕНИЕ 2

Я рационализировал, что единственная причина, по которой операция может быть значительно медленнее в одном случае, чем другая, заключается в том, что данные передаются по-разному через COM в разных версиях.

Мы записали журналы привязки для обоих случаев, и это то, что мы нашли; в быстрой версии собственное изображение CustomMarshalers найдено not (это журналы привязки, захваченные 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.

Slow

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

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.

Slow

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, он будет работать с быстрой скоростью.

Я попробовал обернуть этот код в сборке, а затем загрузить его динамически, и это не имеет никакого значения.

4b9b3361

Ответ 1

Это был длинный выстрел. Рад, что я мог помочь.

Соответствие MTA и STA (модель потоков) действительно важно при создании множества различных вызовов в любой COM-объект. Директива [STAThread] в верхней части метода - это один из способов убедиться в модели потоков для каждого вызова в этом методе.

Похоже, что Thread.SetApartmentState(ApartmentState.STA) будет работать для всего потока, но не для потоков потоков пула.

Ответ 2

Когда вы говорите: "... даже в приложениях приложений STA есть...", это на самом деле неверно. Поток может выбрать настройку состояния квартиры до того, как он обратится к любым COM-объектам, но в .NET, если вы ничего не сделаете, эти потоки будут неявно быть MTA.

Путь потока - это MTA. Это должно быть, если вы думаете об этом, потому что, если бы он был заполнен потоками STA, это был бы дрянной поток-пул, поскольку любой раз, когда поток пытался получить доступ к объекту, созданному на одном из других потоков в пуле, он потребовал бы сортировочный.

Thread.SetApartmentState будет работать только по потоку по определению. Он никогда не сможет повлиять на другие потоки (как вы обнаружили). Объекты принадлежат к квартире, и нить может принадлежать одной модели резьбы. Если поток пытается посещать объект с несогласованной моделью, его нужно будет объединить.

Если ваш COM-сервер отмечен как "оба", вы можете использовать его без прокси из STA или потока MTA. Если это так, вам повезло, и вы должны создать его в потоке MTA для начала (или для потоков threadpool это сделать).

Если вы создаете его в потоке STA, даже если (особенно, если) все ваши другие потоки являются STA, они будут ВСЕ проходить через прокси-сервер, если только вы не вызываете объект из потока, который изначально его создал.

Если ваш COM-сервер однопоточный, вам нужно убедиться, что вы вызываете его не только из потока STA, но и потока STA, который его сначала создает, иначе вы будете перенаправлены через прокси.