Długa kompilacja programu Visual Studio w przypadku zamiany int na double

86

Moja kopia VS2013 Ultimate kompiluje ten kod przez ponad 60 sekund:

class Program
{
    static void Main(string[] args)
    {
        double dichotomy = Dichotomy(
            d =>
            {
                try
                {
                    int size = (int) d;
                    byte[] b = new byte[size];
                    return -b.Length;
                }
                catch (Exception)
                {
                    return 0;
                }
            },
            0,
            int.MaxValue,
            1);

        Console.WriteLine(dichotomy);
        Console.ReadKey();
    }

    private static double Dichotomy(
        Func<double, double> func,
        double a,
        double b,
        double epsilon)
    {
        double delta = epsilon / 10;
        while (b - a >= epsilon)
        {
            double middle = (a + b) / 2;
            double lambda = middle - delta, mu = middle + delta;
            if (func(lambda) < func(mu))
                b = mu;
            else
                a = lambda;
        }
        return (a + b) / 2;
    }
}

Ale jeśli mogę wymienić doublez int, kompiluje natychmiast. Jak to wytłumaczyć ...?

Alex Zhukovskiy
źródło
Kompiluje się natychmiast na moim komputerze, dla obu typów danych ... Na jakim komputerze je kompilujesz?
Chris Mantle
1
Podrap mój pierwszy komentarz; Widzę to samo zachowanie. ~ 15 sekund doublezi natychmiast z int. Maszyna 3,4 Ghz.
Kevin Richardson,
Ciekawy. Sprawdziłem swoją wersję i aktualnie używam VS2013 Premium - myślałem, że mam zainstalowany Ultimate. Być może to tylko wersja Ultimate, z którą to się dzieje.
Chris Mantle
1
@chris Aby poprzeć tę hipotezę, VS Express 2013 / Windows Desktop kompiluje to dobrze.
ClickRick,
5
Z tego, co słyszałem, „bardzo dziwne zachowanie VS2013” ​​nie jest niczym dziwnym. :)
Wyścigi lekkości na orbicie

Odpowiedzi:

140

Powtarzam, 27 sekund na mojej maszynie. Złoczyńcą jest MsMpEng.exe, który przez tak długi czas spala 100% rdzenia. Łatwo zobaczyć na karcie Procesy Menedżera zadań.

To jest usługa Windows Defender, która faktycznie wykonuje skanowanie złośliwego oprogramowania. Wyłączenie go przez odznaczenie opcji „Włącz ochronę w czasie rzeczywistym” natychmiast naprawia opóźnienie. Podobnie jest z dodaniem ścieżki, w której przechowuję projekty, do pola „Wykluczone lokalizacje plików”, prawdopodobnie preferowaną metodą.

Nie chciałbym zgadywać przyczyny, ale muszę założyć, że Twój kod źródłowy uruchamia regułę dotyczącą złośliwego oprogramowania. Nie jest to świetne wyjaśnienie, nie widzę opóźnienia, gdy wybieram wersję .NET <4.0. Okej, poddaję się :)

Hans Passant
źródło
4
Omg, Microsoft, żartujesz sobie ze mnie ... Tnx o pomoc, to naprawdę MSSEi .Net 4.0+kto jest winowajcą
Alex Zhukovskiy
3
Dobry chwyt! Zastanawiam się, co dokładnie powoduje problem (szczególnie w przypadku programu, który jest tak prosty i prawie nie zawiera zależności zewnętrznych). Czy byłoby możliwe, aby wynikowe bajty MSIL z kompilacji wyglądały dokładnie tak, jak wzorzec znanego złośliwego oprogramowania, a zatem MsMpEnd zostałby uruchomiony?
tigrou,
-1

Nie mogę powiedzieć autorytatywnie, ponieważ minęło ponad 20 lat, odkąd majstrowałem na poziomie kodu asemblera, ale łatwo w to uwierzyć.

Różnica między standardowymi operacjami zmiennoprzecinkowymi IEEE a operacjami implementowanymi przez procesor często wymusza linkowanie procedur bibliotecznych w celu wykonania tłumaczenia, podczas gdy matematyka liczb całkowitych może po prostu używać instrukcji procesora. W czasie, gdy IEEE definiowało standard, dokonali wyborów, które były bardzo rzadkie we wdrażaniu, a zwłaszcza że dawno temu znacznie droższe we wdrażaniu w mikrokodzie, a obecne systemy PC są oczywiście zbudowane na układach pochodzących z 80387 i 80486 , które są starsze niż standard.

Więc jeśli mam rację, wydłużony czas jest spowodowany dodaniem fragmentu kodu biblioteki do łącza, a linkowanie jest dużą częścią czasu kompilacji, który ma tendencję do mnożenia się w miarę dodawania relokowalnych fragmentów.

Clang w systemie Linux może, ale nie musi, mieć takie samo spowolnienie; jeśli tego uniknie i poszerzy moje domysły jeszcze bardziej, będzie to artefakt wszechobecnej biblioteki libc pamięci współdzielonej, którą tam dostaniesz, i optymalizacji linkera wokół tego.

grał
źródło