Языки и виртуальные машины: функции, которые трудно оптимизировать и почему

Я делаю обзор функций в рамках подготовки к исследовательскому проекту.

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

В моем списке трудно оптимизировать функции и мои теории (некоторые из моих теорий непроверены и основаны на мысленных экспериментах):

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

2) Тип/варианты типов (например, на основе набора символов, а не на основе переменных) Традиционная оптимизация просто не может быть применена, если вы не знаете, может ли тип someting измениться в базовом блоке. В сочетании с мульти-методами вложение должно выполняться тщательно, если вообще, и, вероятно, только для заданного порога размера вызываемого абонента. то есть. легко рассмотреть возможность вставки простых свойств (getters/seters), но встроенные сложные методы могут привести к раздуванию кода. Другая проблема заключается в том, что я не могу просто назначить вариант регистру и использовать JIT для собственных инструкций, потому что мне нужно нести информацию о типе, или для каждой переменной требуется 2 регистра вместо 1. На IA-32 это неудобно, даже если улучшено с дополнительными регистрами x64. Это, вероятно, моя любимая функция динамических языков, поскольку она упрощает так много вещей с точки зрения программиста.

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

4) Арифметика указателя и способность маскировать указатели (сохранение в целых числах и т.д.) Если бы это было сделано, но я мог бы жить без этого довольно легко.

Мои чувства заключаются в том, что многие из высокоуровневых функций, особенно в динамических языках, просто не сопоставляются с оборудованием. Микропроцессорные реализации имеют миллиарды долларов исследований за оптимизацией на чипе, однако выбор языковых функций может привести к маргинализации многих из этих функций (такие функции, как кеширование, сглаживание верхней части стека для регистрации, инструкция parallelism, буферы обратного адреса, буферы буферов и предсказание ветвлений). Макро-приложения микро-функций не обязательно выделяются, как некоторые разработчики любят думать, а реализация многих языков в виртуальной машине заканчивается сопоставлением собственных ops с вызовами функций (т.е. Чем более динамичный язык, тем больше мы должны искать/кеш во время выполнения, ничто не может быть принято, поэтому наш набор команд состоит из более высокого процента нелокального разветвления, чем традиционный, статически скомпилированный код), и единственное, что мы можем реально использовать JIT, - это оценка экспрессии нединамических типов и операции с постоянными или непосредственными типами. Из-за этого мне кажется, что байт-коды виртуальных машин и ядра JIT, возможно, не всегда оправдываются для определенных языков.

Я приветствую ваши ответы.

Ответ 1

Несколько комментариев:

  • Все языки с динамической диспетчеризацией, даже основанные на одном объекте, довольно сложно реализовать эффективно. Посмотрите на все усилия, которые вошли во временную оптимизацию Self (или, совсем недавно, JavaScript, с SpiderMonkey).

  • Не пропустите разграниченные продолжения. Жюри все еще не работает, но их значительно легче оптимизировать, чем классические неподтвержденные продолжения. Прочитайте статью Габбихлера и Спербера.

Ответ 2

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

Не удалось ли написать IronPython, чтобы доказать, что виртуальная машина не может работать так же, как собственная реализация языка (Python). И тогда автор IronPython получил шок, когда узнал, что IronPython отлично работает для динамического языка на виртуальной машине байт-кода?

Собственная внутренняя группа Microsoft вне зависимости от того, что, по их мнению, JITter будет превосходить "нормальный" компилятор/компоновщик (например, C/С++).

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