от Гост автор

Това е публикация като гост от Лорънс Трат, който е програмист и читател по разработка на софтуер в Департамента по информатика в Кралския колеж в Лондон, където той ръководи Екипа за разработка на софтуер. Той също така е стипендиант на EPSRC.

Езикът за програмиране Виртуалните машини (VM) са познати зверове: ние ги използваме, за да изпълняваме приложения на телефона си, код в нашите браузъри и програми на нашите сървъри. Традиционните VM са полезни и широко използвани: почти всеки работещ програмист е запознат с една или повече от „стандартните“ Lua, Python или Ruby VM. Въпреки това, такива виртуални машини са опростени, съдържащи само интерпретатор (проста реализация на език). Те често не могат да изпълняват нашите програми толкова бързо, колкото ни е необходимо; и дори когато могат, те често губят огромни количества сървърно процесорно време. Понякога забравяме, че сървърите консумират голяма и нарастваща част от световното производство на електроенергия: бавните езикови реализации буквално променят света, и то не по добър начин.

По-усъвършенстваните виртуални машини идват с компилатори Just-In-Time (JIT) (добре известни примери включват LuaJIT, HotSpot (известен още като „JVM“), PyPy и V8). Такива виртуални машини наблюдават поведението на програмата по време на изпълнение и го използват, за да компилират често изпълнявани части от програмата в машинен код. Когато това работи добре, това води до значителни ускорявания (2x-10x е обичайно; и 100x не е неизвестно). Всички искаме да направим тези виртуални машини дори по-добри, отколкото са в момента, но да го направим е по-лесно да се каже, отколкото да се направи.

Вътрешно виртуалните машини с JIT компилатори са свирепо сложни зверове, с много движещи се части, които взаимодействат по фини начини, за които е трудно да се разсъждава. Например, всеки разработчик на VM, който си заслужава солта, ще има истории за „бъгове при деоптимизация“: тоест грешки, които възникват, когато оптимизираният машинен код вече не е полезен и VM трябва да се върне към по-малко оптимизирана, но по-обща версия на програмата (напр. интерпретатор). Мислили ли сте някога как да разделите стека на вградена функция? Може би звучи доста лесно. Какво се случва, когато вграждането е позволило на JIT компилатора да премахне разпределенията на паметта: как трябва да бъдат идентифицирани и „възстановени“ „липсващите“ разпределения? Дори само в тази единствена част от VM, сложността бързо става умопомрачителна.

Какво общо има това с Cloudflare или мен? Е, както много от вас знаят, Cloudflare е тежък потребител на LuaJIT и биха искали LuaJIT да работи дори по-добре, отколкото днес. Въпреки че Cloudflare има разработчици с дълбоко разбиране на LuaJIT, те отдавна искат да дадат повече на общността с отворен код. За съжаление намирането на някой, който може и желае да работи по такава сложна програма, не е най-малкото лесно. Предложих, че нашата изследователска група — „Екипът за разработка на софтуер“ в Кралския колеж в Лондон – може да предостави ползотворен алтернативен път. За щастие Cloudflare се съгласи и ни даде финансиране за проект, целящ да подобри представянето на LuaJIT, който започна в края на август.

Защо нашият екип? Е, отчасти защото сме свършили много работа с VM от „оптимизиране на структурата на данните“ до „композиция на езика“ до „бенчмаркинг“, което ни помага да накараме хората, които са нови в тази област, да работят бързо. Отчасти обичам да мисля, защото сме отворени към проектите, които използваме като част от нашите изследвания. Въпреки че не сме правили огромно количество пряко проучване на LuaJIT, винаги сме се опитвали да сме в крак с неговото развитие (напр. това доведе до поканата на Вячеслав Егоров да говори за LuaJIT на VM Summer School, което проведохме през 2016 г. ) и често сме го използвали като ключова част от сравнителния анализ между VM.

