LINUX.ORG.RU

Технология JIT - это диверсия?


0

2

Я вот думаю, а есть ли хоть один пример, когда JIT имеет смысл. Смотрите:
- мы запускаем программу как интерпретируемую, т.е. гарантирована только скорость работы интерпретируемой программы. Если мы хотим делать суждения о том, когда рантайм соизволит скомпилировать наш цикл в бинарный код, мы попадаем на скользкую почву.
- программа несёт в себе компилятор (и становится тяжелее)
- программа постоянно запущена как бы под профайлером, т.е., идут постоянные траты процессорных циклов на оценку повторяемости кода и траты памяти на хранение результатов этой оценки. Т.е., она изначально работает не то, что медленнее скомпилированной, а даже медленнее такой же интерпретированной программы.
- время отклика увеличивается. Вызов компилятора приводит к неожиданным затратам CPU, замена кода должна производиться с какой-то блокировкой (хотя и небольшой).
- надёжность снижена. Ошибки самой реализации JIT могут вылезти в произвольное время и их появление зависит от полного пути исполнения программы. Т.е., их крайне сложно диагностировать.

Единственное, что мы за это получаем - переносимость байткода. В любой технической ситуации, которую я могу помыслить, я бы предпочёл компилятор. Кроме того, на практике (мало имел дела с жабой, но), к примеру, исходники ICQ клиентов для мобильных телефонов - разные для разных моделей телефонов, то переносимости байткода всё равно не существует. Итого, вывод: JIT придуман для замедления работы железа и для того, чтобы оно скорее потребовало апгрейда.

Где изъян в моей логике? Какие ситуации я упустил?

★★★★★

Ответ на: комментарий от anonymous

Анонимус — слоупок и не читает тред.

anonymous
()

А есть какая-нибудь такая фигня, чтобы на машине разработчика можно было бы выполнить профилировку, сохранить результаты вместе с байт-кодом, а потом при установке по результатам профилировки сделать выборочную прекомпиляцию?

anonymous
()
Ответ на: комментарий от den73

Если где-то мы увидели, что наш нативный код недостаточно быстр (неоптимизирован инлайн, безусловный переход, боксинг объектов), то мы заменим этот нативный код на другой

У любого нормального JIT есть кеш, а это эквивалентно твоей схеме.

Единственная вещь, за которую я ненавижу JIT - это медленный стар и как следствие потребность в прогревании кода. Но во-первых это критично только для очень серьезных проектов, а во-вторых легко лечится «грелкой ». Во всех остальных отношениях JIT - это сплошные преимущества.

dizza ★★★★★
()
Ответ на: комментарий от anonymous

Зачем? Это нужно только для очень-очень толстых штук, да еще и на которые молниеносно наваливается нагрузка в хотя бы сотни запросов в секунду. Дрочить на миллесекунды в других случаях не стоит.

dizza ★★★★★
()
Ответ на: комментарий от dizza

> У любого нормального JIT есть кеш, а это эквивалентно твоей схеме
Я так понял, что он есть только для .NET.

den73 ★★★★★
() автор топика

Твои теоретические рассуждения противоречат эксперименту, так что искать изъяна не надо - надо забыть весь этот бред целиком.

anonymous
()

Портабельность - единственный, абсолютно единственный, плюс JIT перед компиляцией в нейтив.

Слушать дураков с промытыми маркетологами Sun/Oracle мозгами, которые тут отписались - не стоит.
В частности, про ускорение на лету посредством того, что, видите ли, у Jit метаинформации больше, чем у компилятора. Нисколько ее не больше, а намного меньше - JIT'у приходится работать с тупым байткодом, в котором вся изначальная структура программы поломана; а из байткода много информации не выудишь(не надо про предсказания ветвлений, и перекомпиляцию на основе этого, только бред нести - современные процессоры отлично этим занимаются и для нативного кода).

anonymous
()
Ответ на: комментарий от den73

> при N->infinity предварительная компиляция выигрывает.

...по скорости. Но, кроме скорости, есть и другие соображеия.

