Ինչպես է 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 իրականացումների օգտագործմամբ։