Лингвофорум

Общий раздел => Наука и техника => Компьютеры => Тема начата: Алексей Гринь от ноября 27, 2010, 01:57

Название: V8
Отправлено: Алексей Гринь от ноября 27, 2010, 01:57
WARNING. В данном посте уровень ЧСВ выше допустимых норм.

Ну пипец. Читаю доку от гугла. В хвалёном-расхвалёном яваскрипт-движке V8 поначалу был такой убогий джиттер.

Они фигачили всё через стек по примитивнейшим шаблонам (готовым кускам). А потом проходились ещё раз, выискивая известные паттерны на assembly block boundaries и упрощая их (типа push eax; pop eax;). Ну лол же. О всяких там register allocator'ах говорить не приходится.

Я, убогий гуманитарий, не читая никакой литературы, так и сделал в своей первой поделке (только у меня вышло лучше). А ещё боялся, что у меня тормоза (хотя медленнее получилось всего на 14% от дебуг-билдов си в паре кривых бенчей — я доволен).

Для сравнения "i = j + 666"

V8, ранняя версия, после оптимизации (!):
push [ebp+j.offset]
mov ebx, 666
pop eax
add eax, ebx
push eax
mov [ebp+i.offset], eax
pop eax

Но пишут, что потом это убрали.

Grin's SuperJit 2000, тоже раннее, тоже после оптимизации:
mov eax, [ebp+j.offset]
push eax
mov eax, 666
pop ecx
add eax, ecx
mov [ebp+i.offset], eax


Скипнул в конец, вот так V8 делает щас:
push [ebp+j.offset]
mov eax, 666
pop ebx
add eax, ebx
mov [ebp+i.offset], eax


Через два шага оптимизации у V8 результат почти как у меня умного, только у меня джиттер немного ступил в этом месте:

mov eax, [ebp+j.offset]
push eax


Такого правила в оптимизаторе просто нету. Завтра сделаем. И будет как у Ларса Бака 100%. Разница только в регистрах.
И ведь сравните: я простой гуманитарий без спецобразования, а Ларс Бак мегакрутой магистр программирования, оплачиваемый гуглом, а наши джиттеры выдают абсолютно идентичный код. Почему так? Да просто технари бездари и тупицы, по которым плачет биореактор, а я умничка и мозг.

Справедливости ради надо сказать, что у них строится по AST, а у меня по байткоду.
Завтра внимательнее дочитаю доку, а щас спатеньки, господа филолохи!
Название: V8
Отправлено: Алексей Гринь от ноября 27, 2010, 09:49
В топку, товарищи!

push [ebp+j.offset] это 5 клоков,
mov eax, [ebp+j.offset]; push eax — 4 клока.

Всё-таки я круче V8.
Название: V8
Отправлено: myst от ноября 27, 2010, 09:58
Цитата: Алексей Гринь от ноября 27, 2010, 09:49
push [ebp+j.offset] это 5 клоков,
mov eax, [ebp+j.offset]; push eax — 4 клока.
Это ты где вычитал?
Название: V8
Отправлено: Алексей Гринь от ноября 29, 2010, 06:52
Цитата: myst от ноября 27, 2010, 09:58
Цитироватьpush [ebp+j.offset] это 5 клоков,
mov eax, [ebp+j.offset]; push eax — 4 клока.
Это ты где вычитал?
Ну посмотрел в 386 manual (другого не нашлося).
push [ebp+j.offset] это 5 клоков,
mov eax,  [ebp+j.offset] — 2, push eax — 2.
Если ничё не напутал.

А вообще интел любит делать короткие, но тормозные инструкции, напр.

enter 8

тормознее аналогичного (хотели ввести полезную инструкцию, но её реально никто так и не использует из-за тормозов)

push ebp
mov ebp, esp
sub esp, 8


В то время как

leave

по скорости такое же как аналогичное

mov esp, ebp
pop ebp


Поэтому джиттер мой генерит такое уродство:

push ebp
mov ebp, esp
sub esp, 8
/* тело функции */
leave
ret 4