tailgunner ★★★★★
()
Ответ на: комментарий от den73

Я так понял, что он есть только для .NET.

Ну вот здесь и кроится неправильная предпосылка всех твоих суждений, которые приводят к выводу, что JIT - отстой. По крайней мере у JVM JIT c кешем, так что можно смело утверждать что у 99% всех интсалляций JIT (jvm, .net) есть кеш.

dizza ★★★★★
()
Ответ на: комментарий от anonymous

Я вот раньше тоже не слушал «дураков с промытыми маркетологами Sun/Oracle мозгами, которые тут отписались - не стоит.»

А потом по работе пришлось поработать с java и понял что мир полон тупых красноглазиков, кричащих «лисп!лисп!лисп!» на каждом углу, а по факту не имеющих выполенных нормальных проектов.

dizza ★★★★★
()
Ответ на: комментарий от den73

При том, что я сравнивал с компиляцией.

Сравнивать обычную, статическую компиляцию с JIT некорректно - для слишком разных целей они предназначены.

Хотя JIT иногда может и превзойти статическую компиляцию, он не для того предназначен. Он нужен для того, чтобы повысить быстродействие для языков, к которым по каким-либо причинам сложно/нежелательно/неоптимально/невозможно применить статическую компиляцию.

Кстати, насчет временных затрат - JIT-компиляция - это обычно компиляция байткода. И проходит она достаточно быстро, потери, связанные с ней, не являются критическими для типичного десктопного или серверного приложения.

Deleted
()
Ответ на: комментарий от dizza

И как это ты понял? И при чем тут это вообще?

И каких это красноглазиков ты имеешь ввиду?

anonymous
()
Ответ на: комментарий от anonymous

> Нисколько ее не больше, а намного меньше - JIT'у приходится работать с тупым байткодом, в котором вся изначальная структура программы поломана;

Чушь несусветная. CLI или байткод JVM уровнем намного выше, чем тот же GIMPLE или любой другой промежуточный уровень, который используется оптимизатором в любом современном компиляторе.

Ты, чувак, неграмотен, ты не в теме.

anonymous
()
Ответ на: комментарий от anonymous

Это ты не в теме про то, какие промежуточные уровни в современных компиляторах используются.
Во-первых, слоев обычно несколько. На каждом проводится ряд специфических оптимизаций.
Потом, всякие там SSA и прочее - в байткоде этого просто не сделать.

anonymous
()
Ответ на: комментарий от anonymous

Повторяю - ты неграмотный и не в теме. Перестань позориться.

Байткод .NET это практически expression tree. Перевод его в SSA задача тривиальная (посмотри на mini в Mono), так же как тривиальна и декомпиляция практически до исходного состояния.

В GCC, в Open64 и во многих других компиляторах, с которыми я имел дело, оптимизации начинаются только уже на очень низком уровне, когда метаданных уже намного меньше чем в байткоде JVM или CLR.

Так что прекрати разговаривать глупостями и займись самообразованием.

anonymous
()
Ответ на: комментарий от anonymous

> Потом, всякие там SSA и прочее - в байткоде этого просто не сделать.

И еще, неграмотный: посмотри на mem2reg и reg2mem проходы в LLVM.

anonymous
()
Ответ на: комментарий от dizza

> у JVM JIT c кешем
чтобы убедиться, что мы говорим об одном и том же. Я имею в виду дисковый кеш, когда код, будучи однажды скомпилирован, складывается в э
тот кеш и при следующем запуске не производится анализ и компиляция, а сразу происходит загрузка из этого кеша. Мне тут кто-то написал, что у jvm такого кеша нет, поэтому можно ли пруфлинк?

den73 ★★★★★
() автор топика
Ответ на: комментарий от anonymous

> CLI или байткод JVM уровнем намного выше, чем тот же GIMPLE или любой другой промежуточный уровень

Ничего себе новости. Что, даже _намного_?

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

>В GCC, в Open64 и во многих других компиляторах, с которыми я имел дело, оптимизации начинаются только уже на очень низком уровне

