Оптимизация приложений на платформе .NET
Покупка
Издательство:
ДМК Пресс
Перевод:
Киселев Артём Николаевич
Год издания: 2014
Кол-во страниц: 524
Дополнительно
Вид издания:
Практическое пособие
Уровень образования:
ВО - Бакалавриат
ISBN: 978-5-94074-944-8
Артикул: 477133.02.99
К покупке доступен более свежий выпуск
Перейти
Увеличение производительности алгоритмов и приложений является чрезвычайно важным аспектом разработки и может дать вам преимущество перед конкурентами, а вашим пользователям обеспечить низкую стоимость владения и удовольствие от использования быстрых и отзывчивых приложений. Данная книга описывает внутренние особенности ОС Windows, среды выполнения CLR и аппаратного обеспечения, влияющие на производительность приложений, а также дает вам знания и инструменты для измерения производительности вашего кода в изоляции от внешних факторов. Книга наполнена примерами кода на С# и рекомендациями, которые помогут вам выжать максимум возможного из вашего приложения - низкое потребление памяти, согласованную нагрузку на процессор и минимальное количество операций ввода/вывода с сетью и диском. Издание предназначено для программистов, знакомых с языком С# и платформой .NET.
Тематика:
ББК:
УДК:
ОКСО:
- ВО - Бакалавриат
- 02.03.01: Математика и компьютерные науки
- 02.03.02: Фундаментальная информатика и информационные технологии
- 09.03.01: Информатика и вычислительная техника
- 09.03.02: Информационные системы и технологии
- 09.03.03: Прикладная информатика
- 09.03.04: Программная инженерия
ГРНТИ:
Скопировать запись
Фрагмент текстового слоя документа размещен для индексирующих роботов.
Для полноценной работы с документом, пожалуйста, перейдите в
ридер.
Голдштейн С. Зурбалев Д. Флатов И. Оптимизация приложений на платформе .NET
Pro .NET Performance Sasha Goldshtein Dima Zurbalev Ido Flatov Apress ®
Оптимизация приложений на платформе .NET Москва, 2014 Голдштейн С. Зурбалев Д. Флатов И.
УДК 004.438.NET ББК 32.973.26-018.2 Г79 Г79 Голдштейн С., Зурбалев Д., Флатов И. и др. Оптимизация приложений на платформе .NET. – Пер. с англ. Киселев А. Н. – М.: ДМК Пресс, 2014. – 524 с.: ил. ISBN 978-5-94074-944-8 Увеличение производительности алгоритмов и приложений является чрезвычайно важным аспектом разработки и может дать вам преимущество перед конкурентами, а вашим пользователям обеспечить низкую стоимость владения и удовольствие от использования быстрых и отзывчивых приложений. Данная книга описывает внутренние особенности ОС Windows, среды выполнения CLR и аппаратного обеспечения, влияющие на производительность приложений, а также дает вам знания и инструменты для измерения производительности вашего кода в изоляции от внешних факторов. Книга наполнена примерами кода на C# и рекомендациями, которые помогут вам выжать максимум возможного из вашего приложения – низкое потребление памяти, согласованную нагрузку на процессор и минимальное количество операций ввода/вывода с сетью и диском. Издание предназначено для программистов, знакомых с языком C# и платформой .NET. УДК 004.438.NET ББК 32.973.26-018.2 Все права защищены. Любая часть этой книги не может быть воспроизведена в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Материал, изложенный в данной книге, многократно проверен. Но, поскольку вероятность технических ошибок все равно существует, издательство не может гарантировать абсолютную точность и правильность приводимых сведений. В связи с этим издательство не несет ответственности за возможные ошибки, связанные с использованием книги. ISBN 978-143-024-458-5 (англ.) © 2012 by Sasha Goldshtein, Dima Zurbalev, and Ido Flatow ISBN 978-5-94074-944-8 (рус.) © Оформление, перевод на русский язык, ДМК Пресс, 2014
Моей любимой жене Дине (Dina), наполнившей мою жизнь солнечным светом. Моим родителям, Борису (Boris) и Марине (Marina), жертвовавшим всем, чтобы я ни в чем не нуждался. – Саша Моей очаровательной жене Ефрат (Efrat), напомнившей мне, что муза не пропала – она просто играет в прятки. – Идo
ОГЛАВЛЕНИЕ Предисловие ............................................. 13 Об авторах ................................................ 16 О научных редакторах ................................. 18 Благодарности ........................................... 19 Введение .................................................. 20 ГЛАВА 1. Характеристики производительности ............ 23 Требования к производительности .......................................... 24 Характеристики производительности ...................................... 28 В заключение .......................................................................... 31 ГЛАВА 2. Измерение производительности ................... 32 Подходы к измерению производительности ............................ 32 Встроенные инструменты Windows .......................................... 33 Счетчики производительности ................................................. 34 Механизм трассировки событий для Windows .......................... 42 Профилировщики времени ...................................................... 58 Дискретный профилировщик Visual Studio ............................... 59 Инструментированный профилировщик Visual Studio ............... 64 Дополнительные приемы использования профилировщиков времени ................................................................................... 67 Профилировщики выделения памяти ...................................... 71 Профилировщик выделения памяти Visual Studio ..................... 72 CLR Profiler ............................................................................... 75 Профилировщики памяти ......................................................... 81 Другие профилировщики ........................................................ 86 Профилировщики доступа к данным и базам данных ............... 87 Профилировщики конкуренции ................................................ 88
Оглавление Профилировщики ввода/вывода .............................................. 91 Микрохронометраж ................................................................. 92 Пример неправильного микрохронометража ........................... 92 Рекомендации по проведению хронометража .......................... 96 В заключение .......................................................................... 99 ГЛАВА 3. Внутреннее устройство типов ..................... 102 Пример.................................................................................. 102 Семантические отличия между ссылочными типами и типами значений ................................................................. 104 Хранение, размещение и удаление ....................................... 105 Внутреннее устройство ссылочных типов .............................. 108 Таблица методов .................................................................... 109 Вызов методов экземпляров ссылочных типов ....................... 114 Блоки синхронизации и ключевое слово lock .......................... 122 Внутреннее устройство типов значений................................. 128 Ограничения типов значений ................................................. 130 Виртуальные методы типов значений ..................................... 132 Упаковка ................................................................................ 133 Предотвращение упаковки типов значений с помощью метода Equals ........................................................................ 136 Метод GetHashCode ............................................................... 140 Эффективные приемы использования типов значений .......... 144 В заключение ........................................................................ 144 ГЛАВА 4. Сборка мусора ......................................... 145 Назначение сборщика мусора ............................................... 146 Управление свободным списком ............................................ 146 Сборка мусора на основе подсчета ссылок ............................ 148 Сборка мусора на основе трассировки .................................. 150 Фаза маркировки ................................................................... 151 Фазы чистки и сжатия ............................................................ 158 Закрепление .......................................................................... 161 Разновидности сборщиков мусора ........................................ 163 Приостановка потоков для сборки мусора.............................. 163 Сборщик мусора для сервера ................................................ 170 Выбор разновидности сборщика мусора ................................ 172 Поколения ............................................................................. 175 Предположения в основе модели поколений .......................... 176 Реализация поколений в .NET ................................................ 177
Оглавление Куча больших объектов .......................................................... 183 Ссылки между поколениями ................................................... 185 Фоновый сборщик мусора...................................................... 188 Сегменты сборщика мусора и виртуальная память ................ 189 Финализация ......................................................................... 194 Детерминированная финализация вручную ........................... 194 Автоматическая недетерминированная финализация ............ 195 Ловушки недетерминированной финализации ....................... 198 Шаблон реализации метода Dispose ...................................... 202 Слабые ссылки ...................................................................... 205 Взаимодействие со сборщиком мусора ................................ 208 Класс System.GC ................................................................... 209 Взаимодействие с применением интерфейсов размещения CLR .................................................................... 213 Триггеры сборщика мусора .................................................... 215 Эффективные приемы повышения производительности сборки мусора ....................................................................... 216 Модель поколений ................................................................. 216 Закрепление .......................................................................... 218 Финализация ......................................................................... 219 Разные советы и рекомендации ............................................. 220 В заключение ........................................................................ 226 ГЛАВА 5. Коллекции и обобщенные типы ................... 230 Обобщенные типы ................................................................. 230 Обобщенные типы в .NET ....................................................... 234 Ограничения обобщенных типов ............................................ 236 Реализация обобщенных типов в CLR ..................................... 239 Коллекции ............................................................................. 249 Параллельные коллекции ....................................................... 252 Проблемы, связанные с кешем .............................................. 254 Собственные коллекции ........................................................ 261 Система непересекающихся множеств .................................. 261 Список с пропусками ............................................................. 263 Одноразовые коллекции ........................................................ 265 В заключение ........................................................................ 269 ГЛАВА 6. Конкуренция и параллелизм ....................... 270 Перспективы и преимущества ............................................... 270
Оглавление Зачем использовать приемы параллельного программирования? .............................................................. 272 От потоков к пулам потоков и задачам ................................... 273 Параллелизм задач ................................................................ 281 Параллелизм данных.............................................................. 290 Асинхронные методы в C# 5 ................................................... 295 Дополнительные шаблоны в TPL ............................................ 300 Синхронизация ...................................................................... 302 Код без блокировок ................................................................ 304 Механизмы синхронизации Windows ..................................... 311 Вопросы оптимального использования кеша ......................... 314 Использование GPU для вычислений ..................................... 318 Введение в C++ AMP .............................................................. 318 Умножение матриц ................................................................. 322 Моделирование движения частиц .......................................... 323 Мозаики и разделяемая память ............................................. 325 В заключение ........................................................................ 331 ГЛАВА 7. Сети, ввод/вывод и сериализация ............... 332 Общие понятия ...................................................................... 333 Синхронный и асинхронный ввод/вывод ................................ 333 Порты завершения ввода/вывода .......................................... 335 Пул потоков в .NET ................................................................ 340 Копирование памяти .............................................................. 341 Чтение вразброс и запись со слиянием ................................. 342 Файловый ввод/вывод ........................................................... 343 Управление кешированием .................................................... 343 Небуферизованный ввод/вывод ............................................. 344 Сети ...................................................................................... 345 Сетевые протоколы ................................................................ 346 Сетевые сокеты ..................................................................... 348 Сериализация и десериализация данных .............................. 351 Тестирование производительности средств сериализации .... 352 Сериализация объектов DataSet ............................................ 354 Windows Communication Foundation ....................................... 356 Пороговые значения .............................................................. 356 Модель обработки ................................................................. 357 Кеширование ......................................................................... 359 Асинхронные клиенты и серверы WCF ................................... 359 Привязки ................................................................................ 361 В заключение ........................................................................ 362
Оглавление ГЛАВА 8. Небезопасный код и взаимодействие с ним ... 364 Небезопасный код ................................................................. 365 Закрепление объектов в памяти и дескрипторы сборщика мусора ................................................................................... 366 Управление жизненным циклом ............................................. 368 Выделение неуправляемой памяти ........................................ 368 Использование пулов памяти ................................................. 368 P/Invoke ................................................................................. 370 PInvoke.net и P/Invoke Interop Assistant ................................... 372 Привязка ................................................................................ 374 Заглушки маршалера ............................................................. 375 Двоично совместимые типы ................................................... 380 Направление маршалинга, ссылочные типы и типы значений ................................................................................ 382 Code Access Security .............................................................. 383 Взаимодействие с COM-объектами ....................................... 384 Управление жизненным циклом ............................................. 386 Маршалинг через границы подразделений ............................ 386 Импортирование библиотек типов и Code Access Security ...... 389 NoPIA ..................................................................................... 390 Исключения ........................................................................... 391 Расширения языка C++/CLI ................................................... 392 Вспомогательная библиотека marshal_as ............................... 395 Код на языке IL и неуправляемый код ..................................... 397 Взаимодействие со средой выполнения WinRT в Windows 8 ... 397 Эффективные приемы взаимодействий ................................ 398 В заключение ........................................................................ 399 ГЛАВА 9. Оптимизация алгоритмов .......................... 400 Систематизация сложности ................................................... 401 Большое О ............................................................................. 401 Машины Тьюринга и классы сложности .................................. 403 Мемоизация и динамическое программирование ................. 409 Расстояние Левенштейна ....................................................... 411 Кратчайший путь между всеми парами вершин ...................... 413 Аппроксимация ..................................................................... 416 Задача коммивояжера ........................................................... 417 Задача о максимальном разрезе ............................................ 418 Вероятностные алгоритмы .................................................... 419 Вероятностное решение задачи о максимальном разрезе ..... 419
Оглавление Тест простоты Ферма ............................................................. 420 Индексирование и сжатие ..................................................... 421 Кодировка переменной длины ............................................... 421 Сжатие индексов .................................................................... 423 В заключение ........................................................................ 425 ГЛАВА 10. Шаблоны оптимизации производительности ...426 Оптимизации JIT-компилятора .............................................. 426 Стандартные оптимизации ..................................................... 427 Встраивание методов ............................................................ 428 Отключение проверки границ ................................................. 430 Хвостовые вызовы ................................................................. 432 Производительность на этапе запуска ................................... 436 Предварительная JIT-компиляция с помощью NGen (Native Image Generator) ................................................ 438 Фоновая JIT-компиляция в многопроцессорных системах ..... 441 Упаковщики образов .............................................................. 442 Управляемая оптимизация на основе профилирования ......... 443 Различные советы по оптимизации времени запуска ............. 445 Аппаратно-зависимые оптимизации ..................................... 447 Единственный поток команд и множество потоков данных ..... 448 Распараллеливание инструкций ............................................. 452 Исключения ........................................................................... 457 Механизм рефлексии ............................................................ 458 Генерация кода ...................................................................... 459 Генерация из исходного кода ................................................. 460 Генерация кода с использованием легковесного генератора кода ..................................................................... 462 В заключение ........................................................................ 467 ГЛАВА 11. Производительность веб-приложений ......... 468 Измерение производительности веб-приложений ................ 469 Тестирование производительности и нагрузочное тестирование веб-приложений в среде Visual Studio .............. 469 Инструменты мониторинга HTTP ............................................ 471 Инструменты анализа веб-взаимодействий ........................... 473 Увеличение производительности веб-сервера ...................... 473 Кеширование часто используемых объектов .......................... 474 Использование асинхронных страниц, модулей и контроллеров ...................................................................... 476
Оглавление Настройка окружения ASP.NET ............................................... 481 Отключение механизмов трассировки и отладки в ASP.NET .... 481 Отключение механизма ViewState .......................................... 483 Кеш вывода на стороне сервера............................................. 485 Предварительная компиляция приложений ASP.NET .............. 488 Тонкая настройка модели процесса в ASP.NET ....................... 488 Настройка IIS ......................................................................... 491 Кеширование вывода ............................................................. 491 Настройка пула приложения................................................... 493 Оптимизация сети ................................................................. 496 Включение HTTP-заголовков кеширования ............................ 496 Включение сжатия в IIS .......................................................... 501 Минификация и объединение ................................................ 504 Использование сетей доставки содержимого (CDN) .............. 507 Масштабирование приложений ASP.NET ............................... 509 Горизонтальное масштабирование ........................................ 510 Механизмы масштабирования в ASP.NET ............................... 511 Ловушки горизонтального масштабирования ......................... 512 В заключение ........................................................................ 513 Предметный указатель .............................. 514
ПРЕДИСЛОВИЕ Платформа Desktop .NET Framework недавно (в феврале 2012) отметила свое 10-летие. Я входил в состав команды с самого ее образования и больше половины этого времени занимался проблемами оптимизации платформы, поэтому 10-й день рождения навел меня на мысли о том, где была платформа .NET, куда она пришла, и какие направления в улучшении производительности можно считать «правильными». Возможность написать предисловие к книге, посвященной производительности приложений на платформе .NET, дала мне шанс изложить свои мысли. Продуктивность программиста всегда была и будет главной ценностью платформы .NET. Механизм сборки мусора является самой важной особенностью, обеспечивающей продуктивность. Но не только потому, что он устраняет целый класс ошибок (при работе с памятью), но и потому, что позволяет писать библиотеки классов, не загромождая их различными соглашениями о выделении ресурсов (требующими передавать временные буферы или устанавливающими правила о том, кто должен освобождать память). Еще одной важной особенностью является строгий контроль типов (которому теперь подчинены и обобщенные типы (Generics)), позволяющий выявлять намерения программиста и находить многие распространенные ошибки еще до запуска программы. Он также обеспечивает строгое соблюдение контрактов между программными компонентами, что очень важно для библиотек классов и больших проектов. Отсутствие контроля типов в таких языках как JavaScript всегда будет расцениваться как недостаток. Поверх этих двух особенностей мы создали библиотеку классов (весьма однородную, с простыми интерфейсами, непротиворечивыми соглашениями об именовании и так далее), простота использования которой была не последней целью. Я очень горжусь полученным результатом – мы создали систему, дающую возможность разрабатывать программный код с высочайшей продуктивностью. Однако, одной продуктивности программиста недостаточно, особенно для такой зрелой платформы, как среда выполнения .NET. Нам
Предисловие также необходима высочайшая производительность приложений, о чем и рассказывает данная книга. Как нельзя ожидать, что программа будет работать без ошибок с самого первого запуска, так же нельзя ожидать, что программа «просто так» начнет показывать высокую производительность. Существуют не только инструменты (сборщик мусора и контроль типов) и приемы (проверки, интерфейсы), снижающие вероятность появления программных ошибок, но и инструменты (различные профилировщики) и приемы (планирование, создание прототипов, отложенная инициализация), снижающие вероятность появления проблем с производительностью. Но все не так плохо – производительность приложений подчиняется правилу 90%/10%. Обычно более 90% программного кода не оказывает существенного влияния на производительность приложения в целом и может создаваться программистом с максимальной продуктивностью (в виде коротких строк простейшего кода). Однако другие 10% требуют пристального внимания. Для этого нужен план, и этот план должен быть составлен еще до того как код будет написан. Именно об этом рассказывается в главе 1. Для подобного планирования нужны исходные данные (сведения о скорости выполнения различных операций и библиотечных вызовов), а для этого необходимы инструменты измерения (профилировщики), о которых рассказывается в главе 2. И то, и другое является основой любого проекта высокопроизводительного программного обеспечения. Уделите этим главам особое внимание. Если вы примете их близко к сердцу, это поможет вам писать весьма эффективные программы. Остальная часть книги посвящена деталям, знание которых потребуется при составлении плана (главы 3, 4 и 5). Но они не заменят базовых знаний характеристик производительности используемой платформы. Если в ходе работы над прототипом выяснится, что простая и прямолинейная реализация не дает желаемой производительности, следует заняться усовершенствованием алгоритма (глава 9) или подумать о возможности включения параллельной обработки (глава 6), потому что они позволяют получить самый большой эффект. Если и после этого производительность оказывается неудовлетворительной, можно прибегнуть к некоторым хитростям .NET (глава 10). Если все вышеперечисленное не дало желаемого эффекта, остается только пожертвовать малой толикой продуктивности программиста и переписать наиболее критичные фрагменты приложения в виде небезопасного и неуправляемого кода (глава 8).
Предисловие Ключевым моментом, который я хотел бы подчеркнуть, является план (глава 1), потому что именно с него все начинается. В этом плане вы определите наиболее критичные участки программы и выделите дополнительное время на тщательное исследование прототипов этих участков. Затем, вооруженные результатами исследований прототипов и информацией из этой книги, вы без особого труда сможете добиться желаемой производительности. Иногда для этого достаточно будет просто избежать распространенных ловушек, а иногда – применив простейшие оптимизации. Реже вам может понадобиться организовать параллельную обработку данных или написать небезопасный, неуправляемый код. Как бы то ни было, в результате вы сможете поднять производительность 10% кода (потратив дополнительные усилия) и добиться высокой продуктивности, создавая остальные 90%. Это и есть главная цель платформы .NET: высокая продуктивность программиста и высокая производительность кода. Итак, помните, что высокая производительность не дается бесплатно – для ее достижения требуется составить план, но это не так сложно, и взяв в руки данную книгу вы уже сделали первый и самый важный шаг на пути к созданию высокопроизводительных приложений для .NET. Удачи, и получайте удовольствие от книги. Саша, Дима и Идо постарались для этого. Вэнс Моррисон (Vance Morrison) Архитектор производительности, .NET Runtime
ОБ АВТОРАХ Саша Голдштейн (Sasha Goldshtein) – наиболее ценный специалист (MVP) в Microsoft Visual C# и директор SELA Group. Руководит направлением производительности и отладки в SELA Technology Center, и консультирует по различным темам, включая подготовку приложений к промышленной эксплуатации, решение проблем производительности и создание распределенных архитектур. Наибольший опыт имеет в области разработки приложений на C# и C++, и создания архитектур масштабируемых и высокопроизводительных систем. Часто выступает на конференциях Microsoft и является автором множества курсов, таких как: «Производительность .NET», «Отладка приложений для .NET», «Внутреннее устройство Windows» и многих других. Блог: http://blog.sashag.net Twitter: @goldshtn Дима Зурбалев (Dima Zurbalev) – старший консультант в группе экстренной помощи по вопросам производительности и отладки в SELA Group. Владеет навыками оптимизации производительности и отладки, позволяющими ему решать почти неразрешимые проблемы своих клиентов. Обладает глубокими знаниями внутреннего устройства механизмов CLR и Windows. Большая часть его опыта лежит в плоскости разработки приложений для .NET и инфраструктуры проектов на C++. Является участником ряда открытых проектов на CodePlex. Блог: http://blogs.microsoft.co.il/blogs/dimaz
Идо Флатов (Ido Flatow) – наиболее ценный специалист (MVP) в Microsoft Connected Systems и старший архитектор в SELA Group. Обладает более чем 15-летним опытом и является одним из экспертов по Windows Azure и веб-технологиям в SELA. Специализируется на таких технологиях, как WCF, ASP.NET, Silverlight и IIS. Является сертифицированным преподавателем Microsoft, соавтор официального курса обучения Microsoft WCF 4.0 (10263A). Часто выступает на конференциях по всему миру. Блог: http://blogs.microsoft.co.il/blogs/idof Twitter: @IdoFlatow Об авторах
К покупке доступен более свежий выпуск
Перейти