Лично аз познавам LuaJIT от много години: изпратих много, много малка корекция, за да я накарам да работи на OpenBSD през 2012 г., за да мога да изпробвам тази виртуална машина, за която бях чувал други да се възхищават; Използвах умната система за сглобяване на LuaJIT в малък проект за играчки; и съм включил LuaJIT в повече от един пакет за сравнителен анализ (напр. „този документ“). Първото ми впечатление беше, че LuaJIT има удивително малка кодова база и удивително бързо загряване (грубо казано, времето от началото на програмата до генерирането на крайния машинен код). И двете точки остават верни днес и са доказателство за визията и способностите за кодиране на Mike Pall. Въпреки това, сравняването на LuaJIT с други виртуални машини показа слабости, които, както разбрах, са широко известни на тези, които използват LuaJIT на големи системи. Накратко, по-големите програми показват значителни разлики в производителността от едно изпълнение до следващо и някои програми не работят толкова бързо за дълги периоди, колкото другите виртуални машини са способни. Не виждам това като критика - всяка виртуална машина, с която съм запознат, има силни и слаби страни - а по-скоро като възможност да видим дали можем да направим нещата още по-добри.

Как ще се опитаме да подобрим LuaJIT? Първо, имахме един от онези късмети, за които обикновено можете само да мечтаете: след разговори с някои приятелски настроени служители на LuaJIT, имах голям късмет да изкуша Томас Франшам, експерт по LuaJIT, да работи с нас в King’s. Дълбокото разбиране на Том за вътрешността на LuaJIT означава, че имаме някой, който може незабавно да започне да превръща идеите в реалност. Второ, ние използваме нашата многогодишна работа по бенчмаркинг на VM, който наскоро видя бял свят като хартията „Virtual Machine Warmup Blows Hot and Cold“ и системите „Krun“ и „warmup_stats“. За да съкратим една дълга и плътна хартия, ние открихме, че дори в идеализирана обстановка, широко проучените бенчмаркове често не загряват, както се предполага на добре известни виртуални машини. Понякога стават по-бавни с времето; понякога никога не се стабилизират; понякога те са непоследователни от едно изпълнение до следващо. Дори и в най-добрия случай открихме, че във всички виртуални машини, които изследвахме, само 43,5% от случаите се затоплиха, както се очакваше (при 51%, LuaJIT беше малко по-добър от някои виртуални машини). Въпреки че това е донякъде смущаваща новина за онези от нас, които разработват виртуални машини, това ме принуди да направя две хипотези (което е фантастична дума за „интуиция“), които ще тестваме в този проект: че виртуалните машини имат евристика (напр. „когато за компилиране на код”), които взаимодействат по начини, които вече не разбираме; и че строгият бенчмаркинг преди и след промени (независимо дали тези промени добавят или премахват код) е единственият начин да направите производителността по-добра и по-предсказуема.

Както може да подскаже това, ние не целим „просто“ да подобрим LuaJIT. Този проект също естествено ще ни помогне да развием нашите по-широки изследователски интереси, съсредоточени около разбирането как може да се подобри производителността на VM. Надявам се, че това, което научаваме от LuaJIT, в дългосрочен план ще помогне и на други виртуални машини да се подобрят. Наистина имаме големи идеи за това как може да изглежда следващото поколение виртуални машини и сме длъжни да научим важни уроци от този проект. Нашият дългосрочен залог е върху мета-проследяването: смятаме, че можем да намалим страховитите в момента разходи за загряване чрез комбинация от новата функция за проследяване на процесора на Intel и някои други трикове, които имаме в ръкавите си. След това това отваря нови възможности за правене на неща като паралелна компилация, които всъщност не са се смятали за полезни преди. Въпреки че LuaJIT не е мета-проследяващ JIT компилатор, той е проследяващ JIT компилатор и, както подсказва подобно име, повечето концепции се пренасят от един към друг.

Да кажа, че съм изключително благодарен на Cloudflare за тяхната подкрепа, е подценяване. Може да не е очевидно отвън, но (с изключение на мен) всички в нашата изследователска група се подкрепят от външно финансиране: без него не мога да плащам на добри хора като Том, за да помогнат за придвижването на темата напред. Също така имам удоволствието да кажа, че преди дори да попитам, Cloudflare даде ясно да се разбере, че искат всички резултати от проекта да бъдат отворени. Всички промени, които правим, ще бъдат с напълно отворен код под нормалния лиценз на LuaJIT, така че както и когато правим подобрения в LuaJIT, цялата общност на LuaJIT ще има полза. Искам също така, по-общо, да бъдем добри граждани в рамките на по-широката LuaJIT общност. Знаем, че имаме много да научим от вас, от идеи за сравнителен анализ до конкретни преживявания при проблеми с производителността. Не се притеснявайте да се свържете!

Първоначално публикувано в blog.cloudflare.com на 19 октомври 2017 г.