Тогда посмотри SBCL - вот это вот действительно крутой оптимизирующий компилятор. Перевод высокоуровневого языка с динамической типизацией в эффективный машкод - задача очень нетривиальная, но он с ней справляется.
Там два представления - IR1, высокоуровневое, и IR2, уровень абстрактной виртуальной машины. И оптимизации проводятся на обоих уровнях. И многие из этих оптимизаций с тупым байткодом просто не сделать.

Вот тут чувак подробно описывает нутро компилятора, советую почитать.
http://insidelisp.blogspot.com/

anonymous
()
Ответ на: комментарий от anonymous

> вот это вот действительно крутой оптимизирующий компилятор

И тем не менее,

http://shootout.alioth.debian.org/u32/benchmark.php?test=all&lang=java&lang2=...

Притом, не будем кривить душой, в лисповых программах на этом соревновании, как правило, все типы задекларированы, так что типизацию можно считать статической.

Хотя я уже предвижу, что хороший бенчмарк - это только тот бенчмарк, который доказывает превосходство любимого языка. А если не доказывает, то это оторванный от жизни пример, который в реальности никому не нужен.

Кстати, кто не знает, я никогда не писал на Яве ничего сложнее консольного hello,world и интенсивно использую Лисп.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

>И тем не менее

Тем не менее, давайте учтем, что Java - язык довольно низкоуровневый, и, притом, статически типизированный.

Полезно сравнение с тем же Ruby, Python, или хотя бы Javascript V8. Последний, несмотря на дико продвинутый JIT байткода, по-прежнему адски тормозит(если не учитывать задачи, где, фактически, используется сишная библиотека, или где боттлнек - I/O). В отличие от.

http://shootout.alioth.debian.org/u32/benchmark.php?test=all&lang=v8&lang2=sbcl

anonymous
()
Ответ на: комментарий от den73

Дискового кеша нету. Его нету просто потому, что не нужно реализовывать не очень нужные фичи. Без диского кеша имеет место небольшой лаг при первом обращении к коду. Ну представь, что он есть у JVM, и что теперь? Это просто такая мелочь, что гворить о ней - просто дрочерство.

dizza ★★★★★
()
Ответ на: комментарий от anonymous

> Тогда посмотри SBCL - вот это вот действительно крутой оптимизирующий компилятор. Перевод высокоуровневого языка с динамической типизацией в эффективный машкод - задача очень нетривиальная, но он с ней справляется.

Я туда смотрел, еще когда он был CMUCL и делал намного больше разнообразных оптимизаций. SBCL это кастрированный огрызок.

Там два представления - IR1, высокоуровневое, и IR2, уровень абстрактной виртуальной машины.

И все это весьма устарело. Того же SSA там нет.

И оптимизации проводятся на обоих уровнях. И многие из этих оптимизаций с тупым байткодом просто не сделать.

Опять бред про «тупой байткод». Этот «тупой байткод» уровнем выше чем даже исходник на Лиспе, потому как он типизированный. Уровень байткода ничем не отличается от уровня исходника на Java или C#, информация не теряется при компиляции (за исключением всяких там foreach/yield). С ним можно делать все что угодно.

anonymous
()
Ответ на: комментарий от anonymous

Кроме того, тов. swizard не так давно показывал, какие чудеса может дать компиляция кода на лиспе на SBCL в рантайме - позади остается даже C++.

Т.е. полноценный компилятор банально лучше оптимизирует, чем любой JIT.

http://swizard.livejournal.com/159125.html

anonymous
()
Ответ на: комментарий от tailgunner

>Ничего себе новости. Что, даже _намного_?

Уже и клоуны подтягиваются. Да, клоун, намного. Во первых, нет арифметики указателей. Во вторых, есть полная информация о типах. В третьих, есть полностью абстрагированный ООП, никаких тебе конкретных плясок с v-table, а просто call virtual.

anonymous
()
Ответ на: комментарий от anonymous

А ничего, что именно эти красноглазики (Гослинг, Стил и ко.) и создали Java?

