Visual Basic: Фоновый компилятор

Источник: microsoft

Одна из особенностей, отличающих Visual Basic от других языков в Visual Studio, - применение фонового компилятора (background compiler, BC). BC работает с момента открытия проекта Visual Basic и до тех пор, пока он не будет закрыт. Когда вы набираете строку кода и нажимаете клавишу Enter (подтверждаете ввод), BC определяет внесенные изменения и компилирует их, добавляя полученную информацию к внутреннему представлению (коду) разрабатываемого приложения. BC реагирует и на внешние изменения, обновляя состояние скомпилированного кода при добавлении ссылок, изменении настроек проекта или получении более новой копии одного из файлов проекта от системы управления версиями исходного кода.

Наиболее очевидная выгода от фонового компилятора заключается в том, что вы можете практически моментально запустить отладчик или само приложение. Поскольку приложение на самом деле уже скомпилировано, остается лишь загрузить его в отладчик или сбросить на диск. Применение BC дает и другой, менее очевидный эффект, влияющий на процесс разработки в Visual Studio, - почти все средства Visual Basic IDE в Visual Studio 2002 и Visual Studio 2003 для получения нужной информации используют BC. Без него эти средства не могли бы функционировать или работали бы в весьма ограниченном режиме.

Эта дополнительная функциональность, конечно, не бесплатна. Так как UI-средства Visual Basic нуждаются в информации от компилятора, UI иногда будет блокироваться в ожидании символьной информации от BC. В большинстве случаев эта задержка незаметна, но для больших проектов она может быть значительной, особенно при операциях над крупными кусками кода. Поэтому группа разработчиков Visual Studio 2005 стремилась найти компромисс между функциональностью и производительностью.

В этой статье я расскажу, как важнейшие функции редактора Visual Basic используют фоновый компилятор, что Microsoft сделала для повышения производительности, а также опишу действия, которые вы можете предпринять для уменьшения негативного влияния BC на процесс разработки ваших приложений.

Больше информации - больше возможностей

Причина, по которой редактор Visual Basic может предоставлять вам так много информации, кроется в том, что он имеет доступ к внутренней символьной информации, генерируемой BC. Например, IntelliSence может различать две одинаковые по именам переменные в разных или вложенных областях видимости независимо от того, существуют они в текущем проекте или в любой другой части решения, потому что компилятор разрешает все неоднозначности. Без этой информации IntelliSense пришлось бы разбирать текст и делать предположения о том, какой тип имеет каждая из переменных.

Различные средства редактора требуют разных уровней информации от фонового компилятора. Поэтому BC предоставляет методы, при помощи которых соответствующее средство редактора способно ожидать перехода компилятора в определенное состояние, не дожидаясь полного завершения процесса компиляции. Список состояний компилятора представлен в табл. 1.

К примеру, выделение ключевых слов, автоматическое завершение, а также интеллектуальная разметка текста требуют лишь разбора текста, чтобы распознать, что представляет собой исходный код. Поэтому для поддержки таких функций достаточно информации, генерируемой при переходе в состояние Declared. IntelliSence всегда требует «связанной» информации, потому что ей нужно точно различать типы. Тем не менее, IntelliSense работает даже на основе информации, генерируемой при последнем «подтверждении ввода» (переводе «каретки» клавишей Enter, нажатии клавиши «стрелка вниз», вставке из буфера, смене фокуса и т. д.); кроме того, IntelliSense не блокируется в процессе набора текста. Ошибки могут генерироваться в любых состояниях и приводят к переходу в другое состояние,

если только по какой-то причине компиляция не выполняется заново. Вывод списка ошибок в области задач не происходит, пока пользователь продолжает набирать текст (так как при этом все равно потребуется перекомпиляция), и это тоже помогает избежать блокировки IntelliSense.

Рис. 1 иллюстрирует некоторые средства редактора и используемые ими состояния компилятора.

