Подходит ли OCaml для написания сетевых серверов? - PullRequest
12 голосов
/ 14 июля 2010

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

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

Заранее спасибо

Ответы [ 5 ]

10 голосов
/ 14 июля 2010

Производительность: , вероятно, нет. Потоки OCaml не обеспечивают параллельное выполнение, они только способ структурировать вашу программу. Сама среда выполнения OCaml не является поточно-ориентированной, поэтому единственным кодом, который мог бы выполняться параллельно одному потоку OCaml, был бы интерфейсный код C (без обратных вызовов к OCaml!).

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

Простота реализации: это не изменит мир. У вас будет комфорт OCaml и pthread-подобная библиотека на стороне. Если вы ищете что-то новое, используя то, что вы узнали об OCaml, я рекомендую Jocaml . Он входит и не синхронизируется с OCaml, но была (ре) повторная реализация совсем недавно, и даже когда он немного не синхронизирован, это очень весело, и это совершенно новый взгляд на параллельные программы.

Jocaml реализован поверх OCaml. Что во время выполнения не является одновременным и все, я почти уверен, что он использует отдельные процессы и передачу сообщений. Но для приложения, которое вы упомянули, оно должно нормально работать.

9 голосов
/ 15 июля 2010

OCaml вполне подходит для написания сетевых серверов, хотя, как отмечает Паскаль, существуют ограничения на многопоточность.

Однако, к счастью, многопоточность - не единственный способ организовать такую ​​программу.Библиотека Lwt (для облегченных потоков) предоставляет абстракцию асинхронного ввода-вывода, которая довольно проста в использовании (особенно в сочетании с небольшой поддержкой синтаксиса).На самом деле все выполняется в одном потоке, но все это выполняется асинхронным циклом ввода-вывода (построенным на вызове Unix select), а стиль программирования позволяет писать код, который выглядит как прямой код (избегая значительной части обычных накладных расходов кодаделать асинхронный ввод-вывод во многих других языках).Например:

lwt my_message = read_message socket in
let repsonse = compute_response my_message in
send_response socket response

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

2 голосов
/ 24 июля 2018

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

Вы говорите «действительно типично, как наличие потока на клиента», но наличие потока ОС на клиента - это крайне плохой дизайн . Потоки имеют большой вес, занимают много времени на создание и уничтожение и занимают ~ 1 МБ только для стека потоков. Если у вас есть один поток на соединение, то 1000 одновременных клиентских подключений (что вполне возможно) сожгут 1 ГБ ОЗУ только для их стеков, а производительность вашей программы (на любом языке) будет ограничена количеством переключений контекста, необходимых для получения любая работа сделана. Вы не хотите использовать этот дизайн на любом языке, включая C и OCaml. Обратите внимание, что эта проблема особенно остра в контексте отслеживания языков, собираемых мусором, поскольку GC также пересекает все эти потоки, чтобы сопоставлять глобальные корни перед каждым циклом GC. Я первый, кто признает, что этот анти-паттерн вездесущ в реальном мире, но, пожалуйста, не копируйте его! Я видел серверы с низкой задержкой в ​​финансовой отрасли, написанные на C ++ с использованием одного потока на соединение, и они терпели задержки до шести секунд только из-за (Windows) ОС, обслуживающей эти потоки.

См .: http://people.eecs.berkeley.edu/~sangjin/2012/12/21/epoll-vs-kqueue.html

Давайте вместо этого рассмотрим эффективный дизайн, такой как интерфейс epoll или kqueue к ядру ОС, предоставляющий код сервера информацию о буферах входящих и исходящих данных. Однопоточные серверы могут достичь превосходной производительности с такой конструкцией. Тем не менее, типичный сервер выполняет сериализацию для каждого клиента и некоторую базовую работу, которая часто выполняется последовательно для всех клиентских подключений. Следовательно, сериализация и десериализация могут быть распараллелены, но работа главного сервера невозможна. В этом контексте OCaml отлично подходит для всего, кроме уровня сериализации, поскольку он плохо поддерживает параллелизм.

Я лично внедрил множество серверов для различных отраслей промышленности с очень разными требованиями к производительности. По моему опыту, OCaml является одним из лучших инструментов для этого, потому что он предлагает отличные библиотеки (простые в использовании и надежные) и отличную производительность последовательного порта. Единственная проблема, которую я имею, связана с распараллеливанием уровня сериализации, но на практике я обнаружил, что OCaml работает вокруг альтернатив, таких как Java и .NET, даже если они могут распараллелить это. Я обнаружил, что типичные задержки составляли ~ 100 мкс для .NET и 10 мкс для OCaml.

Смотри также: http://prl.ccs.neu.edu/blog/2016/05/24/measuring-gc-latencies-in-haskell-ocaml-racket/

2 голосов
/ 14 июля 2010

OCaml будет отлично работать для сетевых приложений, если вы можете жить с относительно небольшим количеством активных потоков одновременно - скажем, не более 100. Вы можете рассмотреть MLdonkey в качестве примера, хотя в пространстве клиента, а не в пространство сервера.

0 голосов
/ 22 января 2016

Haskell будет лучшим выбором, если вы хотите использовать много вытесняющих потоков. GHC может поддерживать огромное количество потоков, и они работают параллельно в многоядерных системах. OCaml предпочитает совместную многопоточность и несколько процессов.

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