Concurrency in Crystal (lang)
Crystal intentionally looks similar to Ruby. However, Crystal is a static typing programming language. A Thai word segmentation program written in Crystal, which is a CPU bound program, was found almost as fast as one written in Go.
I wondered whether its concurrency support was like what I expected. So I did this experiment. By spawning, Crystal did not create any new thread because it doesn't support multithreading parallelism yet. To support concurrency, Crystal has to be able to switch fibers when a fiber performs non-blocking IO operation.
require "socket"
def load(id, chan)
puts "ID=#{id}; START"
(id..11).each do
socket = TCPSocket.new("www.ku.ac.th", 80)
socket.close
end
puts "ID=#{id}; FINISH"
chan.send nil
end
def main
chan = Channel(Nil).new
(1..10).each{|i| spawn(load(i,chan))}
# Wait
(1..10).each{chan.receive}
end
main
In this program, a task with the id with a smaller number creates a TCP socket repeatedly more times than a task with a larger number id. For example task#1 establishes a TCP socket for 11 times and task#10 create a TCP socket for one time only. So even task#1 started long before task#10, task#10 should finish before task#1.
ID=1; START
ID=2; START
ID=3; START
ID=4; START
ID=5; START
ID=6; START
ID=7; START
ID=8; START
ID=9; START
ID=10; START
ID=10; FINISH
ID=9; FINISH
ID=8; FINISH
ID=7; FINISH
ID=6; FINISH
ID=5; FINISH
ID=4; FINISH
ID=3; FINISH
ID=2; FINISH
ID=1; FINISH
The result was that task#1 finished after task#10 although task#1 started before task#10, show that Crystal can switch tasks. And the important thing is the code looks like regular Ruby code, without async-await nor promise nor callback.