JIT կոմպիլյացիա

Վիքիպեդիայից՝ ազատ հանրագիտարանից

JIT-կոմպիլյացիա (անգլ. Just-in-time compilation), դինամիկ կոմպիլացիան (անգլ. dynamic translation) ծրագրի կատարման ժամանակ արված կոմպիլյացիա է՝ այլ ոչ թե մինչև ծրագրի կատարումը։ Շատ հաճախ այն բաղկացած է մեքենայական կոդի թարգմանությունից, բայց կարող է վերաբերվել նաև այլ ֆորմատի թարգմանությանը։

Դինամիկ թարգմանչի հաջորդականությունը

JIT-կոմպիլյացիան մեքենայական կոդը թարգմանելու երկու ավանդական գաղափարների կոմբինացիա է՝ AOT-կոմպիլյացիա և ինտերպրետացիա, և իր մեջ համատեղում է երկուսի որոշ առավելություններ և թերություններ։ Կոպիտ ասած, JIT-կոմպիլյացիան համատեղում է կոմպիլյացված կոդի արագությունը ինտերպրետացիայի ճկունության հետ, ինտերպրետատորի հավելյալ ծախսերի հետ և լրացուցիչ կոմպիլյացիայի ծախսերը (ոչ միայն ինտերպրետացիայի)։ JIT-կոմպիլյացիան դինամիկ կոմպիլյացիայի տեսակ է, այդպիսով JIT-կոմպիլյացիայի տեսությունում կարող է տալ ավելի արագ կատարում քան ստատիկ կոմպիլացիան։ Ինտերպրետացիան և JIT-կոմպիլյացիան հատկապես համապատասխանում են դինամիկ ծրագրավորման լեզուների համար, այդ դեպքում runtime համակարգը կարող է կարգավորել late-bound տվյալների տիպերը և երաշխավորել կատարման անվտանգությունը։

Դինամիկ կոպիլյացիայի դասկարգումները

Իրականցման առանձնահատկությունները[խմբագրել | խմբագրել կոդը]

JIT-կոմպիլյացիան կարող է կիրառվել ինչպես ամբողջ ծրագրում, այնպես էլ դրա առանձին մասերում։ Օրինակ տեքստային ձևախիչը (անգլ. text editor) կարող է կոմպիլյացնել ռեգուլյար արտահայտությունները տեքստի ավելի արագ փնտրման համար։ AOT-կոմպիլյացիայի հետ այդպիսի բան անել հնարավոր չէ, քանի որ տվյալները տրամադրում են ծրագրի կատարման ժամանակ, այլ ոչ թե կոմպիլյացիայի ժամանակ։

Նկարագրություն[խմբագրել | խմբագրել կոդը]

Վիիտուալ մեքենայի միջավայրը՝ միջանկյալ ծրագրի բեռնման համար

Լեզուներում, ինչպիսին են Java, PHP, C#,Lua, Perl, GNU CLISP, սկզբնական կոդը թարգմանվում է միջանկյալ նկարագրության (անգլ. intermediate representation )՝ բայթկոդ անվանմամբ (անգլ. bytecode)։ Բայթկոդը ինչ-որ կոնկրետ պրեցոսսորի մեքենայական կոդ չի հանդիսանում և կարող է տեղափոխվել համակարգչի տարբեր ճարտարապետություն և իրականացվել նույն ձևով։ Բայթկոդը ինտերպրետացվում է կամ իրականցվում վիրտուալ մեքենայում ։ JIT կոպիլյատորը կարդում է բայթկոդի տարբեր բաժիներ (կամ ամբողջը միանգամից՝ հազվադեպ) և կոմպիլյացնում է մեքենայակն կոդի։ Այդ բաժիները կարող են լինել ֆայլեր, ֆունկցիաներ կամ կոդի ցանկացած հատված։ Կոդը կարող է կոմպիլյացված լինել, երբ այն պատրաստվում է կատարվել (այստեղից էլ "just-in-time" անունը)։ Մեկ անգամ կոմպիլյացված կոդը կարող է կեշավորվել և հետագայում կրկին օգտագործվել առանց վերակոմպիլյացայի (անգլ. recompile)։

