Sobes.tech
Middle+

როგორ ხორციელდება Ruby-ში წინასწარი მრავალრიცხოვანობა?

sobes.tech AI

პასუხი AI-სგან

წმინდა Ruby (MRI, JRuby, TruffleRuby) არ აქვს რეალური გამწევი მრავალრეწველობა ერთ პროცესში კოდის პარალელურად შესრულებისთვის, რადგან Global Interpreter Lock (GIL)-ი საშუალებას აძლევს მხოლოდ ერთ თრედს Ruby კოდის შესრულებას ნებისმიერ დროს:

თუმცა, გამწევი მრავალრეწველობა Ruby-ში არსებობს შეტანილი ინტერფეისის დონეზე. როდესაც თრედი ახორციელებს ბლოკირებადი შეტანილ-გამოტანილ ოპერაციას (მაგალითად, ფაილის წაკითხვა, ქსელის მოთხოვნა), GIL-ი გათავისუფლდება, რაც საშუალებას აძლევს სხვა თრედს Ruby კოდის შესრულებას. ეს საშუალებას აძლევს მიაღწიოს პარალელიზმს შეტანილ-გამოტანილ ოპერაციებისთვის, მაგრამ არა CPU-ზედ მორგებულ ამოცანებისთვის:

არსებობს ალტერნატიული Ruby რეალიზაციები (მაგალითად, Rubinius), რომლებიც ცდილობდნენ რეალური გამწევი მრავალრეწველობის განხორციელებას GIL- გარეშე, მაგრამ ისინი არ მიიღეს ისეთი ფართო გავრცელება, როგორც MRI:

პარალელურად CPU-ზედ მორგებული ამოცანების შესასრულებლად Ruby-ში ჩვეულებრივ გამოიყენება:

  • პროცესები (fork) — თითოეულ პროცესს აქვს თავისი GIL, რაც საშუალებას აძლევს Ruby კოდის პარალელურად შესრულებას. მონაცემთა გაცვლა პროცესებს შორის მოითხოვს სპეციალურ მექანიზმებს (IPC).
  • გარე ბიბლიოთეკები და C გაფართოებები — C ენაზე განხორციელებული ოპერაციები შეიძლება შესრულდეს GIL-ის კონტროლიდან გარეთ, უზრუნველყოფს პარალელურ შესრულებას:

Ruby 3.0-ში შემოვიდა Fibers Scheduler, რომელიც საშუალებას აძლევს ასინქრონულად შეასრულოს შეტანილ-გამოტანილ ოპერაციები, გამოყენებით ფიბერებს და არაბლოკიან ზარებს. ეს აუმჯობესებს I/O-ზედ მორგებული ამოცანების შესრულებას, მაგრამ არ აქცევს CPU-ზედ მორგებულ ამოცანებს რეალურად პარალელურ ერთ პროცესში:

# მაგალითი MRI-ის თრედების გამოყენებით I/O-ზედ მორგებული ამოცანებისთვის
require 'net/http'
require 'uri'

urls = %w[http://example.com http://ruby-lang.org]
threads = urls.map do |url|
  Thread.new do
    uri = URI.parse(url)
    response = Net::HTTP.get_response(uri)
    puts "ჩამოტვირთული #{url} (სტატუსი: #{response.code})"
  end
end

threads.each(&:join)

ამგვარად, მიუხედავად იმისა, რომ Ruby-ს აქვს საშუალებები თრედებთან მუშაობისთვის, რეალური გამწევი მრავალრეწველობა CPU-ზედ მორგებულ ამოცანებზე ძირითადად მიღწეულია რამდენიმე პროცესის ან სპეციალური GIL-გაუქმებული Ruby რეალიზაციების გამოყენებით।