Microsoft .NET Framework 4.5: Обзор усовершенствований, направленных на повышение производительности

OSzone.net » Microsoft » Разработка приложений » .NET Framework » Microsoft .NET Framework 4.5: Обзор усовершенствований, направленных на повышение производительности
Автор: Эшвин Камат
Иcточник: MSDN Magazine
Опубликована: 13.08.2012

Группа Microsoft .NET Framework всегда понимала, что повышение производительности, как минимум, столь же ценно для разработчиков, как и добавление новых функций исполняющей среды и библиотечных API. В .NET Framework 4.5 вложены значительные усилия, направленные на увеличение производительности во всех прикладных сценариях. Кроме того, поскольку .NET 4.5 является обновлением .NET 4, даже в приложениях для .NET 4 будут заметны многие улучшения производительности существующих в .NET 4 средств.

Когда разработчикам нужно обеспечивать удовлетворительные в отношении быстродействия характеристики приложений, по-настоящему важны время запуска (msdn.microsoft.com/magazine/cc337892), объем используемой памяти (msdn.microsoft.com/magazine/dd882521), пропускная способность и скорость реакции («отзывчивость»). Мы поставили цели улучшить эти показатели для различных сценариев применения. В этой статье я дам высокоуровневый обзор некоторых ключевых усовершенствований для повышения производительности, внесенных в .NET Framework 4.5.

CLR

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

Поддержка многоядерных процессоров JIT-компилятором Мы постоянно отслеживаем прогресс в аппаратном обеспечении и работаем в тесном сотрудничестве с производителями чипов, чтобы добиться максимально эффективной работы нашего программного обеспечения. В частности, многоядерные процессоры появились в наших лабораториях раньше, чем они стали доступны, и мы внесли соответствующие изменения, чтобы задействовать новые достижения в аппаратном обеспечении; однако поначалу выигрыш от этих изменений получали лишь очень немногие клиенты.

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

Эта функция обеспечивает параллельную JIT-компиляцию методов в фоновом потоке, который на многоядерном процессоре будет выполняться на другом ядре. В идеальном случае второе ядро быстро обгонит первое, выполняющее приложение, поэтому большинство JIT-компилируемых методов будет скомпилировано к тому моменту, когда они потребуются. Чтобы знать, какие методы стоит компилировать, данная функция генерирует данные профиля, с помощью которых отслеживаются выполняемые методы, а затем эти данные используются при последующем запуске приложения. Это требование генерации данных профиля — основной способ, которым вы взаимодействуете с этой функцией.

С минимальным добавлением кода вы можете использовать эту функцию исполняющей среды для значительного ускорения времени запуска как клиентских приложений, так и веб-сайтов. В частности, от вас требуется вызвать два статических метода класса ProfileOptimization в пространстве имен System.Runtime. Подробнее на эту тему см. документацию MSDN. Заметьте, что эта функция включена по умолчанию для приложений ASP.NET 4.5 и Silverlight 5.

Оптимизированные неуправляемые образы Вот уже в нескольких выпусках мы даем возможность предварительно компилировать код в неуправляемые образы (native images) с помощью утилиты Native Image Generation (NGen). Такие образы значительно ускоряют запуск приложений по сравнению с JIT-компиляцией. В этом выпуске мы ввели дополнительную утилиту — Managed Profile Guided Optimization (MPGO), которая оптимизирует структуру неуправляемых образов для еще большей производительности. MPGO использует технологию оптимизации на основе профилирования, очень похожую по своей концепции на описанную ранее поддержку многоядерных процессоров JIT-компилятором. При профилировании приложения применяется репрезентативный сценарий или набор сценариев, на основе которого структуры неуправляемого образа могут быть переупорядочены так, чтобы необходимые при запуске методы и структуры данных размещались с плотным прилеганием друг к другу в пределах одной части неуправляемого образа. Это уменьшает время запуска и сокращает рабочий набор (объем занимаемой приложением памяти). Исходя из нашего опыта и тестов, мы, как правило, наблюдаем выигрыш от MPGO в более крупных управляемых приложениях (например, в больших приложениях с интерактивным GUI) и рекомендуем применять эту утилиту именно для таких приложений.

