
Փորձնական փաթչ Go-ի netip-ում չեղարկում է բայթերի վերադասավորումը IPv4-ը IPv6-ի փոխարկելիս
Փորձնական կոմպիլյատորի վերաշարադրումը Go-ի netip.AddrFrom16(ip.As16()) նախշը վերածում է ներքին դաշտի ուղիղ պատճենման և արտադրում է նույն կարճ ասեմբլերը, ինչ 0,88 ns-անոց ստանդարտ գրադարանի լուծումը։
Ինչու է փոխարկման նախշը դանդաղ
Go-ի netip.Addr-ը տրամադրում է Unmap() մեթոդ, որը IPv4-ով ներկայացված IPv6 հասցեից վերադարձնում է բացված IPv4 հասցեն։ Հակառակ գործողության համար չկա Map() կամ To6() մեթոդ։ Go-ի մենթեյներները հրաժարվել են այն ավելացնելուց և օգտվողներին ուղղորդում են դեպի netip.AddrFrom16(ip.As16())՝ հույսով, որ կոմպիլյատորը դա կօպտիմալացնի։
Ներսում netip.Addr-ը IP հասցեն պահում է որպես 128-բիթանոց արժեք և օգտագործում է լրացուցիչ դաշտ՝ դրա ընտանիքը և գոտին կոդավորելու համար։ To6()-ի ստանդարտ գրադարանի իրականացումը կարող էր փոխել այդ դաշտը IPv4 հասցեների համար։ Իսկ արտաքին օգնականը հակառակը՝ պետք է հասցեն վերածի 16-բայթանոց զանգվածի և վերադարձնի հետ։
Բենչմարկի արդյունքները
Go 1.27.1-ի Linux-ում և AMD-ի Ryzen 5 5600X 6-միջուկանի պրոցեսորի վրա անցկացված բենչմարկներում ստանդարտ գրադարանի լուծումը գործողության համար պահանջել է 0,8775 ns։ Անվտանգ օգնականը պահանջել է 7,137 ns, իսկ անանվտանգ իրականացումը, որը նույն ներքին վիճակին հասնում էր proxy-ի միջոցով,՝ 0,8682 ns։ Այդ պատճառով օգնականը մոտավորապես ութ անգամ դանդաղ էր։
Ստանդարտ գրադարանի և անանվտանգ տարբերակների ասեմբլերները գրեթե նույնական էին։ Երկուսն էլ ստուգում էին հասցեի ընտանիքը և IPv4-ի մշակման ժամանակ փոխում էին ներքին ընտանիքի արժեքը։ Անվտանգ օգնականը ավելի շատ հրահանգներ էր գեներացնում, քանի որ հասցեն դասավորում էր 16-բայթանոց զանգվածում, պատճենում էր զանգվածը և նորից բացում։ Go 1.26.8-ի դրությամբ կոմպիլյատորը այդ հաջորդականությունը չէր հեռացնում։
Կոմպիլյատորի մակարդակի փորձ
Փորձը հենց netip.AddrFrom16(ip.As16()) նախշը վերաշարադրում է կոմպիլյատորի noding փուլի ընթացքում։ Այն կանչերը փոխարինում է netip.Addr կառուցվածքով, որը պատճենում է բնօրինակ հասցեն և վերագրում IPv6 ընտանիքի արժեքը։ Վերաշարադրումը պետք է կատարվի noding-ի ընթացքում, քանի որ ավելի վաղ տիպերի ստուգման փուլն արգելում է կառուցվածքի չարտահանված դաշտերին հասանելիությունը։
Մոդիֆիկացված build-ը վերաշարադրմամբ գեներացնում էր նույն կարճ ասեմբլերը, ինչ ուղիղ իրականացումը, և թեստերը հաջողությամբ անցան net/netip-ի և օգնական փաթեթի համար։ Վերլուծությունը նշում է, որ Go-ի մենթեյներները քիչ հավանական է, որ համաձայնեն այս մոտեցմանը, քանի որ այն կախված է netip.Addr-ի ներքին դասավորությունից և noder-ին ավելի շատ պատասխանատվություն է դնում, քան տիպերի ստուգված շարահյուսական ծառի հավատարմորեն թարգմանելը։
Առաջարկվող SSA օպտիմիզացիա
Ավելի ընդհանուր մոտեցումը որպես թիրախ ընտրում է կոմպիլյատորի ընդհանուր SSA փուլը, մասնավորապես memcombine փասը։ Առաջարկվող վերաշարադրման կանոնները բեռնումները վերահասցեավորում են հիշողության տեղափոխումների միջոցով, պահված արժեքները փոխանցում են հետագա բեռնումներին և չեղարկում բայթերի փոխանակման գործողությունների զույգերը։
Հասցեի յուրաքանչյուր 64-բիթանոց կեսի համար այս ձևափոխությունները խուսափում են ժամանակավոր զանգվածից, դրա պատճենից և ավելորդ հիշողության հասանելիությունից։ Ավելի բարձր կեսի փոխանցումը նույնպես հնարավոր է պահման գործողության միջոցով դեպի հարևան, չծածկվող հասցե։ Պարզեցումից հետո յուրաքանչյուր ելքային կես դառնում է համապատասխան մուտքային կեսի պատճենը, ինչը հասցեի տվյալները թողնում է անփոփոխ և դնում է անհրաժեշտ ընտանիքի արժեքը։
SiTech — AI-ով հզորացված վեբ մշակում
Ստեղծում ենք արագ ու ժամանակակից կայքեր և AI-ը ներդնում իրական բիզնես գործընթացներում։ Ունե՞ք նախագիծ կամ հարց։ Ուրախ կլինենք օգնել։