Могу ли я заставить компилятор оптимизировать конкретный метод?C#

Место общения программистов C#
Anonymous
Могу ли я заставить компилятор оптимизировать конкретный метод?

Сообщение Anonymous »

Есть ли атрибут, который я могу использовать, чтобы сообщить компилятору, что метод всегда должен быть оптимизирован, даже если глобальный переключатель компилятора /o+ не установлен?

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



РЕДАКТИРОВАТЬ: подробнее о неоптимизациях, которые меня беспокоят...

Давайте рассмотрим следующую реализацию факториала функция:

Код: Выделить всё

static long FactorialRec(int n, long acc)
{
if (n == 0)
return acc;
return FactorialRec(n - 1, acc * n);
}
(Примечание: я знаю, что есть более эффективные способы вычисления факториала, это всего лишь пример)

Интерфейс, созданный с включенной оптимизацией, довольно прост:

Код: Выделить всё

IL_0000:  ldarg.0
IL_0001:  brtrue.s    IL_0005
IL_0003:  ldarg.1
IL_0004:  ret
IL_0005:  ldarg.0
IL_0006:  ldc.i4.1
IL_0007:  sub
IL_0008:  ldarg.1
IL_0009:  ldarg.0
IL_000A:  conv.i8
IL_000B:  mul
IL_000C:  call        UserQuery.FactorialRec
IL_0011:  ret
Но неоптимизированная версия совсем другая

Код: Выделить всё

IL_0000:  nop
IL_0001:  ldarg.0
IL_0002:  ldc.i4.0
IL_0003:  ceq
IL_0005:  ldc.i4.0
IL_0006:  ceq
IL_0008:  stloc.1
IL_0009:  ldloc.1
IL_000A:  brtrue.s    IL_0010
IL_000C:  ldarg.1
IL_000D:  stloc.0
IL_000E:  br.s        IL_001F
IL_0010:  ldarg.0
IL_0011:  ldc.i4.1
IL_0012:  sub
IL_0013:  ldarg.1
IL_0014:  ldarg.0
IL_0015:  conv.i8
IL_0016:  mul
IL_0017:  call        UserQuery.FactorialRec
IL_001C:  stloc.0
IL_001D:  br.s        IL_001F
IL_001F:  ldloc.0
IL_0020:  ret
Он спроектирован так, чтобы иметь только одну точку выхода в конце. Возвращаемое значение хранится в локальной переменной.

Почему это проблема? Я хочу динамически генерировать метод, включающий оптимизацию хвостового вызова. Оптимизированный метод можно легко изменить, добавив префикс Tail. перед рекурсивным вызовом, поскольку после вызова нет ничего, кроме ret. Но в неоптимизированной версии я не так уверен... результат рекурсивного вызова сохраняется в локальной переменной, затем появляется бесполезная ветвь, которая просто переходит к следующей инструкции, локальная переменная загружается и возвращается. Поэтому у меня нет простого способа проверить, действительно ли рекурсивный вызов является последней инструкцией, поэтому я не могу быть уверен, что можно применить оптимизацию хвостового вызова.

Подробнее здесь: https://stackoverflow.com/questions/968 ... fic-method

Вернуться в «C#»