Компиляция С# с рекурсивной оптимизацией хвоста?

Основываясь на богатом богатстве stackoverflow, я получал ответы на вопрос о том, выполняется ли рекурсивная оптимизация хвоста специально для кода С#. Несколько вопросов, казалось, говорили о

  • Спекуляция оптимизации в новых версиях .net, которые были выпущены
  • Создание приложения в качестве x64bit приложения для достижения оптимизации
  • Переход от сборки отладки к сборке выпуска в Visual Studio для достижения оптимизации
  • Никакой оптимизации вообще и что сообщество Microsoft не утверждало, что они не будут делать рекурсивную оптимизацию хвоста для "проблем безопасности" (на самом деле это не понимало)
  • Это происходит случайно [/li >

Итак, как и на С# 4.0 (Visual Studio 2013/2015), как можно обеспечить рекурсивную оптимизацию хвоста, если вы можете обеспечить ее вообще?

Ответ 1

Существуют различные уровни, на которых может поддерживаться оптимизация вызовов хвоста. JIT действительно несет ответственность за многие оптимизации, которые происходят. Сам компилятор С# даже не выполняет метод inline, то есть ответственность компилятора JIT. Компилятор С# может использовать код транзакции Tailcall IL, обозначающий вызов как хвостовой вызов, однако я считаю, что никакая версия компилятора С# не делает этого. Компилятору JIT разрешено выполнять оптимизацию хвостовых вызовов всякий раз, когда он сочтет нужным. В частности, я считаю, что только 64-разрядная JIT делает это. В этом сообщении сообщается о нескольких сценариях, в которых JIT64 не может использовать оптимизацию хвостовых вызовов. Я уверен, что критерии могут быть изменены, поскольку они работают над переписыванием JIT-компилятора под кодовым названием RyuJIT.

Если вам нужен короткий пример программы, которая может использовать TCO, попробуйте следующее:

class Program
{
    static void Main(string[] args)
    {
        Test(1);
    }

    private static void Test(int i)
    {
        Console.WriteLine(i);
        Test(i + 1);
    }
}

Задайте проект для сборки Release/x64 (или AnyCPU без предпочтения 32-разрядной версии) и начните без присоединенного отладчика. Программа будет работать вечно. Если я не буду делать все это, я получаю исключение stackoverflow около 20947.