Отслеживание своевременной компиляции - Tracing just-in-time compilation

Отслеживание своевременной компиляции это техника, используемая виртуальные машины к оптимизировать выполнение программы на время выполнения. Это делается путем записи линейной последовательности часто выполняемых операций, составление их к родные Машинный код и выполняя их. Это противоположно традиционному вовремя (JIT) компиляторы, которые работают для каждого метода.

Обзор

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

Технические детали

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

Эти шаги подробно объясняются ниже:

Фаза профилирования

Цель профилирования - выявить горячие петли. Часто это делается путем подсчета количества итераций для каждого цикла. После того, как количество циклов превышает определенный порог, цикл считается горячим и переходит в режим отслеживания.

Фаза отслеживания

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

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

Поскольку трассировка выполняется во время выполнения, трассировка может содержать информация о времени выполнения (например. информация о типе ). Эта информация может быть позже использована на этапе оптимизации для повышения эффективности кода.

Этап оптимизации и генерации кода

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

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

Исполнение

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

История

В то время как идея JIT восходит к 1960-м годам, отслеживание JIT стало чаще использоваться только недавно. Первое упоминание об идее, аналогичной сегодняшней идее отслеживания JIT, было в 1970 году.[2] Было замечено, что скомпилированный код может быть получен из интерпретатора во время выполнения, просто сохраняя действия, выполненные во время интерпретации.

Первой реализацией трассировки является Dynamo, «программная система динамической оптимизации, которая способна прозрачно улучшать производительность собственного потока инструкций при его выполнении на процессоре».[3] Для этого собственный поток команд интерпретируется до тех пор, пока не будет найдена «горячая» последовательность команд. Для этой последовательности создается, кэшируется и выполняется оптимизированная версия.

Позднее Dynamo был расширен до DynamoRIO. Один проект на основе DynamoRIO представлял собой основу для построения интерпретатора, сочетающего трассировку и частичную оценку. Он использовался для «динамического удаления накладных расходов интерпретатора из языковых реализаций».[4]

В 2006 году HotpathVM, первый JIT-компилятор трассировки для языка высокого уровня.[нужна цитата ] был развит.[5] Эта виртуальная машина была способна динамически идентифицировать часто выполняемые инструкции байт-кода, которые отслеживаются и затем компилируются в машинный код с использованием статическое одиночное присвоение (SSA) строительство. Мотивом для HotpathVM было создание эффективной JVM для мобильных устройств с ограниченными ресурсами.

Другой пример трассировки JIT: TraceMonkey, один из Mozilla Реализации JavaScript для Fire Fox (2009).[6] TraceMonkey компилирует часто выполняемые трассировки циклов на динамическом языке JavaScript во время выполнения и специализирует сгенерированный код для реальных динамических типов, встречающихся на каждом пути.

Другой проект, использующий трассировку JIT, - это PyPy. Он позволяет использовать JIT для отслеживания языковых реализаций, которые были написаны с помощью инструментария перевода PyPy, тем самым улучшая производительность любой программы, которая выполняется с использованием этого интерпретатора. Это возможно путем отслеживания самого интерпретатора, а не программы, выполняемой интерпретатором.[7]

Трассировка JIT также была исследована Microsoft в проекте SPUR за свои Общий промежуточный язык (CIL). SPUR - это общий трассировщик для CIL, который также можно использовать для трассировки с помощью реализации JavaScript.[8]

Пример следа

Рассмотрим следующую программу Python, которая вычисляет сумму квадратов последовательных целых чисел, пока эта сумма не превысит 100000:

def квадрат(Икс):    возвращаться Икс * Икся = 0у = 0пока Истинный:    у += квадрат(я)    если у > 100000:        перемена    я = я + 1

След этой программы может выглядеть примерно так:

 петля(i1, y1) i2 = int_mul(i1, i1)		# х * х y2 = int_add(y1, i2)		# у + = я * я b1 = int_gt(y2, 100000) guard_false(b1) i3 = int_add(i1, 1)		# я = я + 1 Прыгать(i3, y2)

Обратите внимание, как вызов функции квадрат встроен в трассировку и как оператор if превращается в guard_false.

Смотрите также

Рекомендации

  1. ^ «Удаление выделения путем частичной оценки в JIT-трассировке» Карл Фридрих Больц, Антонио Куни, Мацей Фийалковски, Майкл Леушель, Самуэле Педрони, Армин Риго - PEPM '11 Материалы 20-го семинара ACM SIGPLAN по частичной оценке и управлению программами - Дои:10.1145/1929501.1929508 Проверено 24 апреля 2012 г.
  2. ^ МИТЧЕЛЛ, Дж. Г. 1970. Проектирование и создание гибких и эффективных систем интерактивного программирования. диссертации в Университете Карнеги-Меллона, Питтсбург, Пенсильвания.
  3. ^ «Динамо: прозрачная система динамической оптимизации» Васант Бала, Эвелин Дюстервальд, Санджив Банерджиа - PLDI '00 Труды конференции ACM SIGPLAN 2000 по разработке и реализации языков программирования - страницы с 1 по 12 - Дои:10.1145/349299.349303 Проверено 28 марта 2012 г.
  4. ^ «Динамическая нативная оптимизация интерпретаторов» Грегори Т. Салливан, Дерек Л. Брюнинг, Айрис Бэрон, Тимоти Гарнетт, Саман Амарасингхе - Продолжение IVME '03 Материалы семинара 2003 года по интерпретаторам, виртуальным машинам и эмуляторам Дои:10.1145/858570.858576. Проверено 21 марта 2012 г.
  5. ^ "HotpathVM: эффективный JIT-компилятор для устройств с ограниченными ресурсамиАндреас Гал, Christian W. Probst, Michael Franz - Proceeding VEE '06 Proceedings 2-й международной конференции по виртуальным средам выполненияДои:10.1145/1134760.1134780.
  6. ^ «Своевременная специализация типов на основе трассировки для динамических языков» А. Гал, М. Франц, Б. Эйх, М. Шейвер и Д. Андерсон - Материалы конференции ACM SIGPLAN 2009 по проектированию и реализации языков программирования, 2009 г.Дои:10.1145/1542476.1542528.
  7. ^ "Трассировка мета-уровня: JIT-компилятор трассировки PyPy" Карл Фридрих Больц, Антонио Куни, Мацей Фийалковски, Армин Риго - ICOOOLPS '09 Труды 4-го семинара по реализации, компиляции, оптимизации объектно-ориентированных языков и систем программирования - страницы 18-25 - Дои:10.1145/1565824.1565827. Проверено 21 марта 2012 г.
  8. ^ "SPUR: JIT-компилятор на основе трассировки для CIL" M. Bebenita et al. -Труды международной конференции ACM по языкам и приложениям объектно-ориентированных систем программированияДои:10.1145/1869459.1869517.

внешняя ссылка