Так что когда я применил свой скилл сложения двух чисел, я не был удивлён.
Название: V8
Отправлено: myst от ноября 29, 2010, 09:12
Цитата: Алексей Гринь от ноября 29, 2010, 06:52
Ну посмотрел в 386 manual (другого не нашлося).
push [ebp+j.offset] это 5 клоков,
mov eax,  [ebp+j.offset] — 2, push eax — 2.
Если ничё не напутал.
Ну ты даёшь. :) На сайте Intel'а целые залежи документации по их процессорам, в том числе и по оптимизации ((Google) optimization manual site:intel.com (http://www.google.com/search?client=opera&rls=en&q=optimization+manual+site:intel.com&sourceid=opera&ie=utf-8&oe=utf-8)). В интеловских процессорах инструкции давно транслируются в микрокоманды, которые оптимизируются, кэшируются etc. Начиная с Pentium Pro ни о каких растактовках говорить нельзя, то есть уже 15 лет. ;)
Хочешь узнать реальное время выполнения фрагмента кода, меряй счётчиком.
Название: V8
Отправлено: myst от ноября 29, 2010, 09:39
Вот это руководство должно тебя возрадовать: http://www.intel.com/Assets/PDF/manual/248966.pdf
Вся подборка на всякий: http://www.intel.com/products/processor/manuals/
Название: V8
Отправлено: Алексей Гринь от ноября 29, 2010, 10:05
Цитата: myst от ноября 29, 2010, 09:12
Начиная с Pentium Pro ни о каких растактовках говорить нельзя, то есть уже 15 лет. ;)
Хочешь узнать реальное время выполнения фрагмента кода, меряй счётчиком.
Т.е. хочешь сказать, что push [ebp+j.offset] быстрее? Хрен знает, мне кажется максимум будет одинаковое выполнение. А если выполнение медленнее или такое же, то нефиг оптимизировать. Я это имел в виду.
А intel.com чё-то не открывается (будь проклят волгателеком!).

Цитата: myst от ноября 29, 2010, 09:12
Хочешь узнать реальное время выполнения фрагмента кода, меряй счётчиком.
В том-то и дело, что в лом :)

Тем временем прочитал, что написание нормального аллокатора регистров может ускорить код до 250%. Пытаюся осилить.
Название: V8
Отправлено: Алексей Гринь от ноября 29, 2010, 10:13
Цитата: myst от ноября 29, 2010, 09:12
В интеловских процессорах инструкции давно транслируются в микрокоманды, которые оптимизируются, кэшируются etc.
Ага, только вот дизассемблер говорит, что никто из компиляторов не использует например enter. Такая уж там оптимизация? Гнилой маркетинг какой-нить наверное, а общее отношение осталось тем же...
Название: V8
Отправлено: myst от ноября 29, 2010, 11:17
Цитата: Алексей Гринь от ноября 29, 2010, 10:05
Т.е. хочешь сказать, что push [ebp+j.offset] быстрее?
Я хочу сказать, надо юзать актуальную документацию. :)

Цитата: Алексей Гринь от ноября 29, 2010, 10:05
В том-то и дело, что в лом :)
Если в лом, то в том мануале куча советов по оптимизации, в том числе и относительно выбора инструкций.

Цитата: Алексей Гринь от ноября 29, 2010, 10:13
Ага, только вот дизассемблер говорит, что никто из компиляторов не использует например enter.
Дык, я в курсе (хотя помню, где-то таки видел...). Её сам Intel до сих пор не советует использовать, поэтому и. :)
Название: V8
Отправлено: Алексей Гринь от ноября 30, 2010, 19:02
Ну почитал, образовался по многим пунктам.

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

