Różnice wydajności między kompilacjami debugowania i Wydania

Muszę przyznać, że zwykle nie zawracałem sobie głowy przełączaniem pomiędzy konfiguracjami Debug i Release w moim programie, a zazwyczaj wybierałem konfigurację Debug, nawet jeśli programy są faktycznie wdrożone u klienta.

Z tego co wiem, jedyną różnicą między tymi konfiguracjami, jeśli nie zmienisz ich ręcznie jest to, że Debug ma DEBUG stała zdefiniowana, oraz Release mają zoptymalizuj kod sprawdzony.

Więc moje pytania są właściwie dwojakie:

  1. Czy istnieje wiele różnic wydajności między tymi dwoma konfiguracjami. Czy istnieje jakiś specyficzny rodzaj kodu, który spowoduje duże różnice w wydajności, czy też nie jest to tak ważne?

  2. Czy istnieje jakiś rodzaj kodu, który będzie działał poprawnie pod konfiguracją Debug , która może się nie udać pod konfiguracją Release, Czy możesz być pewien, że kod, który jest testowany i działa poprawnie pod konfiguracją Debug będzie również działał poprawnie pod konfiguracją Release.

Author: shA.t, 2010-10-28

8 answers

Kompilator C# nie zmienia zbytnio emitowanego IL w Release build. Godne uwagi jest to, że nie emituje już kodów opcodów NOP, które pozwalają ustawić punkt przerwania na nawiasach klamrowych. Dużym jest optymalizator, który jest wbudowany w kompilator JIT. Wiem, że to sprawia, że następujące optymalizacje:

  • Metoda inlining. Wywołanie metody jest zastępowane przez wstrzyknięcie kodu metody. To jest duży, to sprawia, że accessors nieruchomości zasadniczo za darmo.

  • Przydział rejestru CPU. Zmienne lokalne i argumenty metod mogą pozostać przechowywane w rejestrze procesora bez konieczności (lub rzadziej) zapisywania ich z powrotem do ramki stosu. Jest to duża sprawa, która sprawia, że debugowanie zoptymalizowanego kodu jest tak trudne. I nadając słowu kluczowemu volatile znaczenie.

  • Eliminacja sprawdzania indeksu tablicy. Ważna optymalizacja podczas pracy z tablicami (wszystkie klasy kolekcji.NET używają tablicy wewnętrznie). Kiedy Kompilator JIT może sprawdzić, czy pętla nigdy nie indeksuje tablicy poza granicami, a następnie wyeliminuje sprawdzanie indeksu. Duży.

  • Rozwijanie pętli. Pętle z małymi ciałami są ulepszane przez powtarzanie kodu do 4 razy w ciele i zapętlanie mniej. Zmniejsza koszty gałęzi i poprawia opcje superskalarnej realizacji procesora.

  • Eliminacja Martwego kodu. Twierdzenie takie jak if (false) {/.../ } zostaje całkowicie wyeliminowana. Może to nastąpić z powodu stałe składanie i wkładanie. W innych przypadkach kompilator JIT może stwierdzić, że kod nie ma możliwego efektu ubocznego. Ta optymalizacja sprawia, że profilowanie kodu jest tak trudne.

  • Podnośnik szyfrowy. Kod wewnątrz pętli, na który pętla nie ma wpływu, może zostać usunięty z pętli. Optymalizator kompilatora C poświęci dużo więcej czasu na znalezienie możliwości wciągnięcia. Jest to jednak kosztowna optymalizacja ze względu na wymaganą analizę przepływu danych, a jitter nie może pozwolić sobie na czas, więc tylko wciąga oczywiste przypadki. Zmuszanie programistów. NET do pisania lepszego kodu źródłowego i podnoszenia się.

  • Wspólna eliminacja subekspresji. x = y + 4; z = y + 4; staje się z = x; dość powszechne w wyrażeniach takich jak dest[ix+1] = src[ix+1]; napisane dla czytelności bez wprowadzania zmiennej pomocniczej. Nie ma potrzeby obniżania czytelności.

  • Stałe składanie. x = 1 + 2; staje się x = 3; Ten prosty przykład jest wcześnie przechwytywany przez kompilator, ale dzieje się w czasie JIT, gdy inne optymalizacje to możliwe.

  • Kopiuj propagację. x = A; y = x; staje się y = a; pomaga to alokatorowi rejestrów podejmować lepsze decyzje. Jest to duża sprawa w jitterze x86, ponieważ ma niewiele rejestrów do pracy. Wybór właściwych jest kluczowy dla perf.

