Какой из них я должен использовать в Clojure?идти блок или поток? - PullRequest
3 голосов
/ 27 марта 2019

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

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

В моем случае, есть входной поток, который получает значения откуда-то, и значение берется как вход.Некоторые вычисления выполняются, и результат вставляется в канал результатов.Короче говоря, у нас есть входной и выходной канал, и расчет выполняется в цикле.Чтобы достичь параллелизма, у меня есть два варианта: либо использовать go-block, либо использовать thread.

Интересно, в чем разница между этими двумя?(Мы можем предположить, что во время вычислений ввода-вывода нет.) Пример кода выглядит следующим образом:

(go-loop []
  (when-let [input (<! input-stream)]

  ... ; calculations here

  (>! result-chan result))
  (recur))

(thread
  (loop []
    (when-let [input (<!! input-stream)]

    ...  ; calculations here

    (put! result-chan result))
    (recur)))

Я понимаю, что количество потоков, которые могут быть запущены одновременно, точно соответствует количеству ядер ЦП.,Тогда в этом случае, go-block и thread не показывают различий, если я создаю более 8 thread или go-блоков?

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

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

Другое соображение заключается в том, повлияет ли go-block на thread на производительность GC.

1 Ответ

0 голосов
/ 19 мая 2019

Здесь следует отметить несколько моментов.

Во-первых, пул потоков, в котором создаются потоки с помощью clojure.core.async / thread, называется так называемым кэшированным пулом потоков, то есть, хотя он будет-использовать недавно использованные потоки внутри этого пула, он по сути неограничен.Что, конечно, означает, что он может потенциально потреблять много системных ресурсов, если его не проверять.

Но, учитывая, что то, что вы делаете внутри каждого асинхронного процесса, очень легкое, потоки для меня кажутся немного излишними.Конечно, также важно учитывать количество элементов, которые вы ожидаете получить во входном потоке, если это число велико, вы можете переполнить пул потоков core.async для макросов go, потенциально до точки, в которой мы ожидаемпоток, который станет доступным.

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

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

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

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