Для увеличения производительности и функциональности члены группы разработчиков компилятора иногда вносят изменения в существующие сред-ства IDE, чтобы они использовали информацию от BC. В Visual Studio 2003 раскрывающиеся списки, браузер объектов и средство просмотра классов впервые начали оперировать с информацией от BC. Ранее (в Visual Studio .NET 2002) эти средства поддерживались весьма медленно работающим XML-диспетчером библиотек (XML-based library manager), который фактически дублировал то, что делает компилятор (причем с гораздо меньшей точностью). После перехода на использование символьной информации компилятора точность сообщаемых ими сведений и производительность существенно повысились. Поэтому члены группы Visual Studio 2005, отвечающие за разработку Visual Basic, его редактора и отладчика, изменили и ядро модели кода, которое теперь опирается на информацию от BC; это дало существенные преимущества для нового дизайнера классов, различных форм и макросов. Все эти средства теперь требуют «связанной» информации, так как для корректной работы им нужно точно идентифицировать объекты.

Новые средства изначально разрабатывались так, чтобы задействовать преимущества от информации, предоставляемой BC. В частности, коррекция ошибок - совершенно новая технология Visual Basic 2005, которая на основе информации компилятора предлагает пользователю варианты исправления ошибок. Хотя ошибки могут происходить в любых состояниях, эта технология на данный момент работает с теми из них, которые генерируются в состояниях Declared и Bound. Как следствие, коррекция ошибок зависит от этих состояний: в первом состоянии распознается наличие ошибок, а во втором определяются варианты их исправления. Вновь появившаяся функциональность Edit and Continue в Visual Basic 2005 полностью полагается на информацию компилятора, определяя, какие изменения кода требуют перезапуска отладчика, и проверяя, не приведет ли к ошибкам добавление нового сгенерированного кода в случае продолжения отладки. Новые функции Find Symbol и Rename Symbol в Visual Basic 2005 зависят от информации, генерируемой при переходе в состояние Bound, - она нужна им для корректного распознавания символов.

Вертикальное масштабирование фонового компилятора

Одно из наиболее заметных изменений внесено в процесс декомпиляции (здесь имеется в виду сброс компилятора к более раннему состоянию, вызванному изменениями, внесенными пользователем). Декомпиляция, за которой следует повторная компиляция, нужна всякий раз, когда в проект вносятся изменения, но иногда это обходится слишком дорого. Например, удаление файла ресурсов не приведет ваш проект в состояние No State - информация, собранная в состоянии Bound, по-прежнему действительна. Хотя декомпиляция в состояние No State после изменений всегда безопасна, слишком большое число декомпиляций может серьезно ухудшить производительность компилятора. Именно так и было в Visual Studio .NET 2002. Чтобы избежать этой проблемы, группа разработчиков внесла изменения в архитектуру в целом, чтобы эффективнее определять, когда декомпиляция действительно нужна и насколько глубокой она должна быть. Например, после того как вы добавляете еще один символ возврата каретки после End Sub, Visual Studio .NET 2002 выполняет декомпиляцию до состояния No State, полагая, что процедура модифицирована (так как изменение произошло на границе процедуры и это могло переопределить ее). Такие проблемы устранены в Visual Studio .NET 2003, поэтому при радикальной модификации больших решений компиляция происходит гораздо быстрее.

Еще больше изменений подобного характера мы внесли в Visual Studio 2005 и, кроме того, усовершенствовали обработку ссылок, что позволило ускорить запуск и выполнение многих операций.

Рекомендации по повышению производительности для более ранних версий

Теперь вас, возможно, интересует, как увеличить производительность сред Visual Basic .NET 2002 и Visual Basic .NET 2003 в процессе работы над проектами. Хотя выключить фоновый компилятор нельзя, вы можете предпринять несколько мер для повышения производительности.

По-видимому, самое важное - избегать запутанных ссылок. Для любого набора проектов в решении, ссылающихся друг на друга, фоновый компилятор, прежде чем продолжить компиляцию, вынужден дожидаться перехода всех проектов в одинаковое состояние. Таким образом, если проект A ссылается на проект B, который ссылается на проект C, а тот - на проект D, и если изменения происходят в D, тогда A, B и С нужно будет декомпилировать до некоего уровня, чтобы включить в решение новую информацию из D. Более сложные зависимости будут вызывать дополнительные задержки.

Также важен способ ссылок на код в других сборках. Visual Basic поддерживает два вида ссылок, исключая Web-ссылки, которые в данном случае нас не интересуют: на файлы (простые ссылки на сборки на диске) и на проекты (ссылки на другие проекты в том же решении). В Visual Studio .NET 2002 и 2003 оба вида ссылок могут быть добавлены щелчком правой кнопки мыши на узле Reference в Solution Explorer и выбором Add Reference. В результате появится диалог Add Reference с вкладками .NET, COM и Projects (рис. 2).