Они как раз такие не красноглазики, а умные люди. Красноглазики, это те кто прочитали на лоре про лисп и думают, что имет право кричать про то, что жаба не нужна и прочее. Господа, вы ее просто не умете готовить. Истинны гуру уметт готовить даже вижуал бейсик.

dizza ★★★★★
()
Ответ на: комментарий от anonymous

> Т.е. полноценный компилятор банально лучше оптимизирует, чем любой JIT.

Ничто не мешает JIT-у быть «полноценным компилятором». См. llvm.

anonymous
()
Ответ на: комментарий от anonymous

>Я туда смотрел, еще когда он был CMUCL и делал намного больше разнообразных оптимизаций. SBCL это кастрированный огрызок.

Как раз наоборот, в SBCL много чего допилили, и продолжают пилить. А CMUCL, судя по всему, умер.

Того же SSA там нет.

Для CL SSA - довольно нетривиальная вещь. Однако, это в планах разработчиков.

Этот «тупой байткод» уровнем выше чем даже исходник на Лиспе, потому как он типизированный.


Вот это вот уже попахивает бредом.

Уровень байткода ничем не отличается от уровня исходника на Java или C#, информация не теряется при компиляции


Отличается, и причем сильно. Многие программные конструкции тупо размазываются на множество инструкций.

anonymous
()
Ответ на: комментарий от anonymous

> Как раз наоборот, в SBCL много чего допилили, и продолжают пилить.

Предварительно убрав все то, что не осилили понять. То есть, почти все.

Для CL SSA - довольно нетривиальная вещь. Однако, это в планах разработчиков.

Вот когда реализуют, тогда и поговорим. Для CL есть тривиальный аналог - CPS-преобразование.

Вот это вот уже попахивает бредом.

Это все от того, что ты не в теме.

Отличается, и причем сильно. Многие программные конструкции тупо размазываются на множество инструкций.

Конкретней. Какие конструкции, во что размазываются? Всякие for, do, while, if, switch транслируются однозначно, так же однозначно и декомпилируются.

anonymous
()
Ответ на: комментарий от anonymous

Отличается, и причем сильно. Многие программные конструкции тупо размазываются на множество инструкций.

Ты дурак? Любую скомпилированную жабную прогу, если она не обработано специально абсусфактором, можно практически полностью декмпилировать в исходник. Потеряется совсем чуть-чуть: комментарии, анонимные кассы, всякий синтаксический сахар для итераторов, но это мелочи.

Т.е. JIT компилятор имеет все тоже, что и AOT компилятор + рантайм информацию. Выходит, что JIT по крайней мере не хуже.

dizza ★★★★★
()
Ответ на: комментарий от dizza

>>А ничего, что именно эти красноглазики (Гослинг, Стил и ко.) и создали Java?

Они как раз такие не красноглазики, а умные люди.


самые натуральные красноглазики. Стил — это член коммитета по стандартизации ANSI CL и один из авторов Scheme. Гослинг — красноглазик-смоллтокер, автор Gosling Emacs. Я бы удивился, если бы он лиспа не знал.
Эти красноглазики упростили спеки Scheme, Cl, Smalltalk, добавили синтаксис C++ и модули от Modula-2 — и получилась жаба. При том, общеизвестный факт, что тот же сборщик мусора и байткод были в Oberon-2 лучше реализованы.

anonymous
()
Ответ на: комментарий от dizza

> Истинны гуру уметт готовить даже вижуал бейсик.

тебе процитировать эрика наггума про kitchen sync?
http://www.loper-os.org/?p=165 :

On the idiotic fallacy that “a good programmer shouldn’t care about language choice”:

Using such inferior languages is like asking a chef who could have done wonders with any kind of raw materials, to use a dirty kitchen, a broken refrigerator with food that is about to die a second time, broken tools, and brownish tap water that tasted of swamp land. His first task would be to clean up the place. Creating food in there would be the furthest from his mind. That’s how I feel about Perl and C++. I prefer to call it “good taste”, not “tunnel vision”. I don’t like rap, either. Call me intolerant.

anonymous
()
Ответ на: комментарий от anonymous

