LINUX.ORG.RU

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


0

2

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

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

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

★★★★★

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

> тем, например, что мне нужно использовать свой алгоритм шифрования при передаче данных. Или свой тип сертификата.

решил поторговать snake oil? твой апплет разберут до последнего битика и выяснят, как он работает

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

а ява и ява-апплеты вполне резонно запрещены в особо секурных условиях

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

>не факт, оно сольёт скомпилированной под конкретную архитектуру программе

И только при использовании оптимизации программы целиком и PGO

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

«она изначально работает не то, что медленнее скомпилированной, а даже медленнее такой же интерпретированной программы» - зато потом она работает в разы быстрее.

Пусть программа запускается за всю жизнь компьютера N раз и тратит, допустим, на каждый запуск 1000 процессорных циклов (без JIT). Подключаем JIT. Анализ частоты добавляет ещё 100 циклов, плюс компиляция добавляет ещё 200 циклов. В результате, наша программа с JIT начинает тратить 500(исполнение до выявления узких мест)+100(анализ)+200(JIT компиляция 10% горячего кода)+50(ускоренное в 10 раз исполнение с JIT), итого 850циклов. С JIT мы сэкономили N*(1000-850)=N*150 циклов. Если мы компилируем всю программу целиком и сохраняем результат компиляции на диск, то получаем: компиляция всей программы - пусть будет хоть 2000 циклов. После компиляции программа ускоряется в 10 раз и занимает 100 циклов. Итого, общие затраты CPU будут 2000+100*N. Очевидно, что при N->infinity компиляция «сразу» выигрывает перед JIT. В данном случае, она начинает выигрывать при N>40. Как правило, любая программа, установленная на компьютере, запускается больше 40 раз. Цифры взяты с потолка, но закономерность тут общая, при N->infinity предварительная компиляция выигрывает.

Насколько я теперь понимаю, это неверно там, где есть дисковый jit-кеш, сохраняющий результаты компиляции между запусками программы, но, как я опять же только предполагаю, jit-кеш есть только в .net.

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

>Кэш нативного кода + уменьшенное число ветвлений и повышенное cache-

locality

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

Ну, в общем, тема вроде бы раскрыта. Я ожидал, честно говоря, ещё аргументов на тему того, что байт-код компактнее нативного и поэтому он выгоднее, если кусок исполняется один раз (меньше читать с диска).
Но такого аргумента не прозвучало, и теперь я не знаю, есть ли такой аргумент в природе или нет.

Прочие аргументы для меня неубедительны.

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

> решил поторговать snake oil? твой апплет разберут до последнего битика и выяснят, как он работает

Да хоть открытым сделать (см dogtag-pki). Важно то, чтобы ходящую информацию было сложнее прочитать.

а ява и ява-апплеты вполне резонно запрещены в особо секурных условиях

в достаточно секурных условиях ими как раз и пользуются :)

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

чорт :/

Отмазка: ну это уже проблема MAC OS/PPC, тем, более судя по теме про гостлинга apple с oracle договорились.

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

> возникает вопрос - а зачем тогда вообще нужен именно JIT? Ведь можно оставить только возможность прекомпиляции, тогда JIT будет не нужен.

В .NET программа всегда предкомпилируется (если это не было проделано явно с помощью утилиты ngen). Видимо, о JIT можно говорить в контексте какой-нибудь хитроумной оптимизации сгенерированного нативного кода уже в процессе исполнения. Сложная материя.

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

>jit-кеш есть только в .net

Дисковый - возможно. А в памяти его кто только не держит. особенно эмуляторы. И еще можно процессоры transmeta вспомнить.

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

>А теперь ставим себя на место разработчиков Java. Могли они сделать это сразу?

«Сразу» жаба была исключительно интерпретатором. Все JITы встраивались в нее уже в более поздних версиях, исходя из принципа, что байткод остается байткодом, написано однажды — отлаживается^W работает везде, а JIT является прозрачной надстройкой над интерпретатором.