Хочется выделять регистры, но завис: нашёл, что для аллокации регистров по дереву использовать можно алгоритм Сети—Ульмана, но хз чё насчёт джаст-ин-тайма — чё с производительностью, а так же как это скрестить вместе с аллокацией регистров под локальные переменные (ибо Ульман, как я понял, только для временных значений вычисления expression'а выделяет)...  А этих грёбанных регистров в ia32 всего 6-8... Это типа три регистра на локальные переменные и два — на intermediate values, что ли?

Ещё надо чё-то делать с liveness analysis. По задумке сборка мусора не отложенная, а на основе жизни переменных — как только переменная перестаёт использоваться, объект сразу же удаляется. Код для удаления впендирювается кодогенератором и в байткоде его нет. Хочется совместить эту технику с memory compacting (и тут нужен быстрый-пребыстрый typed stack — и опять хз) — память выделяется по bump pointer allocation, и как только предел достигнут — сжимаем кучу, перезаписывая везде затронутые адреса. И этот liveness analysis как-то надо совместить с распределением регистров.

Пока пытаюсь осилить исходники mono, но может есть чё-то попроще?
Название: V8
Отправлено: Алексей Гринь от ноября 30, 2010, 22:57
Короче, всё придумал, завтра реализую.
Название: V8
Отправлено: Алексей Гринь от декабря 3, 2010, 22:00
Прикольно: если кешировать часто используемый аргумент в регистр, то код работает медленнее на пару процентов, чем если бы я читал аргумент из стековой памяти.

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

Кодогенератор-то выдаёт вот такой хреновый код:

mov ecx, eax
mov eax, edx
add eax, ecx
mov ecx, eax


Надо чё-то придумать.
Название: V8
Отправлено: myst от декабря 4, 2010, 08:50
Это я уже не знаю. Смотри код оптимизирующих компиляторов.
Название: V8
Отправлено: Алексей Гринь от декабря 4, 2010, 13:41
Они там так оптимизируют, что без ста грамм не разберёшь.
Название: V8
Отправлено: myst от декабря 4, 2010, 13:56
Эту тему надо очень глубоко курить, вникать в работу кэшей, конвейера, функциональных блоков, etc. А они ведь отличаются у разных поколений процессоров даже в пределах семейства Intel. По идее JIT должен всё это учитывать и уметь оптимизировать под конкретный процессор, именно в этом его преимущество перед обычным транслятором. Правда, времени на обработку у него в обрез. Для постоянно используемых программ было бы неплохо заюзать фоновую оптимизацию на основе статистики использования. На этой почве вспоминается проект Juice Франца. Он разделил фронтэнд (парсер) и бэкэнд (кодогенератор) транслятора Оберона и получил двойной профит: машинонезависимое представление программы и сохранение всей информации, которая есть в распоряжении обычного компилятора и которая теряется при трансляции в байт-код.
Название: V8
Отправлено: Алексей Гринь от декабря 4, 2010, 14:09
Цитата: myst от декабря  4, 2010, 13:56
По идее JIT должен всё это учитывать и уметь оптимизировать под конкретный процессор, именно в этом его преимущество перед обычным транслятором.
Не обязательно. JIT может быть полезен, когда нужно иметь компактные exe'шники. А я адски ненавижу code bloat. Напр. в случае с C++ шаблоны жрут очень много пространства, т.к. на каждую инстанциацию пишется по реализации. А в образе JIT-файла это может храниться буквально в паре байт и распаковываться по надобности.
Ещё у JIT'а преимущество в динамике. Напр. с помощью JIT'а можно сделать так, что статические конструкторы класса вызываются только при самом первом использовании класса.
Ну и ещё какие-то хитрые трюки можно делать.

У меня задумка-то не просто делать командную строку типа "java main.class".
У меня задумка ближе по духу к VB6 — образ байткода хранится в «в контейнерах». Контейнер может быть exe, app и bin. Образ пишется в ресурс, и читается оттуда. Т.е. есть всего один файл, и VM не нужна.

В этом смысле нужно следовать принципу KISSC ("keep it simple, stupid (and compact)"). Не хочу, чтобы эксешник получался размером в 16 мегабайт.

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

Цитата: myst от декабря  4, 2010, 13:56
Для постоянно используемых программ было бы неплохо заюзать фоновую оптимизацию на основе статистики использования.
Не было ли это запатентовано Sun'ом?
Название: V8
Отправлено: myst от декабря 4, 2010, 15:28
Цитата: Алексей Гринь от декабря  4, 2010, 14:09
У меня задумка-то не просто делать командную строку типа "java main.class".
У меня задумка ближе по духу к VB6 — образ байткода хранится в «в контейнерах». Контейнер может быть exe, app и bin. Образ пишется в ресурс, и читается оттуда. Т.е. есть всего один файл, и VM не нужна.
Не нравятся мне вещи в себе, их функционал невозможно повторно использовать, всё гвоздями прибито.

Цитата: Алексей Гринь от декабря  4, 2010, 14:09
Не было ли это запатентовано Sun'ом?
Франц это публиковал в году эдак 97. Sun тогда вроде ещё в салочки играл.
Название: V8
Отправлено: Алексей Гринь от декабря 4, 2010, 15:57
Цитата: myst от декабря  4, 2010, 15:28
Не нравятся мне вещи в себе, их функционал невозможно повторно использовать, всё гвоздями прибито.
А мне наоборот нравится, т.к. компактно, легко переносимо между компутерами, не требует зависимостей, а — главное — нет проблем с versioning.

Функционал можно использовать повторно, просто нужно создать новый проект и имеющиеся исходники (или obj-файлы байткода) туда перекинуть.

Короче, static linking vs. dynamic linking.
Dynamic linking давно не актуально, ибо памяти на диске давно не один мегабайт.

p.s. Да и то из-за проблем с версиями, например под виндой, давным-давно делается трюк, что все зависимые дллшки дублируются в папке с программой (напр., копия opengl32.dll, c++ runtime library и т.д.) А это убивает всю первоначальную идею dll. Почему бы сразу не статически делать? Я просто скипаю один лишний шаг.
Название: V8
Отправлено: myst от декабря 4, 2010, 16:27
Цитата: Алексей Гринь от декабря  4, 2010, 15:57
А мне наоборот нравится, т.к. компактно, легко переносимо между компутерами, не требует зависимостей, а — главное — нет проблем с versioning.
Зато хрен добавишь нужную функцию или изменишь интерфейс. :(

Цитата: Алексей Гринь от декабря  4, 2010, 15:57
Функционал можно использовать повторно, просто нужно создать новый проект и имеющиеся исходники (или obj-файлы байткода) туда перекинуть.
Лишняя возня с исходниками.

Цитата: Алексей Гринь от декабря  4, 2010, 15:57
Короче, static linking vs. dynamic linking.
Dynamic linking давно не актуально, ибо памяти на диске давно не один мегабайт.
Не совсем так. Можно же сделать изменяемым пакетом. У нас будет один файл, который удобно перемещать, и в то же время останется возможность добавлять код, изменять интерфейс, настраивать параметры (их ведь тоже надо хранить) и пр.
Название: V8
Отправлено: Алексей Гринь от декабря 4, 2010, 16:33
Ты собрался менять функцию/интерфейс у уже скомпонованной программы, отправленной в работу? Модель, которую я предлагаю — это уже конечная стадия распространения и работы. Если нужно менять функцию или интерфейс, то как и в С++ и в любом другом языке, нужно работать с исходниками и obj-файлами — до того, как программа скомпонована в окончательный релиз в виде PE-файла.  Что за бред — менять интерфейс (!) у конечного EXE-релиза.

Цитата: myst от декабря  4, 2010, 16:27
настраивать параметры (их ведь тоже надо хранить)
Вот тоже не понял, какое отношение параметры имеют к бинарнику. Оно должно всё хранится параллельно с бинарником в xml или в ini.
Название: V8
Отправлено: myst от декабря 4, 2010, 17:46
Цитата: Алексей Гринь от декабря  4, 2010, 16:33
Ты собрался менять функцию/интерфейс у уже скомпонованной программы, отправленной в работу?
Да. Понадобилась мне дополнительная функция в моей рабочей программе, зачем мне ждать, когда IBM разродится? Я быстрее сам добавлю. Или там выпрямить упоротый индусский гуй.

Цитата: Алексей Гринь от декабря  4, 2010, 16:33
Что за бред — менять интерфейс (!) у конечного EXE-релиза.
Это будущее. Интерфейс не должен быть прибит гвоздями. В одних случаях нужен гуй, в другий куй, а функции одни и те же. Нахрена пересобирать велосипед?

Цитата: Алексей Гринь от декабря  4, 2010, 16:33
Вот тоже не понял, какое отношение параметры имеют к бинарнику. Оно должно всё хранится параллельно с бинарником в xml или в ini.
Это уже несколько файлов — всё удобство одного флакона во фтопке, опять косметичку надо заводить.
Название: V8
Отправлено: Алексей Гринь от декабря 4, 2010, 18:02
Цитата: myst от декабря  4, 2010, 17:46
Это будущее. Интерфейс не должен быть прибит гвоздями. В одних случаях нужен гуй, в другий куй, а функции одни и те же. Нахрена пересобирать велосипед?
Так ты имел в виду GUI, а не интерфейс в нормальном значении а ля design by contract?

Цитата: myst от декабря  4, 2010, 17:46
ЦитироватьТы собрался менять функцию/интерфейс у уже скомпонованной программы, отправленной в работу?
Да. Понадобилась мне дополнительная функция в моей рабочей программе, зачем мне ждать, когда IBM разродится? Я быстрее сам добавлю. Или там выпрямить упоротый индусский гуй.
И как часто ты вносишь изменения в QT или GTK?
Название: V8
Отправлено: myst от декабря 4, 2010, 18:17
Цитата: Алексей Гринь от декабря  4, 2010, 18:02
Так ты имел в виду GUI, а не интерфейс в нормальном значении а ля design by contract?
Интерфейс для оператора.

Цитата: Алексей Гринь от декабря  4, 2010, 18:02
И как часто ты вносишь изменения в QT или GTK?
Ты не понял, я имею в виду изменение элементов управления в окнах.
Название: V8
Отправлено: Алексей Гринь от декабря 4, 2010, 18:24
Цитата: myst от декабря  4, 2010, 18:17
Ты не понял, я имею в виду изменение элементов управления в окнах.
Так изменил исходник да перекомпилировал, я не понял, в чём проблема. Компиляция в байткод мегабыстрая, ибо мой байткод по сути является сериализированным синтаксическим деревом.
Название: V8
Отправлено: myst от декабря 4, 2010, 18:48
Цитата: Алексей Гринь от декабря  4, 2010, 18:24
Так изменил исходник да перекомпилировал, я не понял, в чём проблема.
Хочеццо мышкой вжик-вжик, и всё.
Название: V8
Отправлено: Алексей Гринь от декабря 4, 2010, 19:06
Цитата: myst от декабря  4, 2010, 18:48
ЦитироватьТак изменил исходник да перекомпилировал, я не понял, в чём проблема.
Хочеццо мышкой вжик-вжик, и всё.
Я не понимаю, о чём ты. Мышкой вжик-вжик сделал, и перекомпилировал.

Приведи конкретный пример, я не понимаю.
Название: V8
Отправлено: myst от декабря 4, 2010, 19:08
Цитата: Алексей Гринь от декабря  4, 2010, 19:06
Я не понимаю, о чём ты. Мышкой вжик-вжик сделал, и перекомпилировал.
Мышкой вжик-вжик сделал и продолжил работу, не заморачиваясь перекомпиляцией и исходниками. За перекомпиляцию не платят, понимаешь? :)
Название: V8
Отправлено: Алексей Гринь от декабря 4, 2010, 19:13
Мне сложно говорить на такие темы по русски, ибо привык по-английски. С трудом пониманию все эти кривые переводы терминов.
Название: V8
Отправлено: Алексей Гринь от декабря 4, 2010, 19:15
Цитата: myst от декабря  4, 2010, 19:08
Мышкой вжик-вжик сделал и продолжил работу, не заморачиваясь перекомпиляцией и исходниками.
Я наконец-то понял. Т.е. ты предлагаешь так:

Есть либа, допустим functional.dll.
К ней лицом прикручены gui.exe и console.exe, так?

Ну тут можно сделать загрузку байткода из raw-файла. При том что VM до сих пор сидит полностью в главном EXE.
Название: V8
Отправлено: myst от декабря 4, 2010, 19:23
Цитата: Алексей Гринь от декабря  4, 2010, 19:13
Мне сложно говорить на такие темы по русски, ибо привык по-английски. С трудом пониманию все эти кривые переводы терминов.
Ты про вжик-вжик? :eat:

Цитата: Алексей Гринь от декабря  4, 2010, 19:15
Я наконец-то понял. Т.е. ты предлагаешь так:

Есть либа, допустим functional.dll.
К ней лицом прикручены gui.exe и console.exe, так?

Ну тут можно сделать загрузку байткода из raw-файла. При том что VM до сих пор сидит полностью в главном EXE.
Для щастья должно быть всё в одном флаконе, в системе естественно должен быть редактор флакона, интерфейс (и текстовый и графический) описывается декларативно на специальном языке, для графического ещё редактор интерфейса (для вжик-вжик) не помешает. Для всех программных интерфейсов должна быть спецификация прямо во флаконе.
Название: V8
Отправлено: Алексей Гринь от декабря 4, 2010, 19:38
Цитата: myst от декабря  4, 2010, 19:23
интерфейс (и текстовый и графический) описывается декларативно на специальном языке, для графического ещё редактор интерфейса (для вжик-вжик) не помешает
Ну это, по-моему, задача за пределами VMExecution Engine (EE). Это уже какие-то конкретные реализации/спецификации должны быть поверх EE. И тут, кстати, динамика пригодится: можно конструировать классы, читая текстовый файл спецификации.

Я вот хочу ядро EE сделать без стандартной либы вообще (в отличие от .NET, который без мегабайтного mscorlib.dll не хочет грузиться, хотя функционала мне нужно 1%, напр.). Может быть, засунуть только поддержку строк, потоков и мьютексов в разряд примитивов. А ты тут предлагаешь такую замуту :)
Название: V8
Отправлено: arseniiv от декабря 4, 2010, 19:41
Offtop
Даёшь быстроту! Её скоро станет ощутимо не хватать.
Название: V8
Отправлено: myst от декабря 4, 2010, 20:17
Цитата: Алексей Гринь от декабря  4, 2010, 19:38
Ну это, по-моему, задача за пределами VMExecution Engine (EE). Это уже какие-то конкретные реализации/спецификации должны быть поверх EE. И тут, кстати, динамика пригодится: можно конструировать классы, читая текстовый файл спецификации.
Ну да, я размечтался о наболевшем. :)
Название: V8
Отправлено: myst от декабря 4, 2010, 20:19
Цитата: arseniiv от декабря  4, 2010, 19:41
Даёшь быстроту! Её скоро станет ощутимо не хватать.
Когда станут доступны 16-ядерные 5 ваттовые атомы? :eat:
Название: V8
Отправлено: arseniiv от декабря 4, 2010, 20:43
Offtop
Цитата: myst от декабря  4, 2010, 20:19
Когда станут доступны 16-ядерные 5 ваттовые атомы? :eat:
Когда-нибудь прогресс процессоров начнёт замедляться. А квантовые компьютеры пока что нарисованы на воде.
Название: V8
Отправлено: myst от декабря 4, 2010, 20:54
Цитата: arseniiv от декабря  4, 2010, 20:43
Когда-нибудь прогресс процессоров начнёт замедляться. А квантовые компьютеры пока что нарисованы на воде.
Когда-нибудь != скоро.
Название: V8
Отправлено: Алексей Гринь от декабря 4, 2010, 20:59
Короче, архитектура кодогенерации оказалась такова, что кешировать аргументы в регистры нет смысла. Посмотрим, что насчёт локальных переменных.
Название: V8
Отправлено: Алексей Гринь от декабря 5, 2010, 02:25
Так-с, архитектура работает вроде, впендюривать оптизимацию очень легко.

C#:
int f(int a, int b) { return a + b + 13; }

Байткод:
ILDARG 0
ILDARG 1
IADD
ILDC32 13
IADD
RET


выворачивается в:
push ebp
mov ebp, esp
sub esp, 8 <-- издержки дебуга, не обращаем внимание
push ecx
mov eax, [ebp+08]
mov ecx, [ebp+0C]
add eax, ecx
add eax, 13
pop ecx
leave
ret 8


Сие является результатом пары доп. строчек (которые, отвлекаясь, я писал весь вечер), что позволило ускориться аж на 16.8% по сравнению с предыдущим состоянием.
Вроде теперь не стыдно людям в глаза смотреть.
Или нет?
Название: V8
Отправлено: Алексей Гринь от декабря 5, 2010, 02:35
Что странно, ровно на 16.8% результат получился быстрее дебуг-билда аналога на mingw-c. Или мозг уже ничё не соображает, или совпадение...