2015-04-10 19 views
11

W oparciu o bogate bogactwo stackoverflow, zacząłem włączać i wyłączać odpowiedzi na pytanie, czy optymalizacja rekursywna ogona jest wykonywana dla konkretnego kodu C#. Kilka pytań pojawiła się mówić oKompilacja C# z optymalizacją rekursywną ogona?

  1. spekulacji optymalizacji w nowszych wersjach .NET, które były uwalniane
  2. aplikację Building jako aplikacja x64bit osiągnąć optymalizację
  3. przełączania z kompilacji debugowania do kompilacji wydania w Visual Studio w celu osiągnięcia optymalizacji
  4. Brak optymalizacji i że społeczność microsoft twierdziła, że ​​nie przeprowadziłaby optymalizacji rekursywnej ogona dla "problemów bezpieczeństwa" (tak naprawdę nie rozumiem tego)
  5. To się stało ns losowo

Tak jak w C# 4.0 (Visual Studio 2013/2015) w jaki sposób zapewnić optymalizację rekursywną ogona, jeśli można to w ogóle zapewnić?

+3

Zwykle dodaje on wiele wartości do tych postów, gdy łączysz inne pytania i odpowiedzi, na które natknąłeś się, abyśmy mogli śledzić Twój pociąg myśl i ścieżka, którą podjąłeś, aby osiągnąć swoje pytanie. –

+1

Obecna wersja C# to 5, wersja 6 jest dostępna w podglądzie VS 2015. –

+0

@TravisJ Chciałam spróbować połączyć pozostałe pytania, ale nie byłam pewna, czy mógłbym je śledzić b/c, które oglądałem przez dłuższy czas. –

Odpowiedz

19

Istnieją różne poziomy optymalizacji wywołań końcowych. JIT jest naprawdę odpowiedzialny za wiele optymalizacji, które się zdarzają. Sam kompilator C# nawet nie wykonuje inlineingu metod, to jest odpowiedzialność kompilatora JIT. Kompilator C# mógłby używać Tailcall IL opcode oznaczającego wywołanie jako wywołanie tail, jednak uważam, że nie robi tego żadna wersja kompilatora C#. Kompilator JIT może wykonywać optymalizacje połączeń wychodzących, gdy uzna to za stosowne. W szczególności uważam, że tylko 64-bitowy JIT to robi. Ten blog post przedstawia kilka scenariuszy, w których JIT64 nie może korzystać z optymalizacji połączeń końcowych. Jestem pewien, że kryteria mogą ulec zmianie, ponieważ pracują nad ponownym napisaniem kompilatora JIT o nazwie kodowej RyuJIT.

Jeśli chcesz krótki przykład programu, który można wykorzystać TCO spróbuj tego:

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

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

Ustaw projekt budowy uwolnienie/64 (lub AnyCPU w/o preferują 32-bit) i uruchomić bez debuggera przywiązany. Program będzie działać wiecznie. Jeśli nie zrobię wszystkich tych rzeczy, otrzymam wyjątek stackoverflow około 20947.

+1

Drugi odsyłacz wskazuje to samo co pierwszy. Miałaś na myśli to? http://blogs.msdn.com/b/clrcodegeneration/archive/2009/05/11/tail-call-improvements-in-net-framework-4.aspx Ponadto dobry post: http://stackoverflow.com/ pytania/15864670/generate-tail-call-opcode –

+0

@ Erti-ChrisEelmaa Naprawiono link, do którego odnosi się również w poście, z którym się łączyłeś. –

+0

W celu zapewnienia prawdopodobieństwa optymalizacji rekursywnej ogona przez kompilator JIT, należy ustawić 64-bitową kompilację? Dodatkowo, czy istnieje coś bezpośredniego (słowa kluczowe, znaczniki atrybutów), które można dodać, aby zwiększyć prawdopodobieństwo optymalizacji? –