Почему они потом не разработали полностью компилируемого варианта жабы? Все же от части кода, скомпилированной JIT-ом и имеющей возможности в любой момент обратиться к интерпретатору до полноценной самостоятельной программы — дистанция огромного^W немалого размера.

Потом, Жаба ведь не единственный язык, не компилирующийся целиком в нативный код. Perl'ом, Python'ом, Javascript'ом, Ruby и прочим все как-то пользуются, и ничего. Но, опят же, bytecode vs. native — это давний холивар.

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

Ты доверяешь продавцам, у которых цель - продать тебе что-то.

Я не верю в теории заговора, уж извините.

Не знал. Спасибо. Вот и мне так кажется, что это - оптимальный вариант. И сразу после этого возникает вопрос - а зачем тогда вообще нужен именно JIT? Ведь можно оставить только возможность прекомпиляции, тогда JIT будет не нужен.

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

Это - не преимущество JIT. То же самое может сделать и «статический» компилятор, если в нём есть соответствующие переключатели.

Вы предполагаете пользование source-based дистрибутивами? Это во-первых неудобно для многих (я использовал Gentoo где то полгода, в итоге перестал, мне не нравится, что установка новой программы или обновление старой занимает так много времени), во-вторых сложно совместить с проприетарным софтом.

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

Вообще-то, разные версии J2ME действительно не 100%-совместимы

Может быть, уж не знаю, что там с этой J2ME, накосячил видимо Sun с соблюдением спецификаций, хотя я слышал, что он таки совместим на 100%, просто его недостаточно для реальных приложений, и всем приходится использовать проприетарные модули. В любом случае J2ME сдох, а чтобы сделать некроссплатформенную программу на обычной Java, надо постараться. У меня пока ни разу не получалось. Все проблемы, которые я видел, в итоге сводились к import com.sun.something.

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

в частности, анализ и частичная пересборка программы во время запуска (например, развиртуализация функций, возможно escape-анализ) вполне возможно полезен (и мог бы делаться в че-то типа llvm); вот только я бы не назвал это JIT

А как это назвать?

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

>> Нет, он не напрямую влияет на запуск компилятора.

А как?

А он переключает используемую версию VM на предназначенную для серверов. Помимо способа компиляции там еще есть и другие оптимизации, суть которых сводится к увеличению производительности за счет увеличения времени запуска и, ЕМНИП, потребления памяти. Но и «серверный» компилятор не компилирует всю программу сразу.

Можно указать VM, через сколько вызовов каждого метода его компилировать, соответственно, выставив значение «1», можно компилировать каждый метод при первом же вызове. В HotSpot'е этим заведует какая-то из хорошо спрятанных опций командной строки. Но это, естественно, далеко не всегда увеличивает производительность, чаще это ее уменьшает.

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

> Или хотя бы ссылки на людей, которые сталкивались, пока это похоже на сказки).

http://www.emu-land.net/forum/index.php?action=profile;u=14400;sa=showPosts;s...

Случайно попалось :-)

Далее существуют NUMA-архитектуры, в которых JIT может сильно повлиять на скорость работы программы, причём в зависимости от обрабатываеммых данных.

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

ведь не от балды в java решения принимаются

Не от балды, но мотивы могут быть разными. Sun - это не настоящее Солнце, которое всем светит совершенно задаром, Sun - это коммерческая организация. И что-то я помню, они серверами торговали. А если кто-то торгует железом, ему выгодно, чтобы программы были более прожорливыми и требовали апгрейда железа. Так что мы не можем сделать никаких выводах о технических преимуществах JIT только на основании разумности разработчиков Java.

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

> Цифры взяты с потолка, но закономерность тут общая, при N->infinity предварительная компиляция выигрывает.

цифры надо брать не с потолка, а из результатов профилировки реальных программ, а так это словоблудие, которое даже не надо опровергать

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

OK, допустим ты написал свою программу на Java SE 6. Как запустить ее на Mac OS/PPC?

