„Przedwczesna optymalizacja jest źródłem wszelkiego zła” to coś, co prawie wszyscy z nas słyszeli / czytali. Co mnie ciekawi, jaki rodzaj optymalizacji nie jest przedwczesny, tj. Na każdym etapie tworzenia oprogramowania (projektowanie na wysokim poziomie, szczegółowe projektowanie, wdrażanie na wysokim poziomie, szczegółowe wdrażanie itp.) Jaki zakres optymalizacji możemy rozważyć bez przechodzenia na ciemną stronę.
optimization
Gauraw
źródło
źródło
Odpowiedzi:
Kiedy bazujesz na doświadczeniu? Nie zło „Za każdym razem, gdy robiliśmy X, doświadczaliśmy brutalnego spadku wydajności. Tym razem planujemy zoptymalizować lub całkowicie uniknąć X”.
Kiedy jest względnie bezbolesny? Nie zło „Wdrożenie tego jako Foo lub Bar zajmie tyle samo pracy, ale teoretycznie Bar powinien być o wiele bardziej wydajny. Zabierzmy to”.
Kiedy unikasz gównianych algorytmów, które skalują się strasznie? Nie zło „Nasz technolog mówi, że nasz proponowany algorytm wyboru ścieżki działa w czasie czynnikowym; nie jestem pewien, co to oznacza, ale sugeruje, abyśmy popełnili seppuku, nawet by to rozważyć. Zastanówmy się nad czymś innym.”
Zło pochodzi z spędzania dużo czasu i energii na rozwiązywaniu problemów, o których istnieniu nie wiadomo. Kiedy problemy na pewno istnieją lub gdy fantomowe problemy psudo można rozwiązać tanio, zło znika.
Steve314 i Matthieu M. podnoszą punkty w komentarzach, które należy wziąć pod uwagę. Zasadniczo niektóre odmiany „bezbolesnych” optymalizacji po prostu nie są tego warte, ponieważ oferowane przez nich trywialne ulepszenia wydajności nie są warte zaciemnienia kodu, są duplikatami rozszerzeń, które kompilator już wykonuje, lub obu tych elementów. Zobacz komentarze, aby zapoznać się z przykładami zbyt sprytnych usprawnień o połowę.
źródło
i
jest niepodpisany,i / 2
można go zastąpići >> 1
. To jest szybsze. Ale jest też bardziej tajemniczy (nie wszyscy zobaczą efekt, nawet ci, którzy to robią, mogą stracić czas). Ale najgorsze jest to, że kompilator i tak to zrobi, więc po co zaciemniać kod źródłowy;)?i/2
jest rzeczywiście gorącym punktem i że (niewiarygodne, ale załóżmy)i>>1
sprawia, że jest szybszy, zrób to i dodaj komentarz, że to profilowanie pokazało, że jest szybsze. Jeśli rzeczywiście jest to potrzebne gdziekolwiek (co wątpię, ponieważ, jak powiedział Matthieu, kompilatory powinny być wystarczająco inteligentne, aby zrobić to sami), nowicjusze nauczą się czegoś, jeśli nie jest (co jest prawdopodobne), dlaczego chcesz podłączyć ich głowy z niepotrzebnym folklorem?Kod aplikacji powinien być tylko tak dobry, jak to konieczne, ale kod biblioteki powinien być tak dobry, jak to możliwe, ponieważ nigdy nie wiesz, jak twoja biblioteka będzie używana. Więc kiedy piszesz kod biblioteki, musi on być dobry pod każdym względem, czy to pod względem wydajności, niezawodności, czy jakiejkolwiek innej kategorii.
Musisz także pomyśleć o wydajności podczas projektowania aplikacji i wybierania algorytmów . Jeśli nie jest zaprojektowany tak, aby był wydajny, żaden stopień zhakowania nie może go później sprawić, a żadna mikrooptymalizacja nie przeważy nad lepszym algorytmem.
źródło
Takie, które powstają w wyniku znanych problemów.
źródło
Trudno powiedzieć, co jest dobre, a co złe. Kto ma to prawo? Jeśli spojrzymy na przyrodę, wydaje się, że jesteśmy zaprogramowani na przetrwanie z szeroką definicją „przetrwania”, która obejmuje przekazywanie naszych genów potomstwu.
Powiedziałbym więc, przynajmniej zgodnie z naszymi podstawowymi funkcjami i programowaniem, że optymalizacja nie jest zła, gdy jest zgodna z celem reprodukcji. Dla facetów są blondynki, brunetki, rude głowy, wiele uroczych. W przypadku dziewcząt są faceci, a niektóre z nich wydają się być w porządku.
Być może powinniśmy optymalizować w tym celu i tam pomaga korzystanie z profilera. Narzędzie do profilowania pozwoli Ci lepiej ustalać priorytety optymalizacji i czasu, a także zapewnia szczegółowe informacje o hotspotach i ich przyczynach. To da ci więcej wolnego czasu poświęconego na rozmnażanie i jego pogoń.
źródło
Pełny cytat określa, kiedy nie jest przedwczesna optymalizacja:
Kod krytyczny można zidentyfikować na wiele sposobów: krytyczne struktury danych lub algorytmy (np. Intensywnie używane lub „rdzeń” projektu) mogą dawać duże optymalizacje, wiele drobnych optymalizacji jest identyfikowanych za pomocą profilerów i tak dalej.
źródło
Zawsze powinieneś wybrać „wystarczająco dobre” rozwiązanie we wszystkich przypadkach na podstawie swoich doświadczeń.
Słowo „optymalizacja” odnosi się do pisania „bardziej złożonego kodu niż„ wystarczająco dobrego ”, aby przyspieszyć go”, zanim faktycznie dowie się, że jest to konieczne, a tym samym czyni kod bardziej złożonym niż to konieczne. Złożoność sprawia, że wszystko jest trudne, więc to nie jest dobra rzecz.
Oznacza to, że nie powinieneś wybierać super złożonej procedury sortowania plików o pojemności 100 Gb przez przezroczyste przełączanie na dysk, gdy wystarczy sortowanie proste, ale przede wszystkim powinieneś dokonać dobrego wyboru dla sortowania prostego. Ślepo wybierając Bubble Sort lub „wybierz losowo wszystkie wpisy i sprawdź, czy są w porządku. Powtórz”. rzadko jest dobry.
źródło
Moja ogólna zasada: jeśli nie jesteś pewien, czy potrzebujesz optymalizacji, załóż, że nie. Ale pamiętaj o tym, gdy musisz zoptymalizować. Jest jednak kilka problemów, które możesz wiedzieć z góry. Zazwyczaj wymaga to wyboru dobrych algorytmów i struktur danych. Na przykład, jeśli chcesz sprawdzić członkostwo w kolekcji, możesz być całkiem pewien, że będziesz potrzebować pewnego rodzaju ustalonej struktury danych.
źródło
Z mojego doświadczenia wynika, że na etapie szczegółowej implementacji odpowiedź polega na profilowaniu kodu. Ważne jest, aby wiedzieć, co musi być szybsze, a co akceptowalnie szybkie.
Ważne jest również, aby wiedzieć, gdzie dokładnie jest wąskie gardło wydajności - optymalizacja części kodu, której uruchomienie zajmuje tylko 5% całkowitego czasu, nie przyniesie żadnego pożytku.
Kroki 2 i 3 opisują przedwczesną optymalizację:
źródło
To nie jest optymalizacja przy wybieraniu rzeczy, które trudno zmienić, np .: platforma sprzętowa.
Dobranie struktur danych jest dobrym przykładem - kluczowym dla spełnienia zarówno funkcjonalnych, jak i niefunkcjonalnych (wydajnościowych) wymagań. Niełatwo to zmienić, a jednak będzie napędzać wszystko inne w Twojej aplikacji. Twoje struktury danych zmieniają dostępne algorytmy itp.
źródło
Znam tylko jeden sposób, aby odpowiedzieć na to pytanie, a mianowicie zdobyć doświadczenie w dostrajaniu wydajności. Oznacza to - pisz programy, a po ich napisaniu znajdź w nich przyspieszenia i rób to iteracyjnie. Oto jeden przykład.
Oto błąd, który popełni większość ludzi: próbują zoptymalizować program przed jego uruchomieniem. Jeśli ukończyli kurs programowania (od profesora, który tak naprawdę nie ma praktycznego doświadczenia), będą mieli kolorowe okulary w kształcie litery „O” i pomyślą, że o to właśnie chodzi . To ten sam problem, wcześniejsza optymalizacja. **
Ktoś powiedział: Najpierw napraw to, a potem szybko. Mieli rację.
Ale teraz dla kickera: jeśli zrobiłeś to kilka razy, rozpoznajesz głupie rzeczy, które wcześniej robiłeś, które powodują problemy z prędkością, więc odruchowo ich unikasz. (Rzeczy takie jak zbyt ciężka struktura zajęć, zalewanie się powiadomieniami, mylące rozmiary wywołań funkcji z ich kosztem czasu, lista jest długa i długa ...) Instynktownie unikasz ich, ale zgadnij, jak to wygląda mniej- doświadczył: przedwczesna optymalizacja!
Więc te głupie debaty trwają i trwają :)
** Mówią też, że nie musisz się już o to martwić, ponieważ kompilatory są tak dobre, a maszyny są tak szybkie w dzisiejszych czasach. (KIWI - Kill It With Iron.) Nie ma wykładniczego przyspieszenia sprzętowego lub systemowego (wykonywanego przez bardzo inteligentnych, ciężko pracujących inżynierów), które mogłyby zrekompensować wykładnicze spowolnienie oprogramowania (wykonywane przez programistów, którzy myślą w ten sposób).
źródło
Gdy wymagają tego wymagania lub rynek.
Na przykład wydajność jest wymagana w większości aplikacji finansowych, ponieważ kluczowe jest małe opóźnienie. W zależności od charakteru instrumentu będącego przedmiotem obrotu optymalizacja może przejść od stosowania algorytmów nieblokujących w języku wysokiego poziomu do używania języka niskiego poziomu, a nawet ekstremum - implementowanie algorytmów dopasowywania zamówień w samym sprzęcie (na przykład przy użyciu FPGA ).
Innym przykładem mogą być niektóre typy urządzeń osadzonych. Weźmy na przykład hamulec ABS; po pierwsze jest bezpieczeństwo, kiedy uderzysz w przerwę, samochód powinien zwolnić. Ale jest też wydajność, nie chciałbyś żadnych opóźnień, gdy dojdziesz do przerwy.
źródło
Większość osób nazwałaby optymalizację przedwczesną, jeśli optymalizujesz coś, co nie powoduje „miękkiej awarii” (działa, ale nadal jest bezużyteczne) systemu ze względu na wydajność.
Przykłady ze świata rzeczywistego.
Jeśli uruchomienie mojego sortowania bąbelkowego zajmuje 20 ms, optymalizacja go do 1 ms Quicksort nie poprawi ogólnej użyteczności w żaden znaczący sposób, mimo że wzrost wydajności o 2000%.
Jeśli załadowanie strony zajmuje 20 sekund, a my zmniejszamy ją do 1, może to zwiększyć użyteczność witryny z 0 do prawie nieskończoności. Zasadniczo coś, co zostało zepsute, ponieważ było zbyt wolne, jest teraz przydatne.
źródło
Jaki rodzaj optymalizacji nie jest przedwczesny?
Optymalizacja, która rozwiązuje znany problem z wydajnością aplikacji, lub optymalizacja, która pozwala aplikacji spełniać dobrze zdefiniowane kryteria akceptacji.
Po zidentyfikowaniu należy poświęcić trochę czasu na ustalenie poprawki i zmierzyć korzyści związane z wydajnością.
(tzn. nie jest - „Myślę, że ten fragment kodu wygląda na powolny, zmienię X, aby używał Y, a to będzie szybsze”).
Spotkałem wiele przedwczesnych „optymalizacji”, które ostatecznie spowolniły kod - w tym przypadku przedwcześnie rozumiem, że „nie przemyślałem”. Wydajność powinna być testowana przed optymalizacją i po niej oraz utrzymywany tylko kod, który faktycznie poprawia wydajność.
źródło
Prawdziwe. Niestety jest to również jeden z najbardziej (złośliwie) niewłaściwie używanych cytatów programistycznych wszech czasów. Ponieważ Donald Knuth stworzył mema, warto dodać oryginalny cytat z cytatu:
Zauważ, że Knuth mówił konkretnie o szybkości wykonywania w czasie wykonywania .
Napisał także ten artykuł w 1974 r., Kiedy wszelkie zasoby maszynowe, w których premia i ujemna korelacja między szybkością wykonywania a utrzymywalnością programu (większa prędkość - mniej utrzymywalna) były prawdopodobnie silniejsze niż obecnie.
OK, aby odpowiedzieć na twoje pytanie, według Donalda Knutha, optymalizacja NIE jest przedwczesna, jeśli naprawi poważne wąskie gardło wydajności, które zostało zidentyfikowane (najlepiej mierzone i wskazywane podczas profilowania).
Jak powiedziałem wcześniej, „przedwczesna optymalizacja” jest jednym z najbardziej złośliwie wykorzystywanych memów, więc odpowiedź nie będzie kompletna bez kilku przykładów rzeczy, które nie są przedwczesnymi optymalizacjami, ale czasami są odtrącane jako takie:
Ponadto nie są nawet związane z szybkością wykonywania środowiska wykonawczego:
przemyślany projekt z góry
pisanie statyczne (!)
itp. / wszelkie formy wysiłku umysłowego
źródło