Натыўная кампіляцыя ў Quarkus чаму гэта важна

Ўсім прывітанне! З вамі другі пост з нашай серыі па Quarkus сёння пагаворым аб натыўнай кампіляцыі.

Натыўная кампіляцыя ў Quarkus чаму гэта важна

Кваркус - гэта Java-стэк, заменчаны пад Kubernetes. І хоць тут, вядома, шмат чаго яшчэ трэба зрабіць, мы добра прапрацавалі масу аспектаў, уключаючы аптымізацыю JVM і цэлага шэрагу фрэймворкаў. Адной з асаблівасцяў Quarkus, выклікалай падвышаную цікавасць са боку распрацоўнікаў, стаў комплексны бясшвоўны падыход да ператварэння Java-кода ў выкананыя файлы для пэўнай аперацыйнай сістэмы (так званая «натыўная кампіляцыя») па аналогіі з C і C++, дзе такая кампіляцыя звычайна адбываецца у канцы цыклу, які складаецца з зборкі, тэсціравання і разгортвання.

І хоць натыўная кампіляцыя, як мы пакажам ніжэй, важная, трэба адзначыць, што Quarkus рэальна добра працуе і на самай звычайнай Java-машыне OpenJDK Hotspot дзякуючы тым паляпшэнням прадукцыйнасці, якія мы рэалізавалі па ўсім стэку. Таму натыўную кампіляцыю варта разглядаць як дадатковы бонус, які можна выкарыстоўваць па жаданні ці неабходнасці. Насамрэч у тым, што дакранаецца натыўных выяў, Quarkus у значна меры абапіраецца на OpenJDK. А цеплыня прыняты распрацоўнікамі рэжым dev mode забяспечвае практычна імгненнае тэставанне змен за кошт развітых магчымасцяў дынамічнага выканання кода, рэалізаваных у Hotspot. Акрамя таго, пры стварэнні натыўных выяў GraalVM задзейнічаецца бібліятэка класаў OpenJDK і магчымасці HotSpot.

Дык навошта тады патрэбна натыўная кампіляцыя, калі ўсё і так добра аптымізавана? На гэтае пытанне мы і пастараемся адказаць ніжэй.

Пачнем з відавочнага: Red Hat валодае вялікім досведам аптымізацыі JVM, стэкаў і фрэймворкаў падчас развіцця праекта JBoss, уключаючы:

  • Першы сервер прыкладанняў для працы ў воблаку на платформе Red Hat OpenShift.
  • Першы сервер прыкладанняў для працы на кампутарах Plug PC.
  • Першы сервер прыкладанняў для працы на Raspberry Pi.
  • Цэлы шэраг праектаў, якія працуюць на прыладах Android.

Мы ўжо шмат гадоў займаемся праблемамі запуску Java-прыкладанняў у воблаку і на прыладах з абмежаванымі рэсурсамі (чытай, IoT) і навучыліся выціскаць з JVM максімум у сэнсе прадукцыйнасці і аптымізацыі памяці. Як і многія іншыя, мы ўжо даўно працуем з натыўнай кампіляцыяй Java-прыкладанняў праз GCJ, птушыны, Excelsior JET і нават Dalvik і выдатна ўсведамляем плюсы і мінусы такога падыходу (напрыклад, дылему выбару паміж універсальнасцю "build once – run-anywhere" і тым, што скампіляваныя прыкладанняў маюць меншы памер і хутчэй запускаюцца).

