Какие библиотеки Haskell лучше всего подходят для реализации программы? [закрыто]

115

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

  • Уметь вести журнал на нескольких уровнях (например, отладка, предупреждение и т. Д.).
  • Уметь собирать и обмениваться метриками / статистикой о типах работы, которую выполняет программа, и о том, сколько времени она занимает. В идеале собранные метрики доступны в формате, совместимом с широко используемыми инструментами мониторинга, такими как Ganglia , или могут быть изменены.
  • Быть настраиваемым, в идеале через систему, которая позволяет обновлять настроенные свойства в запущенных программах без перезапуска указанных программ.
  • Возможность повторного развертывания на удаленных серверах.

В мире Scala есть хорошие библиотеки для выполнения хотя бы первых трех требований. Примеры:

Что касается развертывания, один из подходов, принятых в мире Scala, состоит в том, чтобы связать вместе байт-код и библиотеки, составляющие вашу программу, с чем-то вроде assembly-sbt , а затем отправить полученный пакет («толстый JAR») на удаленные серверы с помощью такого инструмента, как Capistrano. который выполняет команды параллельно через SSH. Это не проблема, для решения которой требуются инструменты, специфичные для языка, но мне любопытно, существует ли такой инструмент в сообществе Haskell.

Вероятно, существуют библиотеки Haskell, которые предоставляют свойства, которые я описал выше. Я хотел бы знать, какие из доступных библиотек считаются «лучшими»; то есть наиболее зрелые, хорошо поддерживаемые, обычно используемые в сообществе Haskell и являющиеся образцом лучших практик Haskell.

Если есть какие-либо другие библиотеки, инструменты или методы, позволяющие сделать код Haskell «готовым к производству», я бы тоже хотел узнать о них.

Алекс Пейн
источник
1
Четвертый пункт может вызвать проблемы, так как Haskell скомпилирован как родной. Вы можете попробовать скомпилировать статически, что может работать или не работать, но оптимально у вас должна быть аналогичная среда на производственном сервере, чем на сервере разработки. Cabal-dev - это изолированная среда, которая может быть подходящей для переноса на другие машины. Даже в этом случае на целевой машине потребуется установить хотя бы базовые библиотеки.
Masse
1
Что касается других инструментов и методов, этот вопрос SO имеет обзор: stackoverflow.com/questions/3077866/…
Дон Стюарт
1
Еще одна вещь - в системах * nix вы можете получить доступ к огромному количеству статистики процессов и метаданных непосредственно через файловую систему / proc. Так что если вы напишете несколько подпрограмм для самоанализа, это поможет восполнить отсутствие прямых перехватчиков во время выполнения.
sclv
1
развернуть двоичный файл легко, если вы используете одну и ту же среду (у вас должен быть промежуточный сервер, если ваш компьютер имеет другую архитектуру). Затем вы можете выполнить синхронизацию двоичного файла и любых внешних файлов. Для haskell нет библиотеки ssh для автоматического выполнения команд перезапуска, но вы можете использовать capistrano.
Грег Вебер,
1
@tchrist Он проводит оставшуюся часть первого абзаца и маркированного списка сразу после слова операционализированный, объясняя его значение на простом английском языке.
Will McCutchen

Ответы:

54

Это большой вопрос! Вот первый вариант.

Уметь вести журнал на нескольких уровнях (например, отладка, предупреждение и т. Д.).

hslogger - самая популярная платформа для ведения журналов.

Уметь собирать и обмениваться метриками / статистикой о типах работы, которую выполняет программа, и о том, сколько времени она занимает. В идеале собранные метрики доступны в формате, совместимом с широко используемыми инструментами мониторинга, такими как Ganglia, или могут быть изменены.

Мне не известны какие-либо стандартизированные инструменты отчетности, однако извлечение отчетов из +RTS -sпотоков (или с помощью флагов вывода профилирования) было чем-то, что я делал в прошлом.

$ ./A +RTS -s
64,952 bytes allocated in the heap
1 MB total memory in use
 %GC time       0.0%  (6.1% elapsed)
 Productivity 100.0% of total user, 0.0% of total elapsed

Вы также можете получить это в машиночитаемом формате:

$ ./A +RTS -t --machine-readable

 [("bytes allocated", "64952")
 ,("num_GCs", "1")
 ,("average_bytes_used", "43784")
 ,("max_bytes_used", "43784")
 ,("num_byte_usage_samples", "1")
 ,("peak_megabytes_allocated", "1")
 ,("init_cpu_seconds", "0.00")
 ,("init_wall_seconds", "0.00")
 ,("mutator_cpu_seconds", "0.00")
 ,("mutator_wall_seconds", "0.00")
 ,("GC_cpu_seconds", "0.00")
 ,("GC_wall_seconds", "0.00")
 ]

