Следующее извлекается из этой ветки на форумах VMWare:
Привет, ребята,
Мы обнаружили, что sgen.exe работает. Просто есть несколько дополнительных шагов помимо предварительной генерации dll-файлов сериализатора, которые мы пропустили в этой теме. Вот подробная инструкция
ПРОБЛЕМА
При использовании VIM 2.0 SDK из .NET требуется длительное время для создания экземпляра класса VimService. (Класс VimService - это прокси-класс, сгенерированный с помощью команды wsdl.exe vim.wsdl vimService.wsdl)
Другими словами, следующая строка кода:
_service = new VimService();
Выполнение может занять около 50 секунд.
ПРИЧИНА
Очевидно, что .NET XmlSerializer
использует атрибуты System.Xml.Serialization.*
, аннотирующие прокси-классы, для генерации кода сериализации во время выполнения. Когда прокси-классы многочисленны и велики, как, например, код в VimService.cs, генерация кода сериализации может занять много времени.
РЕШЕНИЕ
Это известная проблема с работой сериализатора Microsoft .NET.
Вот некоторые ссылки, которые MSDN предоставляет для решения этой проблемы:
http://msdn2.microsoft.com/en-us/library/bk3w6240.aspx
http://msdn2.microsoft.com/en-us/library/system.xml.serialization.xmlserializerassemblyattribute.aspx
К сожалению, ни одна из вышеперечисленных ссылок не описывает полное решение проблемы. Вместо этого они сосредоточены на том, как предварительно сгенерировать код сериализации XML.
Полное исправление включает в себя следующие шаги:
Создание сборки (DLL) с предварительно сгенерированным кодом XML-сериализатора
Удалить все ссылки на атрибуты System.Xml.Serialization. * Из прокси-кода (то есть из файла VimService.cs)
Добавьте основной прокси-класс с помощью атрибута XmlSerializerAssemblyAttribute, чтобы указать, где находится сборка XML-сериализатора.
Пропуск шага 2 приводит только к 20% улучшению времени создания класса VimService
. Пропуск шага 1 или 3 приводит к неправильному коду. За все три этапа достигается улучшение на 98%.
Вот пошаговые инструкции:
Прежде чем начать, убедитесь, что вы используете инструменты .NET версии 2.0. Это решение не будет работать с версией 1.1 .NET, поскольку инструмент sgen и XmlSerializationAssemblyAttribute
доступны только в версии 2.0 .NET
Создайте файл VimService.cs из WSDL, используя wsdl.exe:
wsdl.exe vim.wsdl vimService.wsdl
Будет выведен файл VimService.cs в текущем каталоге
Скомпилируйте VimService.cs в библиотеку
csc /t:library /out:VimService.dll VimService.cs
Используйте инструмент sgen для предварительной генерации и компиляции сериализаторов XML:
sgen /p VimService.dll
Это выведет VimService.XmlSerializers.dll в текущий каталог
Вернитесь в файл VimService.cs и удалите все атрибуты System.Xml.Serialization.*
. Поскольку код кода большой, лучший способ достичь этого - использовать какой-либо инструмент подстановки регулярных выражений. Будьте осторожны при этом, потому что не все атрибуты появляются в строке сами по себе. Некоторые из них встроены как часть объявления метода.
Если вам трудно выполнить этот шаг, вот упрощенный способ сделать это:
Предполагая, что вы пишете C #, выполните глобальную замену следующей строки:
[System.Xml.Serialization.XmlIncludeAttribute
и замените его на:
// [System.Xml.Serialization.XmlIncludeAttribute
Это избавит от атрибутов Xml.Serialization
, которые являются главными виновниками замедления, закомментировав их. Если вы используете какой-либо другой язык .NET, просто измените замененную строку, чтобы она была закомментирована с префиксом согласно синтаксису этого языка. Этот упрощенный подход даст вам большую часть ускорения, которое вы можете получить. Удаление остальных атрибутов Xml.Serialization обеспечивает дополнительное ускорение на 0,2 с.
Добавьте следующий атрибут в класс VimService в VimService.cs:
[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")]
У вас должно получиться что-то вроде этого:
// ... Some code here ...
[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")]
public partial class VimService : System.Web.Services.Protocols.SoapHttpClientProtocol {
// ... More code here
Восстановить библиотеку VimSerice.dll по
csc /t:library /out:VimService.dll VimService.cs
Теперь из вашего приложения вы можете добавить ссылку на библиотеку VimSerice.dll.
Запустите приложение и убедитесь, что время создания объекта VimService сокращено.
ДОПОЛНИТЕЛЬНЫЕ ЗАМЕЧАНИЯ
Инструмент sgen - это черный ящик, и его поведение зависит от того, что у вас есть в файле Machine.config. Например, по умолчанию предполагается отключить оптимизированный неотладочный код, но это не всегда так. Чтобы получить некоторое представление об инструменте, используйте флаг / k на шаге 3, который заставит его сохранить все свои временные сгенерированные файлы, включая исходные файлы и файлы параметров командной строки, которые он сгенерировал.
Даже после вышеуказанного исправления время, необходимое для создания экземпляра класса VimService в первый раз, не является мгновенным (1,5 секунды). На основании эмпирических наблюдений выясняется, что большая часть оставшегося времени связана с обработкой атрибутов SoapDocumentMethodAttribute
. На данный момент неясно, как это время может быть сокращено. Предварительно сгенерированная сборка XmlSerializer не учитывает атрибуты, связанные с SOAP, поэтому эти атрибуты должны оставаться в коде. Хорошей новостью является то, что только первое создание экземпляра класса VimService для этого приложения занимает много времени. Таким образом, если дополнительные 1,5 секунды являются проблемой, можно попытаться создать фиктивную реализацию этого класса в начале приложения в качестве средства улучшения пользовательского опыта во время входа в систему.