Какое минимальное снижение производительности связи Cross AppDomain?
Я пытаюсь свести к минимуму снижение производительности связи между доменами приложений на одном компьютере. В моем игрушечном примере класс A загружается в AppDomain 1. Он создает AppDomain 2 и загружает туда экземпляр Class 2 (Class 2 наследуется от MarshalByRef), возвращающий прокси. Затем Class 1 повторно вызывает метод на прокси, который не возвращает значений.
Я получаю следующие результаты:
- Нет доменов приложений, оба класса загружаются в один и тот же домен приложений, и первый вызов повторяет метод на втором (метод не имеет параметров): 24 миллиона вызовов метода / сек.
- Два AppDomain, как описано выше, метод не имеет параметров или строковых параметров: 340000 вызовов методов / сек.
- Два домена приложений, как описано выше, один сериализуемый параметр (массив из двух строк): 64 000 вызовов метода / сек.
Хотя я понимаю снижение производительности между 2 и 3 (сериализация), я действительно не понимаю, почему я в 100 раз медленнее от случая 1 к случаю 2. Насколько я понимаю, после создания прокси все последующие вызовы методов должны быть очень быстрыми, поскольку никакие данные не передаются из одного домена приложений в другой. Кто-нибудь сейчас почему общение через AppDomains так медленно? Я делаю что-то неправильно?
PS1. Единственный совет, который у меня есть по этому вопросу, здесь: "А стоимость пересечения границы AppDomain смущает". Я догадывался, что он имеет в виду сериализацию...
PS2. Я не считаю время создания AppDomain или Proxy (мои тесты начинаются с первого вызова метода)
PS3. Я использую.NET 3.5 в машине WinXP SP3. Я также пробовал.NET 4.0 Beta 1 без существенных различий.
3 ответа
Если вы подсчитаете количество линий IL, участвующих в каждом сценарии, вы увидите, что CLR выполняет намного больше, чем 100-кратную работу при удаленном взаимодействии. Прямой вызов - это всего лишь несколько кодов операций, но с удаленным взаимодействием задействовано несколько классов, реальные / прозрачные прокси, проверки безопасности, сериализация, yadda yadda yadda. Вы должны будете решить эту проблему с помощью дизайна - не существует волшебной палочки для улучшения перфекта через реализацию.
Есть ли способ, которым вы можете вызвать один вспомогательный метод, который принимает параметры о том, сколько раз вы хотите вызвать метод, который вам нужен? Производительность вызовов между доменами сильно зависит от реализации. Я считаю, что в CLR 4.0 это может быть значительно лучше, но я не совсем разбираюсь в деталях.
Однако, как правило, вы хотите избежать издержек, "пакетируя" вызовы через вспомогательный метод.
Я видел те же результаты. Я не могу объяснить, почему он намного медленнее, за исключением того, что он быстрее, чем запуск двух разных процессов и связь друг с другом. В моем дизайне я столкнулся с подобной дилеммой. В конце я изменил свой дизайн для создания независимых доменов приложений; домен приложения мог выполнять свою работу без необходимости связываться с другим доменом приложения во время выполнения... Он будет сообщать данные только после завершения.