Выбрать главу

мую, без создания промежуточного кортежа в куче. В этом случае значения будут сохранены в регистрах

или на стеке. Для использования специальных значений необходимо активировать расширения MagicHash и

UnboxedTuples

Разработчики различных библиотек могут предоставлять несколько вариантов своих данных: ленивые

версии и незапакованные. Например в ST-массив незапакованных значений STUArray s i a эквивалентен

массиву значений в C. В таком массиве можно хранить лишь примитивные типы.

10.8 Краткое содержание

Эта глава была посвящена компилятору GHC. Мы говорим Haskell подразумеваем GHC, говорим GHC

подразумеваем Haskell. К сожалению на данный момент у этого компилятора нет достойных конкурентов.

А может и к счастью, ведь если бы не было GHC, у нас была бы бурная конкуренция среди компиляторов

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

по скорости с С. И мы бы говорили: ну декларативное программирование, что поделаешь, за радость аб-

стракций приходится платить. Но есть GHC! Всё-таки это очень трудно: написать компилятор для ленивого

языка

Отметим другие компиляторы: Hugs разработан Марком Джонсом (написан на C), nhc98 основанный

Николасом Райомо (Niklas Röjemo) этот компилятор задумывался как легковесный и простой в установке, он

разрабатывался при поддержке NUTEK, Йоркского университета и Технического университета Чалмерса. От

этого компилятора отпочковался YHC, Йоркский компилятор. UHC – компилятор Утрехтского университета,

разработан для тестирования интересных идей в теории типов. JHC (Джон Мичэм, John Meacham) и LHC

(Дэвид Химмельступ и Остин Сипп, David Himmelstrup, Austin Seipp) компиляторы предназначенные для

проведения более сложных оптимизаций программ с помощью преобразований дерева программы.

В этой главе мы узнали как вычисляются программы в GHC. Мы узнали об этапах компиляции. Снача-

ла проводится синтаксический анализ программы и проверка типов, затем код Haskell переводится на язык

Core. Это сильно урезанная версия Haskell. После этого проводятся оптимизации, которые преобразуют де-

рево программы. На последнем этапе Core переводится на ещё более низкоуровневый, но всё ещё функцио-

нальный язык STG, который превращается в низкоуровневый код и исполняется вычислителем. Посмотреть

на текст вашей программы в Core и STG можно с помощью флагов ddump-simpl ddump-stg при этом лучше

воспользоваться флагом ddump-suppress-all для пропуска многочисленных деталей. Хардкорные разработ-

чики Haskell смотрят Core для того чтобы понять насколько строгой оказалась та или иная функция, как

аргументы размещаются в памяти. Но это уже высший пилотаж искусства оптимизации на Haskell.

Мы узнали о том как работает сборщик мусора и научились просматривать разные параметры работы

программы. У нас появилось несколько критериев оценки производительности программ: минимум глубоких

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

и посмотрели как разные типы профилирования могут подсказать нам в каком месте затаилась ошибка.

Отметим, что не стоит в каждой медленной программе искать утечку памяти. Так в примере concat у нас не

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

узнали какой.

Также мы познакомились с новыми прагмами оптимизации программ. Это встраиваемые функции INLINE,

правила преобразования выражений RULE и встраиваемые конструкторы UNPACK. Разработчики GHC отмеча-

ют, что грамотное использование прагмы INLINE может существенно повысить скорость программы. Если

мы встраиваем функцию, которая используется очень часто, нам не нужно создавать лишних отложенных

вычислений при её вызовах.

178 | Глава 10: Реализация Haskell в GHC

Надеюсь, что содержание этой главы упростит понимание программ. Как они вычисляются, куда идёт

память, почему она висит в куче. При оптимизации программ предпочитайте изменение алгоритма перед

настройкой параметров компилятора под плохой алгоритм. Вспомните самый первый пример, увеличением

памяти под сборку мусора нам удалось вытянуть ленивую версию sum, но ведь строгая версия требовала в

100 раз меньше памяти, причём её запросы не зависели от величины списка. Если бы мы остановились на

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