-
-
Notifications
You must be signed in to change notification settings - Fork 49
Description
First of all, thank you for making these gems in the Async family. It's one of the most exciting developments in Ruby 3, in my opinion.
I've been working to replace threads, in several IO-heavy tasks, with Async. For example, downloading up to 500 images in parallel, and saving them to a tempfile:
Sync do |parent|
urls.each do |url|
parent.async { download_and_save(url) }
end
end
The threaded version of this took 0.7s with 500 threads (as an experiment), and 2.5s with 12 threads as we cap to limit resource usage in prod.
download_and_save
was written with Net::HTTP
. I almost went back to threads because the download time increased to 13s in the Async version. Still better than doing it serially (55s), but much slower than threads.
Finally, I updated download_and_save
to use Async::HTTP
, and it managed in ~0.6s, with the advantage of consuming less memory and avoiding context switching! I was sold.
This was surprising since I always assumed the Fiber scheduler would work about the same with any library that does IO: that it could capture most blocking operations and pass work to other fibers. But, it sounds like either Net::HTTP
has some blocking operations that can't be "seen" by the scheduler, or the HTTP2 aspect of Async::HTTP
is making up the difference.
Can you share any comment on this? It look me a while to even think of trying Async::HTTP
because I didn't know it would make such a difference.