Są to bardzo ważne optymalizacje, które mogą zrobić wielką różnicę, gdy na przykład profilujesz kompilację debugowania aplikacji i porównać go z Release build. To jednak ma znaczenie tylko wtedy, gdy kod znajduje się na twojej ścieżce krytycznej, 5 do 10% kodu, który piszesz, że faktycznie wpływa na perf Twojego programu. JIT optimizer nie jest wystarczająco inteligentny, aby wiedzieć z góry, co jest krytyczne, może zastosować tylko pokrętło "skręć na jedenaście" dla całego kodu.

Efektywny wynik tych optymalizacji na czas wykonania programu jest często zależny od kodu, który działa gdzie indziej. Odczyt pliku, wykonanie zapytania dbase, itp. Dokonywanie pracy JIT optimizer robi całkowicie niewidoczne. Nie przeszkadza to jednak :)

JIT optimizer jest dość niezawodny kod, głównie dlatego, że został wystawiony na próbę miliony razy. Bardzo rzadko występują problemy w wersji Release build programu. Zdarza się jednak. Zarówno x64, jak i x86 jitters miały problemy ze strukturami. Jitter x86 ma problemy ze zmiennoprzecinkową spójnością, produkując subtelnie różne wyniki, gdy półprodukty obliczeń zmiennoprzecinkowych są przechowywane w rejestrze FPU z 80-bitową precyzją, zamiast być obcięte po przepłukaniu do pamięci.

 487
Author: Hans Passant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-17 10:34:00
  1. Tak, Istnieje wiele różnic w wydajności i te naprawdę mają zastosowanie w całym kodzie. Debug nie zajmuje się optymalizacją wydajności, a tryb release bardzo dużo;

  2. Tylko kod, który opiera się na stałej DEBUG, może działać inaczej w release build. Poza tym nie powinieneś widzieć żadnych problemów.