Чаму так важна ўлічваць гэтыя плюсы і мінусы? Таму што ў некаторых сітуацыях іх суадносіны робяцца вырашальнымі:

  • Напрыклад, у serverless/кіраваных падзеямі асяроддзях, дзе сэрвісы проста абавязаны запускацца у рэжыме (цвёрдага ці мяккага) рэальнага часу, каб паспяваць рэагаваць на падзеі. У адрозненне ад доўга якія жывуць персістэнтных сэрвісаў, тут працягласць халоднага запуску крытычна павялічвае час адказу на запыт. На запуск JVM усё яшчэ сыходзіць істотны час, і хоць у некаторых выпадках яго можна скараціць чыста апаратнымі метадамі, розніца паміж адной секундай і 5 мілісекундамі можа быць пытаннем жыцця і смерці. Так, тут можна пагуляцца са стварэннем гарачага рэзерву Java-машын (што мы, напрыклад, зрабілі пры партаванні OpenWhisk на Knative), але само па сабе гэта не гарантуе дастатковай для апрацоўкі запытаў колькасці JVM па меры маштабавання нагрузкі. Ды і з эканамічнага пункта гледжання гэта, напэўна, не самы слушны варыянт.
  • Далей, ёсць яшчэ такі часта ўсплывальны аспект, як мультытэнантнасць. Нягледзячы на ​​тое, што JVM па сваіх магчымасцях моцна наблізіліся да аперацыйных сістэм, яны ўсё яшчэ не здольныя рабіць тое, да чаго мы так абвыклі ў тым жа Linux'е - ізаляваць працэсы. Таму збой аднаго струменя можа вывесці са строю ўсю Java-машыну. Многія спрабуюць абыйсці гэты недахоп тым, што вылучаюць пад прыкладанні кожнага карыстальніка асобную JVM, каб мінімізаваць наступствы збою. Гэта суцэль лагічна, але дрэнна спалучаецца з маштабаваннем.
  • Акрамя таго, для хмарна-арыентаваных прыкладанняў важны такі паказчык, як шчыльнасць сэрвісаў на хасце. Пераход на метадалогію 12 фактараў прыкладання, мікрасэрвісы і Kubernetes павялічвае колькасць Java-машын на адно прыкладанне. Гэта значыць, з аднаго боку, усё гэта дае эластычнасць і надзейнасць, але адначасова расце і выдатак базавай памяці ў пераліку на сэрвіс, прычым частка гэтых выдаткаў далёка не заўсёды з'яўляецца строга неабходнай. Статычна скампіляваныя выкананыя файлы выйграюць тут за рахунак розных тэхнік аптымізацыі, накшталт нізкаўзроўневага dead-code elimination, калі ў выніковую выяву ўключаюцца толькі тыя часткі фреймворков (уключаючы і сам JDK), якія сэрвіс рэальна выкарыстае. Таму натыўная кампіляцыя Quarkus дапамагае шчыльней размяшчаць асобнікі сэрвісаў на хасце без шкоды для бяспекі.

Уласна, прыведзеных вышэй довадаў ужо дастаткова для таго, каб зразумець апраўданасць натыўнай кампіляцыі з пункту гледжання ўдзельнікаў праекта Quarkus. Аднак ёсць яшчэ адна, не тэхнічная, але таксама важны чыннік: у апошнія гады шматлікія праграмісты і кампаніі-распрацоўнікі адмовіліся ад Java у карысць новых моў праграмавання, палічыўшы, што Java разам са сваімі JVM, стэкамі і фрэймворкамі стала занадта пражэрлівай у плане памяці, залішне павольнай і г.д.

Аднак звычка выкарыстоўваць адзін і той жа інструмент для вырашэння любых задач - гэта не заўсёды правільна. Часам лепш зрабіць крок назад і пашукаць нешта іншае. І калі Quarkus прымушае людзей зрабіць паўзу і задумацца, тое гэта добра для ўсёй экасістэмы Java. Quarkus увасабляе сабой наватарскі погляд на тое, як ствараць больш эфектыўныя прыкладанні, робячы Java больш рэлевантнай новым архітэктурам прыкладанняў, накшталт serverless. Акрамя таго, дзякуючы сваёй пашыральнасці, Quarkus, як мы спадзяемся, абзавядзецца цэлай экасістэмай Java-пашырэнняў, значна павялічыўшы колькасць фрэймворкаў, якія са скрынкі будуць падтрымліваць натыўную кампіляцыю ў складзе прыкладанняў.

Крыніца: habr.com

Дадаць каментар