java -jar myprogram.jar?

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

> http://www.emu-land.net/forum/index.php?action=profile;u=14400;sa=showPosts;s...

Случайно попалось :-)

а это точно к яве относится?

Ну, в таких задачай ещё не факт, что JIT хорош. Не знаю, что такое NUMA, пусть у нас есть веб-сервер с поддержкой разных языков.

goto wiki; ну допустим у нас сервер с 16 процессорами, каждые 4 из которых с общей памятью. Нужно чтобы обрабатываемые данные раскидывались на подходящие. После предоставляения собранного со стат компиляцией решение меняем архитектуру, ну или в срочном порядке отключаем 4 узла под другие задачи :).

Мы запускаем его утром во Владивостоке. Проходит первый час, и всё оптимизируется JIT-ом. А потом наступает утро в Европе и проверка «а не китайский ли у нас язык?» начинает, как правило, возвращать совсем другой результат, чем раньше.

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

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

> Потому что в джаве есть понятие ClassLoader
Ну, это тоже не требует JIT. Можно включить обязательную компиляцию в этап загрузки класса в память. Сам по себе вызываемый в рантайме компилятор - это ещё не JIT. JIT - это совокупность компилятора, средств анализа исполнения и стратегия замены байт-кода на нативный. Компилятор в рантайме есть, к примеру, в CL и Форте, однако, это не JIT. То же касается и байт-кода, генерируемого на лету - его можно сразу компилировать.

В общем, пока что итоги выглядят так:

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

С точки зрения надёжности, дисковый кеш байт-кода представляет опасность, поскольку он может оказаться неверным при смене зависимостей. Это - тоже аргумент в пользу JIT. Кроме того, наличие файлов на диске делает программу более уязвимой и несколько усложняет её конфигурацию. Однако, можно пытаться отследить зависимости и целостность кешированного нативного кода в момент загрузки и перекомпилировать только устаревшее. Это, скорее всего, будет дешевле, чем JIT.

Жду, кто ещё что напишет.

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

>По сути, единственное (спорное) преимущество JIT перед статической компиляцией - это оптимизация ветвлений.

4.2 же, главное преимущество - агрессивный инлайнинг

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

а при длительной работе и хорошем качестве JIT - с PGO-оптимизированным бинарником

А чем это принципиально от JIT'а отличается? ;)

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

>С точки зрения надёжности, дисковый кеш байт-кода представляет опасность, поскольку он может оказаться неверным при смене зависимостей.

смене чего?

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

> По сути, единственное (ну которое у меня хватает ума понять) преимущество JIT перед статической компиляцией - это оптимизация ветвлений.

грубо, но fixed

история JIT: http://portal.acm.org/citation.cfm?id=800017.800542

что умеет JIT: http://stackoverflow.com/questions/3228141/questions-about-possible-javaor-ot...

почему JIT лучше чем то, что ты предлагаешь: http://stackoverflow.com/questions/2106380/what-are-the-advantages-of-just-in...

гугл за 5 минут, я не верю, что перед тем, как задавать подобные тролячьи вопросы нельзя было это поискать

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

>ну или в срочном порядке отключаем 4 узла под другие задачи

у Явы, насколько я помню, с распараллеливанием не все гладко. А если код многопоточный, то изменение числа узлов не должно уменьшить проиводительность в расчет на узел (ну только если для эфективной реализации нужно не менее 16 потоков :)

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

Я вот разницы практически не наблюдаю. Так и так когда ты с PGO бинарь скомпилил, то там вставляется туева куча всего для сбора статистики после чего вызывается повторная компиляция. JIT имеет точно ту же самую информацию и точно также может в конце концов попрофилировать вдоволь прогу и скомпилить полностью нативный вариант с максимальной оптимизацией и пускать уже его. К тому же с JIT ты можешь на лету менять байткод в приложении, то есть фактически у тебя есть eval(), а это в умелых руках over9000 новых возможностей.

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

