Как избежать ненужного бокса в DLR
-
06-07-2019 - |
Вопрос
Я играю с DLR, чтобы лучше понять это. Я еще не совсем знаком со всеми его концепциями и терминологией, поэтому извините за любые терминологические или концептуальные ошибки в моем вопросе.
По сути, я понимаю, что вы передаете объекты в деревьях выражений, но используете связыватели для демонстрации динамической функциональности ваших объектов другим языкам, поддерживающим DLR. Таким образом, вместо добавления, например, непосредственно в дереве выражений (с Expression.Add), вы создаете связыватель, который вызывается сайтом вызовов всякий раз, когда это необходимо, и выполняет добавление для вас.
Однако, поскольку вы передаете объекты, в конце операции сложения (если операндами являются, например, два значения Int32), вам придется связать получившийся Int32 с объектом, поскольку (все еще в связывателе) это что ожидает сайт вызова. Я немного боюсь, что этот постоянный бокс / распаковка может несколько повлиять на производительность среды выполнения.
Это действительно так, как это должно работать (со всеми боксами / распаковками) или я что-то упустил?
Решение
В динамически типизированном языке идентификация и оптимизация статически типизированной переменной - это специфическая для домена оптимизация. В реализации конкретного динамического языка X вы можете хранить неупакованную локальную переменную в сгенерированном коде, но как только вы предоставляете API с динамической типизацией, нет способа гарантировать статическую типизацию (сама природа динамических языков).
Чтобы избежать упаковок, вам нужно будет идентифицировать фрагменты кода, которые вы можете использовать для проверки статических типов, и генерировать код специально для них с помощью Linq.Expressions
или ILGenerator
. р>
Другие советы
Что касается связующих, вы также можете реализовать пользовательское связующее. Это пользовательское связующее может либо возвращать не-объектный тип, либо может выполнять другие конкретные оптимизации. В IronPython мы используем внешний слой DLR ComboBinder и ComboActionRewriter для оптимизации условий. Например, " if a.b: " может превратиться в ComboBinder, который выполняет как a.b, так и преобразование в bool. Если a.b приведет к не упакованному bool, мы избежим упаковки и распаковки. Мы планируем поэкспериментировать с подобными оптимизациями.