📋 Параллелизм или расписание в Crystal
Выполнять код раз в 10 секунд?
Обычная задача в буднях говнокодера.
Про параллелизм в Crystal есть хорошая статья Concurrency vs. Parallelism.
В целом если её прочитать, то необходимость в прочтении этого руководства отпадает полностью.
Ничего нового ты здесь не узнаешь, однако я продолжу…
Глубокий сон
sleep —
Top Level метод, который блокирует текущий fiber
*
* Fiber — это исполняемый блок кода, управляемый райнтаймом Crystal.
Концептуально Fiber похож на поток (thread), но с меньшими затратами и полностью внутренне связан с процессом Crystal.
Рантайм включает планировщик, который очевидно планирует выполнение волокон.
Связь между волокнами обычно осуществляется через Channel.
Цикличное выполнение
Для реализации цикла в Crystal можно использовать оператор while
:
while p! "╭∩╮(Ο_Ο)╭∩╮".class
end
Или даже оператор loop
:
loop do
p! "╭∩╮(Ο_Ο)╭∩╮".class
end
А если запихонить в цикл метод sleep
, то получим уже имитацию выполнения блока кода
по расписанию:
loop do
p! "╭∩╮(Ο_Ο)╭∩╮".class
sleep 2
end
Но ты же наблюдательный и понял, что пока один loop/while не закончит выполнение, второй цикл не запустится.
Вот для таких случаем и нужны Fiber или волокна, просто меня, но я буду называть их Файберами
.
Файберы
Попробуй запустить этот пример и посмотри что получится.
spawn do
loop do
p! "╭∩╮(Ο_Ο)╭∩╮".class
end
end
spawn do
loop do
puts Time.local.to_unix
end
end
sleep
Тут я создал два файбера, в которых циклично выполняется некий код,
а главный процесс программы я зациклил методом sleep
.
Удивительно, не правда ли?)
Запихониваем в циклы sleep
и получаем выполнение каждого файбера с разным интервалом.
wrapper
Всё эту простыню можно оформить таким образом:
def every(period : Time::Span, &block : -> T) forall T
spawn do
loop do
block.call
sleep period
end
end
end
every(2.seconds) {
puts "-@-@-"
}
every(4.seconds) {
puts "(-.-)Zzz..."
}
sleep
Жрёт это всё ~2Mb памяти.