В идеале вы могли бы подключиться к работающей среде выполнения GHC через сокет и просматривать эту статистику сборщика мусора в интерактивном режиме, но в настоящее время это непросто (требуется привязка FFI к интерфейсу «rts / Stats.h»). Вы можете подключиться к процессу, используя ThreadScopeсборщик мусора и потоковое поведение, и отслеживать их.

Аналогичные флаги доступны для инкрементного, регистрируемого профилирования времени и пространства , которое можно использовать для мониторинга (например, эти графики могут быть построены инкрементально).

hpcсобирает много статистических данных о выполнении программы по ее Tixтипу, и люди написали инструменты для регистрации выполняемого кода по временному интервалу.

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

Для этого доступно несколько инструментов, вы можете выполнить перезагрузку состояния в стиле xmonad; или перейти на горячую замену кода через plugins* packages или hint. Некоторые из них более экспериментальны, чем другие.

Воспроизводимые развертывания

Недавно Галуа выпустил cabal-devинструмент для создания воспроизводимых сборок (т. Е. Зависимости ограничены и контролируются).

Дон Стюарт
источник
6
Предполагается, что пакет dyre абстрагируется от перезагрузки состояния в стиле xmonad, поэтому, я думаю, следует упомянуть об этом особенно. Однако он связывает воедино перекомпиляцию и повторное развертывание, так что на самом деле речь идет об изменениях на машине со всей цепочкой инструментов. Для удаленного повторного развертывания вам нужно что-то более похожее на кислотное, хотя на мой вкус это немного тяжеловесно. У меня есть эта постоянная абстракция mvar, которая имеет более слабые гарантии, но которую вы можете рассматривать как простой MVar, который волшебным образом заполняется при каждом запуске двоичного файла с последними данными, которые он хранит.
sclv
2
Кроме того, новая EventLogструктура ведения журнала GHC (использующаяся +RTS -lво время выполнения) передает потоки вывода в файл, который можно визуализировать с помощью любого инструмента, считывающего формат журнала событий.
Дон Стюарт
2
Программа будет создавать журналы своих событий, например: galois.com/~dons/tmp/A.event.log, которые можно представить как - i.imgur.com/QAe6r.png . Я мог бы представить себе создание других инструментов мониторинга поверх этого формата.
Дон Стюарт
2
Также обратите внимание, что многие инструменты профилирования отлично подходят для тестирования, но не для производственного кода. Не говоря уже о накладных расходах, -prof, например, можно использовать только с одним процессором.
sclv
9
  • Что касается конфигурации, я обнаружил, что ConfigFile полезен для моих проектов. Я использую его для всех своих демонов в продакшене. Он не обновляется автоматически.
  • Я использую cabal-dev для создания воспроизводимых сборок в разных средах (локальных, разработчиков, локальных коллег). На самом деле cabal-dev незаменим, особенно из-за его способности поддерживать локальные исправленные версии библиотек в каталоге проекта.
  • Как бы то ни было, я бы выбрал перезагрузку состояния в стиле xmonad. Чистота Haskell делает это тривиальным; миграция - это проблема, но это все равно. Я экспериментировал с hsplugins и hint для моего IRCd, и в первом случае возникла проблема времени выполнения GHC, а во втором - ошибка сегментации. Я оставил ветки на Github для последующего вскрытия: https://github.com/chrisdone/hulk

Пример ConfigFile:

# Default options
[DEFAULT]
hostname: localhost
# Options for the first file
[file1]
location: /usr/local
user: Fred
Кристофер Сделано
источник
9

Я бы повторил все, что сказал Дон, и добавил несколько общих советов.

Например, вы можете рассмотреть два дополнительных инструмента и библиотеки:

  • QuickCheck для тестирования на основе свойств
  • hlint как расширенная версия-Wall

Оба они ориентированы на качество кода.

В качестве практики кодирования избегайте ленивого ввода-вывода. Если вам нужен потоковый ввод-вывод, воспользуйтесь одной из итерационных библиотек, например enumerator . Если вы посмотрите Hackage, вы увидите библиотеки, такие как http-enumerator, которые используют стиль перечислителя для HTTP-запросов.

Что касается выбора библиотек при взломе, иногда может помочь посмотреть, сколько пакетов от чего-то зависит. Легко увидеть обратные зависимости пакета, который вы можете использовать на этом веб-сайте, который отражает взлом:

Если ваше приложение в конечном итоге выполняет жесткие циклы, например, веб-сервер, обрабатывающий множество запросов, лень может стать проблемой в виде утечки пространства. Часто это вопрос добавления аннотаций строгости в нужных местах. Профилирование, опыт и ядро ​​чтения - вот основные методы, которые я знаю для борьбы с подобными вещами. Лучший справочник профилирования я знаю, это глава 25 из Real-World Haskell .

Джейсон Дагит
источник