Ի տարբերություն, ավանդական ինտերպրետացված վիրտուալ մեքենան (անգլ. interpreted virtual machine) ուղղակի ինտերպրետացնում է բայթկոդ, սովորաբար ավելի ցածր արդյունավետությամբ։ Որոշ ինտերպրետատորներ նույնիսկ ինտերպրետացնում են սկզբնական կոդը, բայթկոդի առանց սկազբանական կոմպիլյացիայի քայլի և նույնիսկ ավելի վատ արդյունավետությամբ։ Ստատիկ կոմպիլյացված կոդը (անգլ. Statically compiled code) կամ հարազատ կոդը (անգլ. native code) կոմպիլյացվում է նախքան տեղակայումը։

JIT մեթոդի հիմանակն նպատակը՝ ստատիկ կոմպիլյացիայի արդյունավետությանը հասնելը և գերազանցելն է, այդպիսով պահպանելով դինամիկ կոմպիլյացիայի առավելությունները՝

  • Ծանրաքարշ գործողությունների մեծամասնությունը, ինչպիսին է նախնական կոդի վերլուծությունը և հիմնական օպտիմիզացիաները հաճախ մշակվում են կոմպիլյացիայի ժամանակ, մինչև տեղակայումը՝ բայթկոդից մեքենայական կոդի կոմպիլյացիան շատ ավելի արագ է, քան կոմպիլյացիան սկզբնական կոդից։
  • Բայթկոդը փոխադրելի է, ի տարբերություն հարազատ կոդի կամ մեքենայական կոդի (անգլ.՝ native code
  • Միջոցը կարող է հսկել բայթկոդի կատարումը կոմպիլյացիայից հետո, այդ պատճառով այն կարող է գործարկվել ավազամանում ( անգլ.՝ Sandboxing, Ավազամանը համակարգչային անվտանգությունում հատուկ մշակված միջոց է, համակարգչային ծրագրերի անվտանգ կատարման համար)։
  • Պետք է նշել նաև որ հարազատ ծրագրերի համար ևս կա այդպիսի հնարավորություն, բայց տվյալ մեթոդի իրականցումը դժվար է։
  • Կոմպիլյացիան բայթկոդից մեքենայակն կոդի հեշտ է իրականցնել, քանի որ օպտիմիզացիայի աշխատանքի մեծամասնությունը արդեն արված է եղել կոմպիլյատորի կողմից։

JIT կոդը հիմանականում առաջարկում է ավելի լավ արդյունավետություն քան ինտերպրետատորը։ Դրանից բացի կարող է առաջարկել ավելի լավ արդյունավետություն քան ստատիկ կոմպիլյացիան, քանի որ շատ օպտիմիզացիաներ հնարավոր են միայն ծրագրի կատարման ժամանակ ՝

  • Կոմպիլյացիան կարող է իրականցվել անմիջապես նպատակային պրացեսսորի և օպերացիան համակարգի համար, որում գործարկվելու է հավելվածը։ Օրիանակ JIT-ը կարող է օգտագործել վեկտորային SSE2 պրոցոսսորի ընդլայնում, եթե գտնում է որ այդ պրոցեսսորը աջակցում է այն։ Սակայն մինչ դեռ JIT-ի հիմանակն իրականացում չկա, որտեղ այդ մոտեցումը կօգտագործվի, քանի որ պետք է օպտիմիզացիայի նման մակարդակ ապահովել, համեմատած ստատսիկ կոմպիլյատերի հետ, կպահանհանջվեր կամ ապպահովել բինար ֆայլ յուրաքանչյուր պալտֆորմի տակ, կամ միացնել օպտիմիզատորի մեկ գրադարան յուրաքանչյուր պալտֆորմի տակ։
  • Այդ միջոցը կարող է աշխատող ծրագրի մասին հավաքել վիճակագրություն և դուրս բերել օպտիմիզացիաներ հաշվի առնելով այդ ինֆորմացիաները։ Որոշ ստատիկ կոմպիլյատորներ կարող են նաև ընդունել մուտքային ինֆորմացիա։
  • Այդ միջոցը կարող է կատարել կոդի գլոբալ օպիմիզացիաներ (օրինակ՝ գրադարանային ֆունկցիաներ ներկառուցումը) առանց կորցնելու դինամիկ կոմպիլյացիայի առավելությունները և առանց հավելյալ ծախսերի՝ բնորոշ ստատիկ կոմպիլյատորին և լինկերին։
  • Կեշի ցանկալի օգտագործման համար կոդի ավելի հասարակ վերակառուցում։

Մեկնարկի հապավումը և օպտիմիզացիաները[խմբագրել | խմբագրել կոդը]

.NET կոպիլյատորով սկզբնական կոդը կոմպիլայցվում է ՛՛exe՛՛-ի կամ ՛՛dll՛՛-ի

JJIT կոմպիլյատորի տիպիկ հապավման պատճառը ծախսերն են բեռնման և բայթկոդի կոմպիլյացիայի վրա։ Ընդհանուր դեպքում, ինչքան լավ և ինչքան մեծ օպտիմիզացիաներ է կատարում JIT-ը, այնքան երկար է ստանում հապաղումը։ Այդ պատճառով JIT կոմպիլյատորը պետք է փոխզիջումներ կատարի գեներացված կոդի որակի և մեկնարկի ժամանակի միջև։ Սակայն, հաճախ ստացվում է այնպես, որ նեղ տեղերը (անգլ. bottleneck) կոմպիլյացիայի գործընթացում ստացվում է ոչ ինքը՝ կոմպիլյացիայի գործընթացը, այլ մուտքային և ելքային հապավումները (ինչպես օրինակ, rt.jar-ը Java Virtual Machine-ում (JVM) ունի 40ՄԲ չափ, և իրենում մետատվյալների փնտրումը զբաղեցնում է բավականչափ շատ ժամանակ)։

Այլ օպտիմիզացիայի միջոց է կոմպիլյացնել հավելվածի այն հատվածները, որոնք ավելի հաճախ են օգտագործվում։ Այդ մոտեցում է իրականցված է SunMicrosystems ընկերության PyPy -ում и HotSpot Java Virtual Machine -ում։


Երբեմն բավական դժվար է գտնել ճիշտ փոխզիջումներ։ Այդպես, օրինակ Sun’s Java Virtual Machine-ը ունի երկու աշխատանքի ռեժիմ՝ կլիենտ և սերվեր (անգլ. client and server) ։ Կլիենտի ռեժիմում կոմպիլյացիայի քանակը և օպտիմիզացիան մինիմալ են ավելի արագ բեռնման համար, մինչդեռ սերվերի ռեժիմում հասնում է մաքսիմալ արդյունավետության, բայց դրա պատճառով մեծանում է բեռնման ժամանակը։

Եվս մեկ մեթոդ, որը կոչվում է pre-JIT , կոդը կոմպիլյացնում է մինչև բեռնելը. տվյալ մեթոդի առավելությունը հանդիսանում է բեռնման ժամանակի արագությունը, մինչդեռ թերությունը հանդիսանում է վատ կոմպիլյացված կոդը runtime JIT -ի հետ համեմատած։

Հուսալիությունը[խմբագրել | խմբագրել կոդը]

Քանի որ JIT կոմպիլյացիան բաղկացած է սկզբնական կոդի տվյալներից առաջանում է հուսալության (անվտանգության) հարց։

JIT կոմպիլյացիան իրենում համախմբում է սկզբնական կոդի կամ բայթկոդի կոմպիլյացիան մեքենայական կոդի և դրանց կատարումը։ Որպես կանոն արդյունքը գրվում է հիշողությունում և կատարվում է անմիջապես, չօգտագործելով դիսկ և չկանչելով առանձին ծրագիր։ Ժամանակակաից ճարտարապետությունում հուսալիությունը բարձրացնելու համար կամայական հիշողության հատվածները չեն կարող լինել իրականցված։ Ճիշտ աշխատանքի հաամար հիշողությունը պետք է նշված, որպես կատարվող (NX bit), ավելի մեծ անվտանգության համար ֆլագը պետք է դրված լինի հիշողության մեջ կոդի բեռնումից հետո, իսկ այդ հիշողությունը պետք է հասանելի լինի միայն ընթեցման համար։

Հղումներ[խմբագրել | խմբագրել կոդը]