> а это точно к яве относится?
Я спрашиваю не про яву, а про JIT вообще.

После предоставляения собранного со стат компиляцией решение меняем архитектуру

Каков выигрыш в конкретном примере, в цифрах, по сравнению со статически компилированной программой? Похоже, ситуация выглядит так, что нам дали (на Java) только JIT и интерпретатор, а статически программу скомпилировать невозможно, т.е., на мой вопрос и ответить-то толком нельзя.

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

Для того, чтобы это было возможно, программа должна повторять анализ повторяемости и после того, как код был скомпилирован в нативный. И тут вопрос о том, что дороже, снова встаёт во весь рост. Что дороже - просто ветвление, пусть не оптимизированное, или ветвление оптимизированное, но с постоянной записью результатов?

убирание боксинга анбоксинга

О боксинге чего идёт речь? Я знаю только боксинг числовых типов, которые точно известны. Но какое это отношение имеет именно к JIT, чем статическая компиляция не подходит?

несоздавание временных объектов для доступов к полям или создание их на стеке дадут не меньший эффект

Если бы не было возможности загрузки классов в рантайме, я бы сказал, что JIT тут не при чём.

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

> у Явы, насколько я помню, с распараллеливанием не все гладко. может мало опыта, но не сталкивался с проблемами, которых нету у других языков.

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

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

>Отмазка

Это не единственный пример. Хотел было сказать, что официально Java SE 6 существует только на x86, x86_64 и Sparc, однако гугль подбросил ссылки на версии для IA64. Однако для всяких MIPS, SH4 и пр. существует только Java ME или «альтернативные» JVM, которые не поддерживают (или в лучшем случае не полностью поддерживают) Java SE 6). С ARM ситуация вроде бы меняется в лучшую сторону

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

> Я спрашиваю не про яву, а про JIT вообще.

кривая реализация — это проблема этой реализации, а не технологии. Так что с вас всё ещё пример проблемы с JIT, где появляются «плавающие» ошибки.

Каков выигрыш в конкретном примере, в цифрах, по сравнению со статически компилированной программой? Похоже, ситуация выглядит так, что нам дали (на Java) только JIT и интерпретатор, а статически программу скомпилировать невозможно, т.е., на мой вопрос и ответить-то толком нельзя.

я думаю, что можно поискать исследования на тему. И поискать информацию как отключить JIT

О боксинге чего идёт речь? Я знаю только боксинг числовых типов, которые точно известны. Но какое это отношение имеет именно к JIT, чем статическая компиляция не подходит?

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

Если бы не было возможности загрузки классов в рантайме, я бы сказал, что JIT тут не при чём

Как раз таки при чём, может таки почитаешь теорию, или хотя бы презентации разработчиков ;) ? так много возможностей как убрать лишние создания объектов, заинлайнить код, и даже можно найти объяснения, почему нельзя эти оптимизации сделать статически.

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

Нет, тут все прозаичнее: в случае компиляции в натив, качество использования многопроцессорной системы определяется только кодом, в случае с JIT - еще и качеством распараллеливания самой виртуальной машины (JIT-компилятора, сборки мусора и пр.)

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

> смене чего?
Ну, если программа грузит какой-нибудь jar-файл, то нужно отслеживать, что при замене этого jar-файла на другой кеш нативного кода был должным образом очищен (я описАлся, имелся в виду кеш нативного кода).

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

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

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

>Так и так когда ты с PGO бинарь скомпилил, то там вставляется туева куча всего для сбора статистики после чего вызывается повторная компиляция.

Да. А полученный бинарь уже не перекомпилируется.

JIT имеет точно ту же самую информацию и точно также может в конце концов попрофилировать вдоволь прогу и скомпилить полностью нативный вариант с максимальной оптимизацией и пускать уже его.

PGO делает разработчик, JIT тратит ресурсы клиента. Да, можно утверждать, что PGO на машине разработчика не будет оптимальным для машины клиента, в таком случае клиент может, например, собрать приложение с параметром «сделать PGO», после чего (спустя несколько часов или дней ;) запускать нативное приложение

