Подтвердить что ты не робот

Является ли Haskell подходящим для долгосрочных приложений?

Я думаю, что Haskell - красивый язык, и, судя по бенчмаркам, его реализация может генерировать быстрый код.

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

Этот комментарий Reddit отражает мои проблемы:

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

(Вся эта дискуссия кажется проницательной и откровенной)

Я лично заинтересован в высокопроизводительных вычислениях, но, я думаю, серверы и HPC имеют это общее требование.

Если Haskell подходит для таких приложений, есть ли примеры, доказывающие этот момент, то есть приложения, которые

  • нужно запускать в течение нескольких дней или недель, поэтому требуется устранение всех соответствующих утечек (время, в течение которого программа проводит спящий режим или ожидает, что некоторая базовая библиотека C для возврата явно не учитывается)
  • являются нетривиальными (если приложение прост, разработчик может просто угадать источник утечки и попробовать различные исправления. Однако я не считаю, что этот подход хорошо масштабируется. Полезность профиля кучи при определении источник утечки (ов) с несколькими [взаимно] рекурсивными функциями, по-видимому, вызывает особую озабоченность, согласно обсуждению Reddit выше).

Если Haskell не подходит для таких приложений, то почему?

Обновление: Ядро веб-сервера Yesod для Haskell, которое было приведено в качестве примера, может иметь проблемы с памятью a > . Интересно, проверял ли кто-нибудь его использование памяти после непрерывного обслуживания запросов в течение нескольких дней.

4b9b3361

Ответ 1

"Пространственные утечки" семантически идентичны любой другой проблеме использования ресурсов на любом языке. В строгих языках GC имеет тенденцию выделять и удерживать слишком много данных (поскольку структуры строгие).

Независимо от того, на каком языке вы должны "сжигать", чтобы искать ресурс с течением времени, а Haskell ничем не отличается.

См. xmonad, который работает месяцами или годами одновременно. Это приложение Haskell, имеет крошечное использование кучи, и я тестировал его, работая в течение недель или месяцев с профилированием, чтобы анализировать шаблоны кучи. Это дает мне уверенность в том, что использование ресурсов является стабильным.

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

Ответ 2

Веб-сервер Warp доказывает, что Haskell подходит для долгосрочных приложений.

Когда приложения Haskell имеют утечки пространства, может быть трудно отследить причину, но как только причина известна, она обычно тривиальна для решения (самым сложным решением, которое я когда-либо использовал, было применение zip [1..] к list и получить длину от последнего элемента вместо функции length). Но утечки пространства на самом деле очень редки в программах Haskell. Обычно сложнее сознательно создавать утечку пространства, чем исправить случайную ситуацию.

Ответ 3

Самые длительные приложения - это управляемые запросы. Например, HTTP-серверы связывают все временные данные с HTTP-запросом. По завершении запроса данные удаляются. Поэтому, по крайней мере, для тех видов приложений, которые работают в течение длительного времени, любой язык не будет иметь утечек пространства. Утечка всего, что вы хотите, в контексте одного запроса. Пока вы не создаете глобальные ссылки на данные для каждого запроса, вы не будете течь.

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

Ответ 4

Это. Существует 2 вида возможных утечек пространства:

Данные о куче. Здесь ситуация ничем не отличается от других языков, использующих GC. (И для тех, у которых ситуация обычно не хуже, - если есть ошибка, вместо увеличения использования памяти процесс может затронуть освобожденную память или наоборот и просто сбой плохо.)

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

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

И если у вас есть служба, ее состояние обычно хорошо сложен, поэтому легко убедиться, что он всегда оценивается в конце запроса. Фактически, Haskell делает это проще по сравнению с другими языками: в Haskell у вас не может быть компонентов вашей программы, сохраняющих собственное внутреннее состояние. Глобальное состояние приложения либо передается в виде аргументов в каком-либо основном цикле, либо сохраняется с помощью IO. И поскольку хороший дизайн приложения Haskell ограничивает и локализует IO как можно больше, он снова позволяет легко управлять состоянием.


В качестве другого примера проект Ganeti (из которого я являюсь разработчиком) использует несколько длинных демонов Haskell.

Из нашего опыта утечки памяти были очень редки, если у нас были проблемы, обычно это было с другими ресурсами (такими как дескрипторы файлов). Единственным недавним случаем, о котором я помню, был демон мониторинга, который утечка памяти в виде трюков в редком случае, когда он собирал данные, но никто не смотрел на них (что заставило бы их оценивать). Исправление было довольно простым.

Ответ 5

У меня есть служба, написанная в haskell, которая работает в течение нескольких месяцев без какой-либо проблемы, связанной с haskell. Был период, когда он работал 6 месяцев без какого-либо внимания, но затем я перезапустил его, чтобы обновить его. Он содержит API-интерфейс без состояния HTTP, но также имеет полноценный интерфейс websockets, поэтому он поддерживает долгое состояние жизни. Его источники закрыты, поэтому я не могу предоставить ссылку, но мой опыт haskell отлично подходит для долгосрочных приложений.

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

Кроме того, библиотеки хакера имеют разное качество, а контроль над зависимостями - важная вещь. Я стараюсь избегать зависимостей, если они действительно не нужны, и я проверяю большую часть своего кода (за исключением ряда широко используемых пакетов, большинство из них либо являются основными библиотеками, либо частью платформы Haskell, хотя я также проверяю их код) изучать новые вещи.)

Хотя существуют угловые случаи, когда GHC (наиболее широко используемая реализация) работает недостаточно эффективно. У меня были проблемы с временем GC, когда приложение поддерживает огромное (в основном, только для чтения) состояние в памяти (есть ticket.) Также много стабильных указателей может быть проблематичным (ticket, хотя я никогда не испытывал этого сам.) В большинстве случаев такие угловые случаи легко избегайте осторожного проектирования.

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