Я делаю обзор возможностей при подготовке исследовательского проекта.
Назовите основной язык или языковую функцию, которую сложно оптимизировать, и объясните, почему эта функция стоит или не стоит заплаченной цены, или просто опровергните мои теории ниже с помощью отдельных примеров. Прежде чем кто-либо пометит это как субъективное, я прошу конкретные примеры языков или функций, а также идеи по оптимизации этих функций или важных функций, которые я не рассматривал. Кроме того, любые ссылки на реализации, которые подтверждают мои теории правильно или неправильно.
Наверху в моем списке трудно оптимизируемых функций и моих теорий (некоторые из моих теорий не проверены и основаны на мысленных экспериментах):
1) Перегрузка метода во время выполнения (так называемая отправка нескольких методов или отправка на основе сигнатур). Трудно ли оптимизировать в сочетании с функциями, которые позволяют перекомпиляцию во время выполнения или добавление метода. Или все-таки сложно? Кэширование сайтов вызовов - это общая оптимизация для многих систем времени выполнения, но мульти-методы добавляют дополнительную сложность, а также делают практические методы менее практичными.
2) Тип морфинга / варианты (он же тип, основанный на значении, а не на переменной)
Традиционная оптимизация просто не может быть применена, когда вы не знаете, может ли тип некоего измениться в основном блоке. В сочетании с несколькими методами, вставка должна быть сделана осторожно, если вообще, и, вероятно, только для данного порога размера вызываемого. то есть. легко рассмотреть встраивание простых выборок свойств (геттеры / сеттеры), но встраивание сложных методов может привести к раздуванию кода. Другая проблема заключается в том, что я не могу просто назначить вариант регистру и JIT его родным инструкциям, потому что мне нужно иметь при себе информацию о типе, или каждая переменная нуждается в 2 регистрах вместо 1. На IA-32 это неудобно, даже если улучшено с помощью дополнительных регистров x64. Вероятно, это моя любимая особенность динамических языков, поскольку она упрощает многие вещи с точки зрения программиста.
3) Продолжения первого класса - Существует несколько способов их реализации, и я сделал это в обоих наиболее распространенных подходах, один из которых - копирование в стеке, а другой - реализация среды выполнения с использованием продолжения. стиль прохождения, стеки кактусов, кадры стека копирования при записи и сборка мусора. Первоклассные продолжения имеют проблемы управления ресурсами, т.е. мы должны сохранить все, на случай, если продолжение будет возобновлено, и я не знаю, поддерживают ли какие-либо языки продолжение с «намерением» (т. е. «я не вернусь сюда, поэтому вы можете отказаться от этой копии мира» ). Я запрограммировал в модели потоков и модели продолжения, я знаю, что оба могут выполнить одно и то же, но элегантность продолжений создает значительную сложность во время выполнения и также может влиять на эффективность кэша (локальность стека меняется больше с использованием продолжений и сопрограмм). ). Другая проблема заключается в том, что они просто не отображаются на оборудование. Оптимизация продолжений - это оптимизация для менее распространенного случая, и, как мы знаем, общий случай должен быть быстрым, а менее распространенные случаи - правильными.
4) Арифметика указателей и способность маскировать указатели (хранение в целых числах и т. Д.) Пришлось добавить это, но я мог бы действительно прожить без этого довольно легко.
Мне кажется, что многие высокоуровневые функции, особенно в динамических языках , просто не соответствуют аппаратному обеспечению . Реализации микропроцессора имеют миллиарды долларов исследований, стоящих за оптимизацией на чипе, однако выбор языковых функций может привести к маргинализации многих из этих функций (такие функции, как кэширование, наложение псевдонима на вершину стека для регистрации, параллелизм команд, буферы адресов возврата, цикл буферы и ветвление предсказания). Макро-приложения микро-функций не обязательно работают так, как некоторые разработчики любят думать, и реализация многих языков в ВМ приводит к тому, что родные операции отображаются в вызовах функций (т. Е. Чем динамичнее язык, тем больше нам нужно искать / кэширование во время выполнения, ничего нельзя предположить, поэтому наш набор инструкций состоит из более высокого процента нелокального ветвления, чем традиционный, статически скомпилированный код), и единственное, что мы можем действительно хорошо JIT, это оценка выражений нединамических типов и операции с постоянными или непосредственными типами. Мне кажется, что из-за этого виртуальные машины с байт-кодом и ядра JIT не всегда оправданы для определенных языков.
Я приветствую ваши ответы.