Podczas tworzenia aplikacji ciągle pytam, czy to najlepszy sposób na wykonanie lub wdrożenie określonej funkcjonalności. Często zamieszczam pytania na temat stackoverflow lub innego forum, które chcą uzyskać informacje zwrotne tylko po to, aby otrzymywać komentarze na temat tego, jak nie „stawiać wózka przed koniem” w odniesieniu do wydajności. Czy większość programistów naprawdę nie myśli o wydajności, dopóki aplikacja nie zostanie zakończona lub wydajność jest absolutnie nie do przyjęcia? Rozumiem, że środowiska programistyczne różnią się od środowisk produkcyjnych i że nie powinieneś całkowicie polegać na wynikach swojego laptopa deweloperskiego ... ale istnieją praktyki i techniki, które zapewniają lepszą wydajność niż inne.
Czy złą praktyką jest uwzględnianie wydajności w całym procesie programowania? Czy powinienem odsuwać te uwagi, dopóki wydajność nie zacznie gwałtownie rosnąć?
Aktualizacja
Żeby było jasne, mówię o sytuacji, w której rozważasz lub właśnie pracujesz nad jakąś funkcjonalnością. Wiesz, że istnieje kilka sposobów na jego wdrożenie, ale nie jesteś pewien, jak dobrze każda implementacja będzie skalowana. Może być też kilka technik, których nawet nie znasz. Na małą skalę każde z tych podejść byłoby prawdopodobnie odpowiednie, ale na większą skalę niektóre nadążą, a niektóre nie. Często, gdy pytam o opinie lub wskazówki, odpowiedź brzmi: martw się później ...
źródło
Odpowiedzi:
Odroczenie rozważań dotyczących wydajności czasami opiera się na niewłaściwym zastosowaniu frazy:
Jeśli przeczytasz cały cytat, Knuth próbował powiedzieć, że mikrooptymalizacje zastosowane podczas programowania bez profilowania są na ogół niewskazane, ponieważ prowadzą do mniej konserwowalnego kodu, niekoniecznie osiągając znaczne korzyści w zakresie wydajności.
Ale to nie znaczy, że nie powinieneś brać pod uwagę wydajności, dopóki aplikacja nie zostanie prawie ukończona. Jeśli to zrobisz, może się okazać, że wydajność jest niewystarczająca, architektura projektowania nie obsługuje lepszej wydajności i musisz zacząć od nowa.
Jest wiele rzeczy, które możesz zrobić podczas programowania, aby osiągnąć dobrą wydajność bez ezoterycznych (i przedwczesnych) optymalizacji:
Jeśli to zrobisz, przekonasz się, że każda optymalizacja wydajności, która musi nastąpić, będzie ograniczona do niewielkiej części twojego kodu. Profilowanie zidentyfikuje ten kod i pozwoli skoncentrować się na poprawie wydajności tam, gdzie przyniosą największe korzyści, bez poświęcania łatwości konserwacji.
źródło
Oto, o czym NIE należy myśleć:
++i
szybszy niżi++
?switch
szybszy niżif
?inline
swoje funkcje?Oto, co myśleć o:
Jeśli chodzi o tę ostatnią kwestię, z mojego doświadczenia najlepiej jest zaprojektować strukturę danych, aby, jeśli trzeba ją znormalizować, aby była w stanie tolerować przejściową niespójność, którą można później rozwiązać poprzez pewien okresowy przegląd. Głównym zabójcą wydajności jest to, że powiadomienia uruchamiają kolejne powiadomienia, które są wyzwalane dalej, w stopniu, w jakim nigdy wcześniej byś nie zgadł. I często jest to zmarnowany wysiłek ze względu na samoczynne anulowanie zmian.
Jeśli to wszystko zrobiłeś, masz czysty projekt. Następnie okresowo, gdy go rozwijasz, profiluj. ( Metoda polegająca na pauzowaniu losowym jest metodą, na której polegam.) Jeśli więc zauważysz, że wydajność poprawiłaby się dzięki wprowadzeniu bardziej wyrafinowanego algorytmu, zrób to.
źródło
Nie, powinieneś pomyśleć o wydajności (szczególnie przy projektowaniu baz danych) od samego początku. Nasza branża wyrządziła wiele szkód osobom, które uważają, że optymalizacja jest przedwczesna. Cytat pierwotnie miał na celu uniemożliwienie ludziom patrzenia na mikrooptymalizacje przed wystąpieniem problemu. Nie miało to na celu żadnej optymalizacji. Na przykład w bazie danych istnieje wiele znanych technik, które działają słabo. Unikanie ich w projekcie jest częścią tego, co musisz zrobić. Refaktoryzacja bazy danych zawierającej 100 000 000 rekordów jest bardzo trudna, ponieważ została zaprojektowana przy użyciu słabo perforowanych technik i nie możemy już dłużej uniknąć tego problemu, kupując lepszy sprzęt.
źródło
Martw się najpierw o poprawność 1 , potem łatwość konserwacji, potem bezpieczeństwo i niezawodność, a potem możesz pomyśleć o wydajności. Zastosuj tę kolejność do każdego fragmentu kodu podczas jego opracowywania. Możliwe, że skuteczne rozwiązanie może w naturalny sposób wypaść z prostego utrzymywania sprawy w czystości.
80% wydajności wybiera odpowiedni algorytm i strukturę danych dla danego problemu; źle zoptymalizowany Quicksort nadal przeciera spodnie w wysoce zoptymalizowanym typie bąbelków w przeciętnym przypadku (najgorszy przypadek to remis).
To, co wszyscy w SO próbują rozwalić, to sposób myślenia „który jest szybszy, ++ p lub p ++”, w którym ludzie są tak pochłonięci przechytrzeniem kompilatora, że tracą świadomość większego problemu, co powoduje, że kod jest kruchy, błąd -zrozumiałe, złe , a co najważniejsze, nie tak dużo szybciej, niż byłoby prostsze rozwiązanie. Zajmowałem się tego rodzaju kodem z pierwszej ręki; jeden przykład był tak kruchy, że nie mogliśmy dokonać żadnych zmian bez całkowitego zerwania.
1 Gdzie „poprawność” oznacza „spełnienie specyfikacji”, co nie jest równoznaczne z „bezbłędnym”.
źródło
Powinieneś zacząć myśleć o wydajności, gdy wiesz, co to jest „dobra” wydajność. Innymi słowy, błędem byłoby zacząć myśleć o wydajności, zanim określisz, jakie są następujące progi:
Po ustaleniu, jakie są te progi, zidentyfikowałeś również dane, których używasz do mierzenia wydajności. Oznacza to, że możesz skonfigurować automatyczne testy wydajności, które możesz uruchamiać kilka razy dziennie. Dzięki temu dowiesz się, czy czujesz się lepiej, czy gorzej.
Aby wymyślić te wskaźniki, musisz zrozumieć, co powinien zrobić Twój system. Na przykład, czy wymagane są bezwzględne wskaźniki wydajności (odpowiedź w czasie X), czy też wymagane są pomiary przepustowości (X odpowiedzi na czas Y)? Optymalizacje przepustowości i czasu bezwzględnego wymagają różnych podejść, a jeśli nie wiesz, co jest naprawdę ważne, być może optymalizujesz niewłaściwie.
źródło
Prawdopodobnie słyszałeś, że przedwczesna optymalizacja jest źródłem wszelkiego zła. Pytanie, co sprawia, że jest przedwczesny? Moim zdaniem myślenie o wydajności nigdy nie jest złym pomysłem, ale nie przejmuj się nadmiernie, dopóki Twój kod nie zadziała. Gdy to zadziała, przeprowadź testy przy dużym obciążeniu, profiluj i identyfikuj wąskie gardła oraz dokonuj optymalizacji wydajności.
Biorąc to pod uwagę, nie ma nic złego w myśleniu o wydajności na początkowym etapie kodowania, jeśli znasz pewne techniki, które zrobią prawdziwą różnicę. Na przykład wybranie jednej struktury pamięci z biblioteki zamiast innej, ponieważ wcześniejsze doświadczenia nauczyły cię, że jedna z nich jest szybsza / zużywa mniej pamięci RAM niż druga. Lub wbudowanie w prosty (możesz uczynić go bardziej wyrafinowanym, jeśli wymaga tego późniejszy test) system buforowania dla danych, które znaszbędą często używane i będą lepiej buforowane. W ten sposób nie martwisz się zbytnio wydajnością (przynajmniej początkowo), ale używasz wskazówek i sztuczek, których nauczyłeś się po drodze z innych projektów. Staraj się, aby były one proste, aby można je było łatwo uwzględnić podczas początkowego rozwoju, i mogą również przynieść pewne korzyści.
źródło
Wydajność powinna być wyszczególniona w specyfikacji systemu i użytkownika w dokumencie wymagań. Wiem, że wiele osób szydzi z pomysłu podjęcia analizy wymagań podczas opracowywania aplikacji, ale zadziwiająco taki dokument zwięźle odpowie na to, na co i gdzie powinieneś poświęcić zasoby związane z wydajnością, gdy aplikacja zbliża się do końca. I odpowie na to pytanie w odpowiednim czasie
Dokumentacja wymagań pozwoli Ci zaoszczędzić setki godzin czasu, które w innym przypadku zostałyby zmarnowane na nieistotne procesy.
źródło
Lepsze byłoby zrównoważone podejście. Wydajność jest ważna, ale nie tak ważna, jak wykonywanie zadań, więc:
To jest moje wspólne podejście do wydajności i funkcjonalności, a ogólnie rzecz biorąc, wszystko zależy od tego, co robi program, i sprawdzenia, czy jest jakaś potrzeba ulepszenia działania i ile mnie to kosztowało.
Pomyślmy o takiej stronie pytań i odpowiedzi, myślę, że osoby, które się za nią stoją, z pewnością dużo zastanawiały się, jak zadać pytanie i uzyskać odpowiedź na jak najwięcej czasu / kosztów. Ale myśląc o powiadomieniach, naprawdę nie ma większego znaczenia, czy powiadomienia pojawiają się raz na jakiś czas i informują, że jest nowa odpowiedź lub coś takiego.
źródło
Istnieje jeden sposób bezpiecznego odroczenia myślenia o wydajności: w miarę możliwości przy użyciu języków specyficznych dla domeny.
Jeśli większość prac rozwojowych można wykonać za pomocą własnych małych list DSL, a są one wystarczająco dobrze zaprojektowane, aby wyrazić domenę problemów w najbardziej ogólnej formie i na wysokim poziomie, możliwe jest, aby najpierw uzyskać działający prototyp, bez zastanowienia się nad tym. wydajność, a następnie ulepszaj tylko implementacje DSL, a nie rzeczywisty kod domeny problemu.
Jest to również znacznie lepsze podejście z punktu widzenia łatwości utrzymania.
źródło
Powinieneś wziąć pod uwagę wydajność. Musisz jednak narysować linię, aby zaznaczyć koniec strojenia, ponieważ (zwykle) twój czas jest ważniejszy niż komputer.
Naprawdę dobrym tekstem na temat wydajności jest: The Computer Performance Shell Game .
źródło
„Najlepszy” sposób jest bardzo obciążonym terminem, a odpowiedź może być wysoce zależna od czynników nieznanych do czasu uruchomienia.
Lista jest długa.
Co może zrobić, to napisać „najprostszą rzeczą, która mogłaby praca” z wiedzy obecnie nie mają, i zrobić to w modułowej mody, dzięki czemu można łatwo reorganizacji, gdy wiesz więcej. Pamiętaj, że „najprostsza” rzecz niekoniecznie jest prosta!
źródło
Zawsze należy o tym pamiętać. Myślę, że większość ludzi próbuje powiedzieć, że nie ma sensu spędzać dwóch dni na optymalizacji czegoś, o czym nawet nie wiesz, że jest zepsute. Po uruchomieniu produktu i przeprowadzeniu testów użyteczności powinien on pokazać, gdzie występują problemy z wydajnością. Następnie, gdy zidentyfikujesz prawdziwe problemy z wydajnością, możesz kierować się optymalizacjami, które musisz wykonać.
źródło
Teoretycznie powinieneś zacząć myśleć o wydajności, gdy jesteś w fazie testów beta, a nie wcześniej.
Nie jest to jednak licencja na podejmowanie złych decyzji projektowych. Na przykład użycie ciągu NVARCHAR jako klucza podstawowego jest pewną ścieżką do niskiej wydajności; powiedziawszy, jest to brudny nawyk, niezależnie od problemów z wydajnością i nie powinieneś go używać.
Jeśli Twój projekt jest zgodny z konwencjonalnymi najlepszymi praktykami (wszystko w trzeciej normalnej formie, odpowiednie informacje ukryte w twoich zajęciach, minimalne użycie singletonów itp.), A później wystąpi problem z wydajnością, będzie łatwo go obsłużyć (utwórz tutaj indeks, zaimplementuj tam pamięć podręczną).
HTH
źródło
To zależy. Warto pamiętać o zasadzie 80/20: większość (powiedzmy 80%) kodu w aplikacji nigdy nie będzie wykonywana wystarczająco często, aby wprowadzić zauważalną różnicę w wydajności. Musisz skupić się na pozostałych 20%, w przypadku których aplikacja będzie musiała spędzić około 80% czasu wykonywania.
Być może będziesz w stanie z wyprzedzeniem zidentyfikować niektóre z najbardziej popularnych punktów wydajności, na przykład jeśli wiesz, że określone obliczenia będą powtarzane miliony razy. W takich przypadkach zdecydowanie warto pomyśleć o optymalizacji z góry, wybierając odpowiednie struktury danych i algorytmy dla zadania.
Jednak ta optymalizacja jest raczej działaniem projektowym. To, co zwykle jest bezwartościowe, to mikrooptymalizacje, w których ktoś spędza nadmiernie dużo czasu ze sprytnymi sztuczkami polegającymi na grze w bicie w imię „zwiększania wydajności”. Zwłaszcza jeśli dokonano tego bez odpowiednich pomiarów przed i po, takie zmiany mogą nie mieć znaczenia lub faktycznie spowolnić aplikację w rzeczywistych okolicznościach.
źródło
To zależy od tego, na jakim etapie rozwoju jesteś
1) Jeśli budujesz funkcjonalność swojego oprogramowania, kontynuuj je i upewnij się, że działa dobrze (tj. Jest pożądane i wydajne).
2) Po zintegrowaniu bloków konstrukcyjnych dostaniesz wskazówkę dotyczącą przechwytywania zasobów, tam masz miejsce na optymalizację.
źródło
Jeśli musisz zacząć myśleć o wydajności, masz kłopoty. Powinieneś cały czas myśleć o wydajności. Podejrzewam, że dobrzy programiści będą myśleć o wydajności, nawet jeśli nie zamierzają, w stylu „mężczyźni myślą o seksie co siedem sekund”…
Ważne jest, jakie działania podejmiecie w oparciu o całe to myślenie. Myśli są tanie, ale działania mogą złamać kod i skrócić terminy.
W większości przypadków jedynym sensownym działaniem będzie nic nie robić: ustaliłeś, że twój kod nie będzie wywoływany wystarczająco często, aby można było zaobserwować problemy z wydajnością - być może jest to fragment kodu startowego, który uruchamia się raz na komputer dla 1% twojej potencjalnej bazy użytkowników, może to trochę zbędnego kodu serwera zatopionego w morzu powolnego dostępu do bazy danych, może to tylko liczba całkowita w niekrytycznej części kodu.
Dość często podejrzewasz, że dana operacja może powodować problem z wydajnością, który można rozwiązać za pomocą prostej zmiany. Jest na przykład dokuczliwe uczucie, że uruchamianie złożonego zapytania SQL przy każdym żądaniu lub dwukrotne proszenie o ten sam fragment danych ze słownika będzie dla ciebie złe. Tutaj przydaje się znajomość technik optymalizacji i być może najbardziej zaskakujący wniosek:
Jeśli znasz szybką technikę, która prawie na pewno poprawi wydajność fragmentu kodu, nie rób tego.
Jeśli teraz możesz o tym pomyśleć, możesz to zrobić w pięć minut później. Trzymanie go poza kodem (ale być może w
// TODO
komentarzu) pozostawia kod czystszy i pozwala zaoszczędzić czas do pracy nad inną funkcją, a jednocześnie nie marnować czasu, jeśli w końcu wyrzucisz ten kod później. Jeśli oryginalny kod okaże się powodować problemy z wydajnością podczas testowania, wróć i zastosuj szybką technikę.Nie mówię tutaj, że powinieneś unikać pisania kodu, który jest idiomatyczny tylko dlatego, że dzieje się to szybciej. Napisz idiomatyczny kod zgodnie z najlepszymi praktykami, które poprawiają wydajność i czytelność oraz redukują błędy. Po prostu, jeśli masz wybór między idiomatycznym kodem z książki a szybszą, ale łatwą do napisania alternatywą, zawsze wybieraj czytelność zamiast szybkości.
Jedyną trudną sytuacją jest sytuacja, w której wydaje się, że nie ma łatwego sposobu na poprawienie wydajności kodu, a jednak boleśnie oczywiste jest, że kawałek kodu zepsuje się, gdy tylko zostanie dostarczony - pełne przejście do bazy danych za każdym kliknięciem, sto zapytań SQL na stronę w witrynie lub coś równie strasznego. Właśnie tam musisz się zatrzymać i przemyśleć coś jeszcze. Są to zwykle problemy związane z architekturą, których i tak nie można rozwiązać na skalę lokalną. Potwierdź swoje podejrzenia szybkim skokiem lub prototypem, poszukaj podobnych doświadczeń i typowych rozwiązań oraz rozważ zmianę architektury lub spadek funkcji.
źródło
IMHO ważne jest, aby pomyśleć o wydajności przed wdrożeniem systemu, ale tylko o tym pomyśleć. Powinieneś przeanalizować aplikację i dowiedzieć się, jakie potencjalnie mogą być wąskie gardła wydajności.
Następnie zaimplementuj system tak prosto, jak to możliwe. Jeśli pojawią się problemy z wydajnością, zoptymalizuj.
Załóżmy na przykład, że masz klienta GUI, który pobiera dane za pośrednictwem jakiejś usługi (SOAP, REST HTTP itp.). Zatem najważniejszą rzeczą dla wysokiej wydajności / skalowalności jest posiadanie jak najmniejszej liczby połączeń, przy czym każde połączenie zwraca dużo danych, a nie tyle dużej liczby połączeń, z których każda zwraca niewiele informacji, tzn. Wolą masywną komunikację niż rozmowę.
Podczas wdrażania tego rodzaju systemu nie przejmowałbym się tak bardzo liczbą połączeń między systemem. Ale upewniłbym się, że baza kodu ułatwi mi refaktoryzację / optymalizację, gdy zajdzie taka potrzeba.
źródło
Od samego początku powinieneś myśleć o wydajności w bardzo ogólny sposób. Powinieneś wybrać struktury danych i algorytmy, które będą dobrze działać dla twojej aplikacji i będą względnie wydajne. Algorytmy mają fundamentalne znaczenie dla oprogramowania, a struktury danych bardziej. Prawdopodobnie będziesz musiał dokonać poważnych przeróbek, jeśli będziesz musiał dokonać poważnych zmian w jednym z nich, a mniejsze szczegóły można łatwiej przepisać.
Możesz także chcieć uzyskać skuteczne nawyki, ale będą one zależeć od języka. Na przykład w C ++ „++ i;” jako samodzielna instrukcja lub wyrażenie jest zawsze co najmniej tak dobre, jak „i ++;” i może potencjalnie być znacznie wydajniejsze. Jednak w większości przypadków powinieneś napisać czysty kod i zaufać kompilatorowi. Nabycie nawyku martwienia się o mikro-wydajność prawie na pewno spowoduje więcej problemów niż rozwiązuje. W przypadku aplikacji komputerowych albo kompilator jest co najmniej tak inteligentny, jak ty w kwestii takich jak
i >> 1
vs.i / 2
, lub najlepszym sposobem na poprawę wydajności jest uzyskanie lepszego kompilatora, więc nie martw się o to.Poza tym nie martw się dużo, dopóki nie masz czegoś, co możesz przetestować. W tym momencie możesz profilować program, aby zobaczyć, gdzie znajdują się gorące punkty, i prawdopodobnie masz pomysł, czy masz program wydajnościowy, czy nie. Jeśli chcesz poprawić wydajność, dowiedz się, gdzie program spędza większość czasu i popraw tam rzeczy. Jeśli zaprojektowałeś odpowiednią globalną wydajność i dobrze napisałeś program, zmieniasz tylko stosunkowo niewielką część programu.
źródło
Myślę, że najlepsze, co możesz zrobić, to postępować zgodnie z dobrymi praktykami projektowymi (np. Nie rób rzeczy, o których wiesz, że obniżą wydajność), dopóki nie zaczniesz działać. Jeśli nie możesz zmierzyć poprawy, nie możesz dokonać poprawy. Gdy już masz coś, z czym możesz przetestować, często dobrym pomysłem jest przeprowadzenie profilowania i ustalenie, gdzie znajdują się hotspoty (jeśli takie istnieją). Jeśli coś na ciebie wyskoczy, powinieneś rozważyć przeredagowanie lub przepisanie obszaru problemu, ale jeśli nie jest tak źle (tylko dlatego, że kod spędza 90% czasu na dwie lub trzy metody, nic nie znaczy, jeśli działa odpowiednio ogólnie) to po prostu rozwijaj się. Niejednokrotnie widziałem programistów, którzy spędzają dni optymalizując najbardziej złożoną część systemu,
źródło
Kiedy powinienem zacząć o tym myśleć? Ile wysiłku powinienem w to włożyć? To zależy od skali Cockburn projektu. (Innymi słowy, jakie jest ryzyko braku dobrej wydajności?)
Nauczyć się podstaw dużym wyprzedzeniem (patrz Roberta Harveya odpowiedź ). Aby zastosować myślenie zorientowane na wydajność na różnych etapach tworzenia oprogramowania, deweloper musi znać je na wylot, aby te dodatkowe uwagi nie utrudniały procesu myślenia. (Innymi słowy, zacznij myśleć o wydajności, zanim powstanie projekt).
Na wczesnym etapie rozwoju swobodnie korzystaj z narzędzi do profilowania wydajności i śledź historię statystyk. Zwróć szczególną uwagę na organizowanie takich informacji, aby były przydatne w późniejszym podejmowaniu decyzji.
Następnie, w zależności od charakteru projektu i jego skali Cockburn:
Szybkie prototypowanie lub „wybijaj kod, jakby nie było jutra”, lub wewnętrzny rozwój o niskim wpływie na biznes: po prostu zachowaj statystyki. Nie myśl jeszcze o wydajności. Zaimplementuj tę funkcję w najprostszy sposób. Trzymaj się pierwszego algorytmu, który przychodzi ci na myśl.
Aplikacje komputerowe, które wymagają spójnego, wszechstronnego podejścia do wydajności. Nie musi być wysoce zoptymalizowany; jednak powinno być jak najmniej „zawieszeń” (brak odpowiedzi).
Komputery o wysokiej wydajności, które wymagają jak największej wydajności sprzętu.
źródło
Na początku. Zidentyfikuj wymagane parametry wydajności. Jeśli nie możesz zidentyfikować celu, musisz albo cofnąć się, aby lepiej zrozumieć swoje wymagania, albo odroczyć, dopóki nie poznasz wymagań komponentu z ryzykiem, które możesz przepisać. Następnie przetestuj. Nie optymalizuj, testuj. Jeśli kod nie przejdzie testu wydajności, zoptymalizuj. Po wdrożeniu struktury testowej użycie istniejących narzędzi do monitorowania wydajności powinno znacznie ułatwić zadanie.
Zachowaj testy wydajności przez cały czas trwania projektu jako test regresji. Kod konserwacji jest znany z wywoływania problemów z wydajnością, ponieważ „poprawki” często mają bardzo wąski zakres.
źródło
Zawsze polegam na prostej formule:
... w tej kolejności.
Według c2 , ten preparat przypisuje się Kentowi Beckowi .
źródło