Przykładem kodu frameworka zależnego od stałej DEBUG jest Metoda Debug.Assert(), która ma zdefiniowany atrybut [Conditional("DEBUG)"]. Oznacza to że zależy to również od DEBUG stałej i nie jest to zawarte w release build.

 23
Author: Pieter van Ginkel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-28 14:27:00

To w dużej mierze zależy od charakteru Twojej aplikacji. Jeśli Twoja aplikacja jest ciężka dla interfejsu użytkownika, prawdopodobnie nie zauważysz żadnej różnicy, ponieważ najwolniejszym komponentem podłączonym do nowoczesnego komputera jest użytkownik. Jeśli używasz animacji interfejsu użytkownika, możesz sprawdzić, czy możesz zauważyć zauważalne opóźnienia podczas uruchamiania w kompilacji debugowania.

Jednak, jeśli masz wiele obliczeń ciężkich, to zauważysz różnice (może być aż 40%, jak wspomniał @Pieter, choć byłoby to zależy od charakteru obliczeń).

To w zasadzie projektowy kompromis. Jeśli wydajesz w ramach DEBUG build, jeśli użytkownicy napotkają problemy, możesz uzyskać bardziej znaczące śledzenie i możesz wykonać znacznie bardziej elastyczną diagnostykę. Wypuszczając w DEBUG build, unikasz również optimizera produkującego obscure Heisenbugs .

 12
Author: Lie Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-28 15:02:24
  • Z mojego doświadczenia wynika, że średnie lub większe aplikacje są zauważalnie bardziej responsywne w kompilacji wersji. Wypróbuj swoją aplikację i zobacz, jak to jest.

  • Jedną z rzeczy, które mogą cię ugryźć z Release builds jest to, że kod kompilacji debugowania może czasami tłumić warunki rasowe i inne błędy związane z wątkiem. Zoptymalizowany kod może spowodować zmianę kolejności instrukcji, a szybsze wykonanie może zaostrzyć pewne warunki wyścigu.

 11
Author: Dan Bryant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-28 14:51:21

Nigdy nie powinieneś wypuszczać kompilatora debugowania. NET do produkcji. może zawierać brzydki kod do obsługi edit-and-Continue lub kto wie co jeszcze. Z tego, co wiem, dzieje się to tylko w VB, a nie w C # (Uwaga: oryginalny post jest oznaczony jako C#), ale nadal powinno dać powód do wstrzymania się z tym, co Microsoft uważa, że może zrobić z kompilacją debugowania. W rzeczywistości, przed. NET 4.0, kod VB wycieka pamięć proporcjonalnie do liczby wystąpień obiektów ze zdarzeniami, które konstruujesz w celu wsparcia Edit-and-Continue. (Choć podaje się, że jest to stałe na https://connect.microsoft.com/VisualStudio/feedback/details/481671/vb-classes-with-events-are-not-garbage-collected-when-debugging, wygenerowany kod wygląda paskudnie, tworząc WeakReference obiekty i dodając je do listy statycznej podczas trzymając blokadę ) na pewno nie chcę żadnej z tego rodzaju obsługi debugowania w środowisku produkcyjnym!

 9
Author: Jason Kresowaty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-28 23:05:05

Z mojego doświadczenia, najgorszą rzeczą, która wyszła z trybu Wydania, są niejasne "błędy wydania". Ponieważ język IL (intermediate language) jest zoptymalizowany w trybie Release, istnieje możliwość wystąpienia błędów, które nie przejawiałyby się w trybie debugowania. Są też inne pytania dotyczące tego problemu: najczęstsze przyczyny błędów w wersji Release nieobecnej w trybie debugowania

Zdarzyło mi się to raz lub dwa razy, gdy prosta aplikacja konsoli działała idealnie w debugowaniu mode, ale biorąc pod uwagę dokładnie to samo wejście, byłby błąd w trybie Release. Błędy te są niezwykle trudne do debugowania(z definicji trybu Wydania, jak na ironię).

 5
Author: Roly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:57

Powiedziałbym, że 1) w dużej mierze zależy od twojej realizacji. Zazwyczaj różnica nie jest aż tak duża. Zrobiłem wiele pomiarów i często nie widziałem różnicy. Jeśli używasz kodu niezarządzanego, wielu ogromnych tablic i tym podobnych rzeczy, różnica w wydajności jest nieco większa, ale nie inny świat (jak w C++). 2) zwykle w kodzie wydania pojawia się mniej błędów (większa tolerancja), dlatego przełącznik powinien działać dobrze.

 3
Author: testalino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-17 07:22:42
    **Debug Mode:**
    Developer use debug mode for debugging the web application on live/local server. Debug mode allow developers to break the execution of program using interrupt 3 and step through the code. Debug mode has below features:
   1) Less optimized code
   2) Some additional instructions are added to enable the developer to set a breakpoint on every source code line.
   3) More memory is used by the source code at runtime.
   4) Scripts & images downloaded by webresource.axd are not cached.
   5) It has big size, and runs slower.

    **Release Mode:**
    Developer use release mode for final deployment of source code on live server. Release mode dlls contain optimized code and it is for customers. Release mode has below features:
    More optimized code
    Some additional instructions are removed and developer can’t set a breakpoint on every source code line.
   1) Less memory is used by the source code at runtime.
   2) Scripts & images downloaded by webresource.axd are cached.
   3) It has small size, and runs fast.
   4) Scripts & images downloaded by webresource.axd are cached.
   5) It has small size, and runs fast.
 0
Author: Nandha kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-17 05:31:04