Sobes.tech
Middle+

Ինչպես է Ruby-ում իրականացվում կանխարգելիչ բազմակողմանիություն?

sobes.tech AI

Պատասխան AI-ից

Նախնական Ruby (MRI, JRuby, TruffleRuby) իրական ժամանակի հետագծային բազմակողմանիություն չունի, քանի որ Global Interpreter Lock (GIL)-ը թույլ չի տալիս միաժամանակ մի քանի թրեդով Ruby կոդ գործարկել: GIL-ը թույլ է տալիս միայն մեկ թրեդին կատարել Ruby կոդ ցանկացած ժամանակ:

Այնուամենայնիվ, Ruby-ում ժամանակի հետագծային բազմակողմանիությունը առկա է մուտք-արտաքին մակարդակում: Երբ թրեդը կատարում է բլոկավոր մուտք-արտաքին (օրինակ՝ ֆայլի ընթերցում, ցանցային հարցում), GIL-ը ազատվում է, թույլ տալով մյուս թրեդին կատարել Ruby կոդ: Սա թույլ է տալիս հասնել մուտք-արտաքին գործողությունների համաժամանակեցման, բայց ոչ CPU-կենտրոնացված խնդիրների համար:

Կան այլ Ruby իրականացումներ (օրինակ՝ Rubinius), որոնք փորձել են իրականացնել իրական բազմակողմանիություն GIL-ով, բայց դրանք չեն ստացել այնպիսի լայն տարածում, ինչպիսին MRI-ն:

Սովորաբար, Ruby-ում CPU-կենտրոնացված խնդիրների համար օգտագործվում են՝

  • Պրոցեսներ (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-ն ունի գործիքներ թրեդների հետ աշխատելու համար, իրական ժամանակի հետագծային բազմակողմանիությունը հիմնականում հասանելի է մի քանի պրոցեսների կամ հատուկ GIL-ով չտարբերակված Ruby իրականացումների օգտագործմամբ։