Утилита MPGO генерирует данные профиля для DLL на промежуточном языке (IL) и добавляет этот профиль как ресурс в IL DLL. После профилирования с помощью NGen осуществляется предварительная компиляция IL DLL и выполняется дополнительная оптимизация благодаря наличию данных профиля. Схема этого процесса показана на рис. 1.

*
Увеличить

Рис. 1. Схема процесса при использовании утилиты MPGO

ApplicationПриложение
MPGOMPGO
Application with Profile DataПриложение с данными профиля
NGen InstallNGen
Optimized Application NGen ImagesОптимизированные NGen образы приложения

Распределитель Large Object Heap (LOH) Многие .NET-разработчики просили решить проблему фрагментации LOH или предоставить способ принудительного уплотнения LOH. О том, как работает LOH, можно прочитать в рубрике «CLR с изнанки» за июнь 2008 г. (msdn.microsoft.com/magazine/cc534993). Если в двух словах, то память под любой объект размером 85 000 байтов и более выделяется в LOH. В настоящее время LOH не уплотняется. Уплотнение LOH потребовало бы много времени, так как сборщику мусора пришлось бы перемещать большие объекты, а это создавало бы высокие издержки. Когда объекты в LOH подпадают под сбор мусора, они оставляют свободные пространства между объектами, которые пережили сбор мусора, и это ведет к фрагментации.

CLR создает список свободной памяти из «мертвых» объектов, позволяя повторно использовать их, чтобы удовлетворить запросы на создание больших объектов; смежные мертвые объекты объединяются в один свободный. В конечном счете программа может оказаться в ситуации, когда фрагменты свободной памяти между «живыми» большими объектами недостаточно велики для дальнейшего выделения памяти под большие объекты в LOH, и, поскольку сжатие не предусмотрено, мы быстро попадаем в проблему. Это ведет к тому, что приложение начинает отвечать со все большими задержками, а потом возникают исключения, связанные с нехваткой памяти.

В .NET 4.5 мы внесли некоторые изменения для более эффективного использования фрагментов памяти в LOH, особенно в плане того, как мы управляем списком свободной памяти. Изменения относятся к сбору мусора (garbage collection, GC) как на рабочей станции, так и сервере. Но обратите внимание на то, что это не отменяет лимит в 85 000 байтов на размер объекта в LOH.

Фоновый GC для сервера В .NET 4 мы включили фоновый GC для рабочих станций. С того времени мы все чаще наблюдаем использование куч с размерами в диапазоне от нескольких до десятков гигабайт. Даже такому оптимизированному параллельному сборщику, как у нас, могут потребоваться секунды на сбор столь больших куч, а значит, потоки приложения будут блокированы примерно на то же время. Введение фонового GC для сервера обеспечивает поддержку нашим серверным сборщиком параллельных процедур сбора. Это сводит к минимуму длительные блокирующие операции сбора мусора, почти не влияя на высокую пропускную способность приложения.

Если вы используете серверный GC, вам не нужно ничего делать для того, чтобы задействовать преимущества этой новой функциональности; фоновый GC для сервера выполняется автоматически. Высокоуровневые характеристики фонового GC одинаковы как для клиента, так и для сервера:

Асинхронное программирование