>Предварительно убрав все то, что не осилили понять. То есть, почти все.
Например?

Это все от того, что ты не в теме.

Код на лиспе динамически типизирован(в общем случае). Т.е. метаинформация о конкретных типах не имеет права в нем существовать.

for, do, while, if, switch

Это глупые примеры. Их и из ассемблера x86 можно однозначно транслировать назад.
А вот как насчет LINQ?

anonymous
()
Ответ на: комментарий от anonymous

И? Знать лисп, это не значит быть красноглазиком. И не значит быть умным. Ну как дети малые, емае.

Красноглазики - это тупые задроды, которые с одной стороны кричат про крутость и невъебенность лиспа, а с другой стороны кричат про какую-то интерпрайзность и смерть всем велосипедам. По крайней мере это 2 самых распростренненых типа тупых задротов на лоре, которые к тому же любят сталкиваться лбами.

dizza ★★★★★
()
Ответ на: комментарий от anonymous

тебе процитировать эрика наггума

Мне не нужны ни чьи цитаты, что бы думать (впрочем, это не запрещает мне все же цитаты читать). Так вот твой эрик мудак, потому, что подготовить рабочее месте, так сказать кухню, нужно лишь один раз. Потом можно спокойно готовить профит. Уловил суть, уважаемый анон? Так всегда, инвестируешь вначале в инструмент, потом пожинаешь плоды. В конце концов по достижению какого-то уровня сложности любой интсрумент требует допиливания. Так что такой скил допиливания не лишний.

dizza ★★★★★
()
Ответ на: комментарий от anonymous

и как конкретно ты собрался допиливать вижуал бейсик?

Ну ты блин даешь такие вопросы задавать без контекста. Во первых не факт что для какой-то задачи придется его допиливать. Протой и понятный код можно писать на любом языке. В общем-то много не надо.

dizza ★★★★★
()
Ответ на: комментарий от dizza

Уточнение на счет любого языка. Конечно не любой, а позволяющий писать в соотвествии с методологией структуурного программирования.

dizza ★★★★★
()
Ответ на: комментарий от anonymous

>> Ничего себе новости. Что, даже _намного_?

Уже и клоуны подтягиваются.

Ты давно уже здесь.

Во первых, нет арифметики указателей.

Капитан?

Во вторых, есть полная информация о типах.

В GIMPLE она есть.

В третьих, есть полностью абстрагированный ООП, никаких тебе конкретных плясок с v-table, а просто call virtual.

После заявления о легком восстановлении if, switch и while из скомпилированного кода, это просто смешно.

tailgunner ★★★★★
()

Кроме того, на практике (мало имел дела с жабой, но), к примеру, исходники ICQ клиентов для мобильных телефонов - разные для разных моделей телефонов, то переносимости байткода всё равно не существует. Итого, вывод: JIT придуман для замедления работы железа и для того, чтобы оно скорее потребовало апгрейда.

В телефонах для поддержки спецификаций J2ME чаще используется не JIT, а AOT (Ahead-of-Time) compiler. При загрузке или при первом запуске приложения AOT компилятор полностью компилирует байткод в нативный для данного процессора, либо оставляет некоторые куски байткода для выполнения на Java-ядре основного процессора (технология непосредственного исполнения — picoJava). Таким образом, получается полностью нативное выполнение мидлета без использования JIT.

iZEN ★★★★★
()
Ответ на: комментарий от tailgunner

> Капитан?

Вот интересный ты человек. Обычно люди со временем умнеют. Ты же с каждым годом все больше недоумок.

Повторить для тупых? VM с арифметикой указателей - ниже уровнем, чем VM без таковой.

В GIMPLE она есть.

Ее нет даже на уровне исходников на C, ха ха ха!

После заявления о легком восстановлении if, switch и while из скомпилированного кода, это просто смешно.

Ну недоумок же. Реальный недоумок. google: reflector.

Ты вообще, хотя бы примерно представляешь себе устройство JVM и CLR?

anonymous
()
Ответ на: комментарий от anonymous

