This is fantastic, I love when people show the code for comparison. It really highlights the differences in ergonomics between the languages. I did the same when comparing Crystal to Rust and, even though the ergonomics weren’t the point of that post, people still mentioned it a lot. :-D
One of the Disqus comments makes a good point, though: have you tried running the Crystal code with --release and CRYSTAL_WORKERS environment variable set to the number of CPU cores on your machine (defaults to 4)? That may or may not make it fast enough to outperform the Go code (seriously, it might!), but even if it doesn’t it’ll likely be a lot closer than without it.
Thanks for kind words And thanks for pointing out the compiler flags etc. Yes, for performance comparison, I’ve been using those. Updated the post now, to clarify that, should have done it from the start for sure.
That is a very interesting post comparing with Rust as well! Didn’t expect Crystal to win out against Rust Maybe gives me more excuses for not need to take the effort to learn Rust, haha.
I don’t think Crystal can beat Go here. I suspect a lot of time is spent in the runtime, sending stuff through channels, doing context switches, etc. Go is really optimized for that stuff, at the register level.
Out of curiosity: why are two fibers or goroutines even needed here? Reading from a file will never block so you can just read from it and parse it as you go. I guess it’s just to demonstrate the usage of fibers and channels?
Exactly. Although I have been playing a lot with the idea of a very simple flow-based programming framework with re-usable pluggable components for common tasks, and for this, a general file-reader component does make sense [1] … although it would have a little more structure around it than in the example above, such as an object with the output channel stored in a field.