Оптимизация хвостовых вызовов в последнем CLR - PullRequest
3 голосов
/ 24 июня 2011

Я обнаружил (по аварии ), что последний CLR выполняет оптимизацию хвостового вызова. Я проверил это с помощью кода, но, честно говоря, он не ведет себя так, как я ожидал. Я думал, что оптимизация хвостового вызова может произойти, когда последним в функции является вызов функции.

Я пытаюсь «сломать» этот код, чтобы предотвратить опровержение формы.

class Program
{
    static void Foo(int counter, int limit)
    {
        try
        {
            if (counter == limit)
            {
                return;
            }
            Foo(++counter, limit);

            int d = 1;
            d = Bar(d);
            //Console.Write(d);
            //Thread.Sleep(1);
            int baz = 0;
            var z = baz + d;
            StringBuilder b = new StringBuilder();
            b.Append("D");
        }
        catch (Exception)
        {
            throw;
        }
    }

    static int Sum(int s)
    {
        if (s == 1)
        {
            return s;
        }
        return s + Sum(s - 1);
    }

    static int Bar(int d)
    {
      return  d = 10 + d;
    }

    static void Main(string[] args)
    {
        int i = 0;

        Foo(i, 10000); // jitter 
        Sum(10000);

        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        Foo(i, 10000);
        stopwatch.Stop();
        Console.WriteLine(string.Format("time of execution = {0}ms",stopwatch.ElapsedMilliseconds));

        stopwatch = new Stopwatch();
        stopwatch.Start();
        Sum(10000);
        stopwatch.Stop();
        Console.WriteLine(string.Format("time of execution = {0}ms", stopwatch.ElapsedMilliseconds));

        Console.ReadKey();
    }
}

И все же Foo оптимизирован. Как получилось?

1 Ответ

0 голосов
/ 24 июня 2011

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

Вы также можете написать члену класса, это будет побочный эффект, от которого нельзя отказаться.

private static int dummy;
static void Foo(int counter, int limit)
{
    if (counter == limit) return;
    Foo(++counter, limit);
    dummy++;
}

, а затем читать dummy в конце Main.

...