> Это глупые примеры. Их и из ассемблера x86 можно однозначно транслировать назад.

Однозначно - нельзя.

А вот как насчет LINQ?

А как насчет показать язык, где конструкции уровня LINQ участвуют в оптимизациях?

Итак, тут какой-то тупица вещал, что мол «тупой байткод» слишком низок уровнем, чтобы делать с ним оптимизации, которые «умные компиляторы» умеют делать со своим внутренним представлением. Как насчет за этот базар ответить? Или все уже поняли, что JVM и CLR уровнем намного выше любого промежуточного кода в «классических» компиляторах?

anonymous
()
Ответ на: комментарий от anonymous

Если бы программа предкомпилировалась в момент установки, а не первого запуска, то это было бы не так критично. .NET не нужен, но тем не менее этот подход — вполне годная альтернатива JIT.

Ага. J2ME KVM пошла именно по этому пути.

iZEN ★★★★★
()
Ответ на: комментарий от anonymous

>А вот как насчет LINQ?

Вообще-то, есть эквивалентные по смыслу конструкции на обычном C#, которые разве что по сравнению с LINQ более «многословны». Выражения LINQ по сути - сокращенная форма записи того, чем маялись шарперы до него. Никто не мешает вместо лямбд с SQL-подобными запросами писать цепочки методов where().any().first() с блэк джеком и делегатами (одно на другое меняется на раз два). Хуже, когда человек использует модные лямбды и запросы, потому что модно (велели ему так глобально переписать, потому что в этом сезоне «красиво» синоним «декларативно» и «Ъ-энтерпрайзно же!!!111») - а рядом в цикле строки «плюсиками» 100500 раз конкатенируются по-прежнему.

slackwarrior ★★★★★
()
Ответ на: комментарий от tailgunner

> > при N->infinity предварительная компиляция выигрывает.

...по скорости. Но, кроме скорости, есть и другие соображеия.

Это еще при учете, что числа взяты «с потолка». Ошибиться в паре таких чисел на порядок — плевое дело. При этом итоговая ошибка уже будет на 2 порядка, и для «выигрыша компиляции» будет требоваться не 40 запусков программы, а 4000 :) Что есть очевидный фейл, ибо запускаемая программа должна при этом быть одной версии.

balodja ★★★
()
Ответ на: комментарий от anonymous

> Обычно люди со временем умнеют. Ты же с каждым годом все больше недоумок.

Твое мнение очень важно для меня.

В GIMPLE она есть.

Ее нет даже на уровне исходников на C, ха ха ха!

Сам пошутил, сам посмеялся, умничка.

После заявления о легком восстановлении if, switch и while из скомпилированного кода, это просто смешно.

Ну недоумок же. Реальный недоумок. google: reflector.

Если ты думаешь, что я не знаю о Reflector, то ты даже более напыщенный дурак, чем кажешься на первый взгляд . Из байт-кода нужную информацию приходится _восстанавливать_. Видишь разницу с промежуточным уровнем компилятора?

Ты вообще, хотя бы примерно представляешь себе устройство JVM и CLR?

Да. А что, есть люди, которые этого не передставляют?

tailgunner ★★★★★
()
Ответ на: комментарий от dizza

>Но во-первых это критично только для очень серьезных проектов

??? на мой взгляд, это наиболее критично для десктопного софта, ради чего-то серьезного можно и подождать

annulen ★★★★★
()
Ответ на: комментарий от balodja

> итоговая ошибка уже будет на 2 порядка, и для «выигрыша компиляции» будет требоваться не 40 запусков программы, а 4000 :)

Если соотношение времени работы компилятора и времени работы программы устраивает заказчика, то всё нормально:) Т.е. относительно небольшой оверхед при старте и иногда «докомпилирование» во время работы - вполне приемлемо за переносимый бинарь и адаптивность _машинного кода_ к нагрузкам (JIT автоматически проводит то, что в gcc называетс PGO).

Вот, кстати, интересное обсуждение с кучей ссылок: http://lambda-the-ultimate.org/node/3851

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.