Ruby-də məcburi çoxlu tapşırıq necə həyata keçirilir?
sobes.tech Süni İntellekt
AI-dan cavab
"Təmiz" Ruby (MRI, JRuby, TruffleRuby) içində, Global Interpreter Lock (GIL) səbəbindən bir prosesdə kodun paralel icrası üçün həqiqi preemptive çoxlu tapşırıq yoxdur. GIL yalnız bir thread-in hər zaman Ruby kodunu icra etməsinə imkan verir.
Ancaq, Ruby-də preemptive çoxlu tapşırıq giriş/çıxış səviyyəsində mövcuddur. Bir thread bloklayan giriş/çıxış əməliyyatı həyata keçirəndə (məsələn, fayl oxuma, şəbəkə sorğusu), GIL sərbəst buraxılır və başqa bir thread Ruby kodunu icra edə bilər. Bu, giriş/çıxış əməliyyatları üçün paralelliyi təmin edir, amma CPU-bağlı tapşırıqlar üçün deyil.
Alternativ Ruby implementasiyaları (məsələn, Rubinius) GIL olmadan həqiqi çoxlu tapşırıq həyata keçirməyə çalışıb, lakin onlar MRI qədər geniş yayılmayıb.
Ruby-də CPU-bağlı tapşırıqların paralel icrası üçün adətən:
- Proseslər (
fork): Hər prosesin öz GIL-i var, bu da Ruby kodunun paralel icrasına imkan verir. Proseslər arasında məlumat mübadiləsi açıq mexanizmlər (IPC) tələb edir. - Xarici kitabxanalar və C uzantıları: C-də həyata keçirilmiş əməliyyatlar GIL nəzarətindən kənarda icra oluna bilər və paralel icra təmin edir.
Ruby 3.0-da Fibers Scheduler təqdim olunub, bu da fiberlər və qeyri-bloklayıcı çağırışlar istifadə edərək giriş/çıxış əməliyyatlarını asinxron icra etməyə imkan verir. Bu, I/O-bağlı tapşırıqlar üçün performansı artırır, amma CPU-bağlı tapşırıqları həqiqətən paralel etmir.
# MRI-də I/O-bağlı tapşırıqlar üçün thread nümunəsi
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 "Yükləndi #{url} (Status: #{response.code})"
end
end
threads.each(&:join)
Beləliklə, Ruby-də thread-lərlə işləmək üçün vasitələr olsa da, CPU ilə əlaqəli tapşırıqlar üçün həqiqi preemptive çoxlu tapşırıq adətən çoxlu proseslər və ya GIL olmayan xüsusi Ruby implementasiyaları vasitəsilə əldə edilir.