Применяйте ссылки на проекты, только если вы одновременно разрабатываете и проект приложения, и проект, который ссылается на него. Однако, если вы используете уже скомпилированные сборки, ссылка на файл сборки предпочтительнее, так как тогда фоновый компилятор не будет пытаться повторно компилировать тот файл, на который указывает ссылка. В этом случае исходный код используемой сборки даже не должен входить в решение. (Заметим, что в Visual Studio 2005 фоновый компилятор более интеллектуален в обработке ссылок на проекты, но все же работает быстрее, если вы не подключаете другие проекты без всякой необходимости.)

Не люблю советовать выключать какие-то средства редактора для большей производительности (и моя группа усиленно работает над тем, чтобы такое никогда не понадобилось), но в больших приложениях можно выключить какие-то средства, не нужные на данный момент. Например, возможно, вам не нужна функция переформатирования кода (pretty listing), когда вы хотите быстро модифицировать большие его блоки (скажем, вставить большой кусок кода или изменить длинный блок If). Большинство этих средств даже не требует, чтобы BC был в состоянии Declared, поэтому с технической точки зрения это не проблема BC - просто обработка операций занимает какое-то время. Наиболее важные параметры редактирования можно настроить через Tools / Options. Управление IntelliSense осуществляется на странице General (которая называется Statement Completion, как показано на рис. 3).

Интеллектуальную разметку текста (только она полагается на информацию состояния Declared) можно настроить на странице Tabs (рис. 4). Переформатирование кода и другие параметры, связанные с форматом текста, настраиваются на странице Visual Basic (рис. 5).

Старайтесь избегать ситуаций, которые приводят к декомпиляции, - это здорово сэкономит вам время. Декомпиляция в Visual Basic происходит применительно к каждому файлу, что в большинстве случаев соответствует «применительно к каждому классу», следовательно, чем больше ссылок в вашем проекте между классами и структурами, находящимися в разных файлах, тем вероятнее декомпиляция. (Заметьте, что Visual Studio 2005 поддерживает частичные классы, т. е. классы, определенные в нескольких файлах. В этом случае обновление класса может потребовать декомпиляции всех связанных файлов.) Основное правило, которому вы должны следовать при организации классов и структур, заключается в том, что если класс A делает запрос к классу B, то класс B не должен обращаться к классу A для выполнения запроса (иначе появится нежелательная зависимость кода класса А от состояния компиляции).

Структуризация кода - еще один важный аспект производительности редактора, потому что эффективность работы некоторых его средств (например функции переформатирования кода) сильно зависит от качества структуры кода. Добавление или удаление конструкции If размером 5000 строк кода определенно замедлит работу функции переформатирования, потому что придется заново рассчитывать отступы и области видимости измененного блока кода. (По этой причине функция переформатирования автоматически отключается для блоков кода размером более 8000 строк.) Тщательно структурированный код всегда будет обрабатываться быстрее, чем плохо структурированный (это особенно важно в тех редких случаях, когда функция переформатирования нуждается в «связанной» информации).

Заключение

Моя группа постоянно работает над увеличением производительности кода, но это не конечная цель, а бесконечный путь. И хотя мы многое сделали для повышения быстродей-ствия BC и зависимых от него средств в Visual Studio .NET 2003 и предстоящем выпуске Visual Studio 2005, мы продолжаем исследовать свою кодовую базу и реализовать усовер-шенствования в ней. Наша цель - добиться столь малого снижения производительно-сти из-за фоновой компиляции, чтобы пользователи ее даже не замечали. Сейчас мы исследуем идеи по отложенному запуску BC (для уменьшения времени загрузки решения), по усовершенствованию декомпиляции, чтобы еще реже требовался сброс состояния компиляции при внесении изменений, и по улучшению кэширования информации, которая остается неизменной при компиляции/декомпиляции.

Вопросы и комментарии (на английском языке) присылайте по адресу basics@microsoft.com.

Мэтью Герц (Matthew Gertz) более 10 лет работал в Microsoft как разработчик ActiveX Control Pad, Visual InterDev, Visual Studio Enter-prise Edition и Visual Basic. В настоящее время руководит группой разработчиков компилятора, редактора и отладчика для Microsoft Visual Basic.


Страница сайта http://185.71.96.61
Оригинал находится по адресу http://185.71.96.61/home.asp?artId=2973