Новая модель асинхронного программирования была введена как элемент Visual Studio Async CTP и теперь является важной частью .NET 4.5. Новые языковые средства в .NET 4.5 позволяют быстрее писать асинхронный код. Поддержку этой модели обеспечивают новые ключевые слова async и await в двух языках (C# и Visual Basic). .NET 4.5 также поддерживает асинхронные приложения, использующие эти новые ключевые слова.

Портал Visual Studio Asynchronous Programming на сайте MSDN (msdn.microsoft.com/vstudio/async) — отличный источник примеров, документов и обсуждений этих новых языковых средств.

Библиотеки параллельных вычислений

В .NET 4.5 был внесен ряд усовершенствований в библиотеки параллельных вычислений (parallel computing libraries, PCL), которые расширяют и улучшают существующие API.

Более быстрые облегченные задачи Классы System.Threading.Tasks.Task и Task<TResult> были оптимизированы так, чтобы они использовали меньше памяти и выполнялись быстрее в основных сценариях применения. В частности, скорость создания объектов Task и планирования продолжений увеличилась вплоть до 60%.

Большее количество параллельно выполняемых PLINQ-запросов PLINQ переключается на последовательное выполнение, когда считает, что распараллеливание данного запроса принесет только вред (замедлит его выполнение). Эти решения принимаются на основе взвешенных догадок и не всегда идеальны, поэтому PLINQ в .NET 4.5 будет распознавать больше классов запросов, которые можно успешно распараллеливать.

Более быстрые параллельные наборы В System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue> внесен ряд тонких изменений, чтобы в определенных сценариях он работал быстрее.

Подробнее об этих изменениях читайте в блоге группы Parallel Computing Platform по ссылке blogs.msdn.com/b/pfxteam.

ADO.NET

Поддержка сжатия строк с null-битами Null-данные особенно часто встречаются у заказчиков, использующих функция разреженных полей (sparse columns feature) в SQL Server 2008. Потенциально они могут получать наборы результатов, содержащие большое количество null-полей. Для этого сценария была введена поддержка сжатия строк с null-битами (маркер SQLNBCROW, или просто NBCROW). За счет сжатия множества полей с NULL-значениями в битовую маску объем строк набора результатов, передаваемых с сервера и содержащих много null-полей, сокращается. Это значительно помогает функции сжатия в протоколе TDS (tabular data stream), где в данных присутствует много null-полей.

Entity Framework

Автоматически компилируемые LINQ-запросы Сегодня, когда вы пишете запрос LINQ to Entities, инфраструктура Entity Framework проходит все дерево выражений, сгенерированное компилятором C#/Visual Basic и транслирует (или компилирует) его в SQL-код, как показано на рис. 2.

*
Рис. 2. Запрос LINQ to Entities, скомпилированный в SQL-код

Компиляция дерева выражений в SQL, однако, приводит к некоторым издержкам, особенно в случае более сложных запросов. В предыдущих версиях Entity Framework, если вы хотели избежать таких издержек при каждом выполнении LINQ-запроса, вы должны были использовать класс CompiledQuery.

Новая версия Entity Framework поддерживает новую функциональность Auto-Compiled LINQ Queries. Теперь каждый выполняемый вами запрос LINQ to Entities автоматически компилируется и помещается в кеш плана запросов (query plan cache) Entity Framework. При каждом повторном выполнении запроса Entity Framework будет находить его в своем кеше запросов и не станет заново инициировать весь процесс компиляции. Подробнее об этом см. по ссылке bit.ly/iCaM2b.

Windows Communication Foundation и Windows Workflow Foundation

Группы Windows Communication Foundation (WCF) и Windows Workflow Foundation (WF) также внесли целый ряд усовершенствований в эти подсистемы, некоторые из которых перечислены ниже.

Более полные описания вы найдете в блоге группы Workflow Team (blogs.msdn.com/b/workflowteam) и в статье из MSDN Library по ссылке bit.ly/n5VCtU.

ASP.NET

Повышение плотности сайтов (site density) (также определяемой как потребление памяти на каждый сайт) и время «холодного» запуска сайтов в случае виртуального хостинга (shared hosting) — вот две основные цели в области производительности, которые ставились группой ASP.NET при работе над .NET 4.5.

В сценариях с виртуальным хостингом множество сайтов размещается на одной машине. В таких средах трафик обычно низкий. Данные, предоставляемые некоторыми компаниями-хостерами, показывают, что большую часть времени количество запросов в секунду ниже 1 с отдельными всплесками до 2 или более. Это означает, что многие рабочие процессы (worker processes) скорее всего будут уничтожены, если они простаивают длительное время (20 минут по умолчанию в IIS 7 и более поздних версиях). Таким образом, стартовое время становится очень важным. В ASP.NET это то время, которое требуется веб-сайту на то, чтобы принять запрос и ответить на него, когда рабочий процесс уже завершен.

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

<configuration>
<!-- ... -->
<system.web>
<compilation profileGuidedOptimizations="None" />
<!-- ... -->
sc config sysmain start=auto
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters" /v EnablePrefetcher /t REG_DWORD /d 2 /f
reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Prefetcher" /v MaxPrefetchFiles /t REG_DWORD /d 8192 /f
net start sysmain

После этого вы можете обновить файл web.config, чтобы использовать предвыборку и в ASP.NET:

<configuration>
<!-- ... -->
<system.web>
<compilation enablePrefetchOptimization
  ="true" />
<!-- ... -->
<configuration>
<!-- ... -->
<runtime>
<performanceScenario
  value="HighDensityWebHosting" />
  <!-- ... -->

Более подробную информацию об усовершенствованиях в области производительности ASP.NET можно найти в документе «Getting Started with the Next Version of ASP.NET» по ссылке bit.ly/A66I7R.

Нам нужны ваши отзывы

Представленный здесь список усовершенствований далеко не полный. Множество менее масштабных улучшений было опущено, чтобы показать главное. Помимо этого, группы .NET Framework также работали над улучшениями производительности, специфичными для управляемых приложений Windows 8 в стиле Metro. Когда вы скачаете и опробуете .NET Framework 4.5 и бета-версию Visual Studio 11 для Windows 8, пожалуйста, дайте нам знать, если у вас появятся какие-либо замечания или предложения, чтобы мы могли учесть их в предстоящих выпусках.

Словарь терминов

Виртуальный хостинг (shared hosting) Также называется виртуальным веб-хостингом. Плотный веб-хостинг сотен, если не тысяч, веб-сайтов, выполняемых на одном сервере. За счет разделения затрат на оборудование расходы на поддержку каждого сайта можно свести к минимуму. Этот метод значительно понижает барьер входа для владельцев веб-сайтов.

Холодный запуск (cold startup) Время, необходимое на запуск приложения, когда его уже нет в памяти. Такое можно наблюдать, например, при запуске приложения после перезагрузки системы. В случае крупных приложений время холодного запуска может достигать нескольких секунд, так как в памяти отсутствуют необходимые страницы (код, статические данные, данные реестра и т. д.) и для их загрузки требуется обращения к дисковой подсистеме, что, естественно, замедляет процесс запуска.

Теплый запуск (warm startup) Время, необходимое на запуск приложения, когда оно уже находится в памяти. Например, если приложение было запущено несколько секунд назад, то, вполне вероятно, большая часть его страниц загружена в память и ОС будет повторно использовать их, экономя на дорогостоящих дисковых операциях. Вот почему приложение гораздо быстрее запускается при его повторном запуске (или почему второе .NET-приложение запускается быстрее первого — части .NET уже загружены в память).

Генерация неуправляемого образа (Native Image Generation, NGen) Относится к процессу предварительной компиляции исполняемых файлов с IL-кодом (Intermediate Language) в машинный код до их выполнения. Это дает два основных преимущества в производительности. Во-первых, уменьшается время запуска приложения, поскольку нет нужды компилировать код в период выполнения. Во-вторых, память используется эффективнее за счет возможности совместного использования страниц кода несколькими процессами. Также существует утилита, NGen.exe, которая создает неуправляемые образы и устанавливает их в Native Image Cache (NIC) на локальном компьютере. Исполняющая среда загружает неуправляемые образы, если они доступны.

Оптимизация на основе данных профиля (profile guided optimization) Такая оптимизация гарантированно ускоряет запуск и работу всех приложений — как управляемых, так и неуправляемых. Windows предоставляет инструментарий и инфраструктуру для выполнения оптимизации на основе данных профилей применительно к неуправляемым сборкам, а CLR — для выполнения аналогичной оптимизации применительно к управляемым сборкам (она называется Managed Profile Guided Optimization, или MPGO). Эти технологии используются многими группами в Microsoft для повышения производительности их приложений.

Сборщик мусора (garbage collector) Исполняющая среда .NET поддерживает автоматическое управление памятью. Она отслеживает каждую операцию выделения памяти, выполненную управляемой программой, и периодически вызывает сборщик мусора, который находит более не используемую память и делает ее доступной для новых операций выделения памяти. Важная оптимизация, выполняемая сборщиком мусора, заключается в том, что он не просматривает всю кучу каждый раз, а разделяет ее на три поколения (поколения 0, 1 и 2). Подробнее о работе сборщика мусора см. рубрику «CLR с изнанки» за июнь 2009 г. по ссылке msdn.microsoft.com/magazine/dd882521.

Уплотнение (compacting) Когда куча достигает пороговой фрагментации, сборщик мусора перемещает активные объекты ближе друг к другу. Главная цель уплотнения кучи — сделать возможным выделение более крупных блоков памяти под большее количество объектов.


Ссылка: http://www.oszone.net/18549/