Эта схема сливает только в случае дополнения старой программы новыми модулями - JIT переоптимизирует систему в целом с учетом произошедших изменений

К тому же с JIT ты можешь на лету менять байткод в приложении, то есть фактически у тебя есть eval()

Давно известно, что самомодифицирующийся код - это плохо. А получить eval() можно встроив в свою нативную программу скриптовый интерпретатор, например Lua, JS или Python

annulen ★★★★★
()

JIT позволяет осуществлять более качественну оптимизвцию, чем AOT за счет накопления статистики и прочих рантаймовых штук. Особенно выигрыш заметен, когда на стадии компиляции вообще мало что извествно. К примеру для языков с динамической типизацией JIT вообще единственный способо быть скомпилированными эффективно. Не нужно думать что все языки такие же близкие как машинным кодам как и Си.

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

> кривая реализация — это проблема этой реализации, а не технологии. Так что с вас всё ещё пример проблемы с JIT, где появляются «плавающие» ошибки.
«Победы ученика - это победы школы, поражения ученика - это поражения ученика», что ли?

То, что JIT позволяет не проводить лишних операций

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

Насчёт инлайна - согласен, что тут может быть смысл статистического анализа.

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

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

> гораздо опаснее подмена кэша - на сановском форуме мне привели этот аргумент против долгоживущего кэширования
Ну, можно какую-нибудь md5 сумму проверять.

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

> ну если быть до конца честным это пафосные идеи разработчиков: анализ архитектуры для распределения данных
Ну вот, а я уже почти поверил.

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

>А если кто-то торгует железом, ему выгодно, чтобы программы были более прожорливыми и требовали апгрейда железа.

Это ынтерпрайзы детка, тут так не рассуждают. В данном случае, логика такая «лучше заплатить за мощный сервер и нанять индусов, чем выискивать программистов на С++ с прямыми руками»

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

> В данном случае, логика такая «лучше заплатить за мощный сервер и нанять индусов, чем выискивать программистов на С++ с прямыми руками»
Но и если эту логику довести до конца, то JIT тем более не нужен. Заплатить за ещё более мощный сервер и пусть будет без JIT :-)

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

>можно работающий пример падения функции из-за ошибки JIT? Или хотя бы ссылки на людей, которые сталкивались, пока это похоже на сказки).

падений не видел, а неправильную работу видел, не уверен что могу раскрывать подробности, и что это не было ошибкой в коде, а именно в jit, но наблюдалось следующее: на x86 и под сановской и под ibm-овской jre все было хорошшо, под z/os при выключенном jit тоже, а при включении одна и та же функция при одних и тех же входных данных в примерно 5% случаев выдавала результат, отличный от ожидаемого.

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

значит, IBM-овцы накосячили :) С кем не бывает

annulen ★★★★★
()

- время отклика увеличивается. Вызов компилятора приводит к неожиданным затратам CPU, замена кода должна производиться с какой-то блокировкой (хотя и небольшой).

- надёжность снижена. Ошибки самой реализации JIT могут вылезти в произвольное время и их появление зависит от полного пути исполнения программы. Т.е., их крайне сложно диагностировать.

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

Karapuz ★★★★★
()

Хорошее объяснение работы JIT youtube.com/watch?v=WmBb_C5uOjA

им надо не про шар,а про хyz обьяснять,тогда бы может быть они поняли

Karapuz ★★★★★
()

Есть ещё вариант — предкомпиляция байт-кода при первом запуске или при установке. В .NET что-то похожее.

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

<цитата с хабра>
У .NET есть проблемы с холодным стартом. При первом запуске какого-либо функционала, этот код необходимо откомпилировать в родной для процессора. Для пользователя это выливается в долгий запуск и задержках (лагах) при работе с программой.
Если хочется, чтобы все сразу и быстро запускалось, надо ЗАРАНЕЕ откомпилировать весь код приложения. Это занимает ВРЕМЯ, иногда довольно много времени.
</цитата с хабра>

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

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

