Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 Контент вільний від AI. Цей пост на 100% написаний людиною, як і все на моєму блозі. Насолоджуйтесь!

27.03.2023

Паралелізація запитів в Ruby

Хочу висловити похвалу моделі одночасного виконання в Ruby, а саме, класу Thread. Ruby так зневажливо відносять до повільних мов, що яка вже там одночасність! Тут же ж навіть багатопотоковості немає. (До речі, справжня багатоядерна паралелізація в Ruby 3 теж вже є, з класом Ractor).

Насправді є сценарій, в якому одночасне виконання дуже допомагає, та він всім нам добре відомий — це звертання до мережевих ресурсів. Будь то запити до API, чи завантаження сторінок, чи надсилання листів по SMTP - всілякі операції через Інтернет можна робити паралельно в декількох потоках, бо під час запиту програма все одно стоїть та чекає відповіді. (Єдине, що треба мати на увазі — не робіть з потоків звертань до бази даних, бо це вичерпає пул підключень. Або пул треба збільшити, або роботу з базою винести з потоку.)

# Паралельне завантаження сторінок
urls.map { |url| Thread.new { Net::HTTP.get(url) } }.map(&:join)

Так на минулому тижні мені вдалося замінити процес, що займав дві години, та опитував кожний ресурс послідовно, на паралелізоване рішення, якому потрібно двадцять хвилин. І це мені поки боязно робити надто багато запитів — можливо, в майбутньому зробимо ще швидше.

Для більш поглибленого використання можливостей одночасності можу порадити гем concurrent-ruby. В ньому реалізовані класи для всього, що можна собі уявити. Я, наприклад. завжди маю на увазі пул тредів для обмеженої паралелізації.