anonymous
()

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

Не знаю, как у других, но у LLVM функция компилируется при необходимости ее выполнить или получить на нее указатель. Лишних и непредсказуемых затрат времени нет.

- программа несёт в себе компилятор (и становится тяжелее)

Где?

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

Такое делается не везде, не всегда, и не во всех случаях вообще возможно.

- время отклика увеличивается. Вызов компилятора приводит к неожиданным затратам CPU, замена кода должна производиться с какой-то блокировкой (хотя и небольшой).

Может замедлится только запуск программы, а так же операции типа eval(). Все остальное только ускорится.

- надёжность снижена. Ошибки самой реализации JIT могут вылезти в произвольное время и их появление зависит от полного пути исполнения программы. Т.е., их крайне сложно диагностировать.

При чем здесь JIT?

Единственное, что мы за это получаем - переносимость байткода.

Не только. Мы получаем все то же, что и от интерпретируемых языков, только в десятки раз быстрее.

В любой технической ситуации, которую я могу помыслить, я бы предпочёл компилятор.

Есть очень много случаев, когда лучше подойдет именно интерпретируемый язык, и кроссплатформенность здесь ни при чем.

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

Просто разрабы часто используют нестандартные проприетарные API, присутствующие только у одного-двух производителей. Это их проблемы, а не проблемы Java.

Итого, вывод: JIT придуман для замедления работы железа и для того, чтобы оно скорее потребовало апгрейда.

Как бы наоборот - JIT, в сравнении с интерпретацией, ускоряет выполнение в разы. При этом программа не лишается преимуществ, предлагаемых интерпретацией.

Где изъян в моей логике?

Итого: в вашей логике море изъянов.

PS. Я не утверждаю, что JIT решает все проблемы. На программе, где каждая вторая строка - eval, JIT может оказаться медленнее интерпретации. На очень маленькой программе, совершающей мало действий, интерпретация может оказаться быстрее. На программе, в которой море кода, который может быть ни разу не вызван, интерпретация может оказаться быстрее. Но при этом в среднем случае JIT дает очень значительный выигрыш.

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

Ответ, конечно, большой и обстоятельный. Особенно, вот в этом месте:

Как бы наоборот - JIT, в сравнении с интерпретацией, ускоряет выполнение в разы.

При том, что я сравнивал с компиляцией. Слава Богам, технология компиляции была доступна уже тогда, когда Java и в планах не было.

Не знаю, как у других, но у LLVM функция компилируется при необходимости ее выполнить или получить на нее указатель. Лишних и непредсказуемых затрат времени нет.

Да-да, не считая того, что с обычной компиляцией я буду запускать компилятор изредка (при установке и смене программы), с LLVM - при каждом запуске. Я надеюсь, никто не станет утверждать, что компиляция ничего не стоит по затратам времени.

А теперь насчёт оптимизаций, связанный со сбором статистики. Давайте сразу скомпилируем программу в нативный код (при установке), но оставим и байт-код, но его нигде не будем вызывать. А дальше запустим программу с JIT и со сбором статистики. Если где-то мы увидели, что наш нативный код недостаточно быстр (неоптимизирован инлайн, безусловный переход, боксинг объектов), то мы заменим этот нативный код на другой.

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

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

под z/os при выключенном jit тоже, а при включении одна и та же функция при одних и тех же входных данных в примерно 5% случаев выдавала результат, отличный от ожидаемого


Спасибо, прекрасная иллюстрация к моему тезису. Как раз та самая плавающая ошибка.

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

Могу посоветовать почитать из книжки CLR via C# (3е издание) страницы с 6ой по 20ю. Там про .NET, конечно, зато четко и ясно все изложено на достаточном уровне, чтобы нормальное понимание сложилось. Там же кстати написано, почему NGen на большом круге задач не лучше, а иногда и хуже JIT'а.

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