Czy mikro-optymalizacja jest ważna podczas kodowania?

178

Niedawno zadałem pytanie na temat przepełnienia stosu, aby dowiedzieć się, dlaczego isset () był szybszy niż strlen () w PHP . Rodziło to pytania dotyczące znaczenia czytelnego kodu i tego, czy warto poprawić wydajność mikrosekund w kodzie, czy nawet warto.

Mój ojciec jest emerytowanym programistą i pokazałem mu odpowiedzi. Był absolutnie pewien, że jeśli koder nie bierze pod uwagę wydajności swojego kodu nawet na poziomie mikro, nie są dobrymi programistami.

Nie jestem tego pewien - być może wzrost mocy obliczeniowej oznacza, że ​​nie musimy już brać pod uwagę tego rodzaju ulepszeń mikroprocesorów? Być może tego rodzaju rozważania podejmują ludzie, którzy piszą rzeczywisty kod języka? (PHP w powyższym przypadku).

Czynniki środowiskowe mogą być ważne - Internet zużywa 10% światowej energii. Zastanawiam się, jak marnotrawstwem jest kilka mikrosekund kodu, jeśli powielają się biliony razy na milionach stron internetowych?

Chciałbym poznać odpowiedzi najlepiej oparte na faktach na temat programowania.

Czy mikro-optymalizacja jest ważna podczas kodowania?

Moje osobiste podsumowanie 25 odpowiedzi, dzięki wszystkim.

Czasami musimy naprawdę martwić się mikrooptymalizacjami, ale tylko w bardzo rzadkich przypadkach. Wiarygodność i czytelność są w większości przypadków znacznie ważniejsze. Jednak rozważanie mikrooptymalizacji od czasu do czasu nie zaszkodzi. Podstawowe zrozumienie może pomóc nam nie dokonywać oczywistych złych wyborów podczas kodowania takich jak

if (expensiveFunction() || counter < X)

Powinien być

if (counter < X || expensiveFunction())

( Przykład z @ zidarsk8 ) Może to być niedroga funkcja i dlatego zmiana kodu byłaby mikrooptymalizacją. Ale przy podstawowym zrozumieniu nie musiałbyś, bo w pierwszej kolejności napisałbyś to poprawnie.

Boz
źródło
123
Rady twojego ojca są nieaktualne . Nie zapytałbym, jak bardzo to poprawia wydajność. Zapytałbym, gdzie jest wąskie gardło. Nie ma znaczenia, czy poprawisz wydajność sekcji kodu, jeśli nie robi to ogólnej różnicy, twój najwolniejszy link określi prędkość. W PHP jest to zapisywanie w sieci (chyba że można udowodnić, że IE zmierzy inaczej); co przekłada się na pisanie bardziej czytelnego kodu jest ważniejsze.
Martin York,
61
Jeśli rozważane jest słowo kluczowe, nie myli się. Musisz mieć o tym jakieś wskazówki.
JeffO,
37
Jest mi smutno, ponieważ nie wspomniano o słynnym cytacie „ Przedwczesna optymalizacja ”: „Programiści marnują mnóstwo czasu na myślenie lub martwienie się o szybkość niekrytycznych części swoich programów, a te próby wydajności mają silny negatywny wpływ wpływ przy rozważaniu debugowania i konserwacji. Powinniśmy zapomnieć o małej wydajności, powiedzmy w około 97% przypadków: przedwczesna optymalizacja jest źródłem wszelkiego zła . Jednak nie powinniśmy tracić naszych możliwości w tak krytycznych 3%. ”
Tamara Wijsman,
13
Czy możesz podać źródło „10% światowej energii”?
Michał Wielkanoc
17
coder does not consider performance in their code even at the micro level, they are not good programmersróżni się bardzo od mikrooptymalizacji. To po prostu dobre kodowanie.
woliveirajr

Odpowiedzi:

90

Obaj się zgadzam i nie zgadzam z twoim ojcem. Wydajność powinna być brana pod uwagę wcześnie, ale mikrooptymalizacja powinna być rozważana tylko wcześnie, jeśli faktycznie wiesz, że duży procent czasu zostanie spędzony w małych sekcjach kodu związanych z procesorem.

Problem z mikrooptymalizacją polega na tym, że zwykle odbywa się to bez pojęcia, jak programy faktycznie spędzają więcej czasu niż to konieczne.

Ta wiedza pochodzi z doświadczenia w dostrajaniu wydajności, tak jak w tym przykładzie , w którym pozornie prosty program, bez oczywistych nieefektywności, jest przeprowadzany przez szereg etapów diagnozy i przyspieszania, aż jest 43 razy szybszy niż na początku.

Pokazuje to, że tak naprawdę nie można zgadnąć ani zrozumieć, gdzie będą problemy. Jeśli wykonasz diagnozę, która w moim przypadku jest losowo wstrzymywana , wiersze kodu odpowiedzialne za znaczną część czasu są preferencyjnie widoczne. Jeśli na nie spojrzysz, możesz znaleźć kod zastępczy, a tym samym skrócić całkowity czas o mniej więcej tę część.

Inne rzeczy, których nie naprawiłeś, nadal zajmują tyle samo czasu, co wcześniej, ale ponieważ ogólny czas został skrócony, te rzeczy zajmują teraz większy ułamek, więc jeśli zrobisz to wszystko jeszcze raz, tę część można również wyeliminować. Jeśli będziesz to robić przez wiele iteracji, w ten sposób możesz uzyskać ogromne przyspieszenia, bez konieczności dokonywania jakiejkolwiek mikrooptymalizacji .

Po takim doświadczeniu, kiedy podchodzisz do nowych problemów programistycznych, zaczynasz rozpoznawać podejścia projektowe, które początkowo prowadzą do takich nieefektywności. Z mojego doświadczenia wynika, że ​​to nadmierne projektowanie struktury danych, nienormalizowana struktura danych, ogromne poleganie na powiadomieniach, tego typu rzeczy.

Mike Dunlavey
źródło
120

Mikrooptymalizacja jest ważna tylko wtedy, gdy liczby mówią, że jest.

Wymagania, które opracowujesz, powinny zawierać specyfikację danych dotyczących wydajności, jeśli wydajność jest w ogóle problemem dla klienta lub użytkownika. Podczas opracowywania oprogramowania powinieneś przetestować wydajność swojego systemu pod kątem tych wymagań. Jeśli nie spełniasz wymagań dotyczących wydajności, musisz wyprofilować bazę kodu i zoptymalizować w razie potrzeby, aby osiągnąć wymagania dotyczące wydajności. Gdy osiągniesz minimalną wymaganą wydajność, nie musisz wyciskać żadnej większej wydajności z systemu, szczególnie jeśli zamierzasz narazić na szwank czytelność i łatwość konserwacji kodu (z mojego doświadczenia wysoce zoptymalizowany kod jest mniej czytelny i łatwe do utrzymania, ale nie zawsze). Jeśli możesz uzyskać dodatkowy wzrost wydajności bez pogorszenia innych atrybutów jakości systemu,

Są jednak przypadki, w których wydajność ma ogromne znaczenie. Myślę głównie w systemach czasu rzeczywistego i systemach wbudowanych. W systemach czasu rzeczywistego zmiana kolejności operacji może mieć ogromny wpływ na dotrzymywanie trudnych terminów wymaganych do prawidłowego działania, a może nawet wpływać na wyniki obliczeń. W systemach wbudowanych zwykle masz ograniczoną pamięć, moc procesora i moc (tak jak w przypadku baterii), więc musisz zmniejszyć rozmiar plików binarnych i zmniejszyć liczbę obliczeń, aby zmaksymalizować żywotność systemu.

Thomas Owens
źródło
Z drugiej strony, jeśli istnieje problem między używaniem wolniejszej a szybszej funkcji, nie ma powodu, aby używać wolniejszej funkcji - tak jak w przypadku isset.
Mavrik
7
@Mavrik To prawda. Jeśli masz dwie funkcje, X i Y, a Y jest szybsze niż X (przynajmniej w określonych warunkach), nie ma powodu, aby nie używać Y, jeśli kod jest nadal tak czytelny i łatwy do utrzymania. Ale jeśli nie wiesz o Y i musisz zmienić kod, aby użyć Y zamiast X, a wydajność (tego segmentu kodu) nie stanowi problemu, nie ma powodu, aby wprowadzać tę zmianę. Chodzi o kompromisy - wydajność, czas, koszt, wysiłek, czytelność / łatwość konserwacji i tak dalej.
Thomas Owens
2
Zgadzam się z całego serca, chciałem tylko powiedzieć o tym, jeśli chodzi o mikrooptymalizację - jeśli nie kosztuje cię to pod względem czytelności / czasu, zrób to. W przeciwnym razie nie.
Mavrik,
Wysoce zoptymalizowany kod +1 jest mniej czytelny i łatwy do utrzymania ... ale nie zawsze.
Boz
Więcej przypadków, w których ważna jest wydajność: (1) gry; (2) duże ilości danych; (3) strona internetowa o dużym ruchu; (4) responsywność bardzo złożonego interfejsu użytkownika; (5) usługa, która powinna działać w tle, jak sprawdzanie wirusów; (6) finanse; (7) smartfon; i tak dalej. Nie ogranicza się to do przypadków ezoterycznych, takich jak RTS i systemy wbudowane.
Rex Kerr,
103

Gdy ktoś prosi o optymalizacji , przypomina mi się cytat z Michael A. Jackson

Pierwsza zasada optymalizacji programu: nie rób tego.

Druga zasada optymalizacji programu (tylko dla ekspertów!): Nie rób tego jeszcze .

Cytat z Wikipedii poprawiony na angielski brytyjski. * 8 ')

Implicite w drugą zasadą jest, aby profil kodu i tylko spędzać czas optymalizacji rzeczy, które uczynią różnicę.

Podczas programowania w asercji stwierdzenie twojego ojca było prawidłowe. Ale to jest znacznie bliżej metalu niż większość ludzi programuje obecnie. Dzisiaj nawet próba zoptymalizowania się (bez profilowania) może spowodować spowolnienie działania kodu, niż gdybyś zrobił coś bardziej powszechnego, ponieważ wspólny sposób jest bardziej zoptymalizowany przez nowoczesne kompilatory JIT .

Nawet w C musisz być całkiem dobry w optymalizacji, aby dowiedzieć się więcej o tym, jak zoptymalizować sekcję kodu niż kompilator.

Jeśli nie jesteś zaznajomiony z tym, o czym mówi Ulrich Drepper w swoim znakomitym artykule Co każdy programista powinien wiedzieć o pamięci , to prawdopodobnie przegrywasz nawet próbując się zoptymalizować. Jednak wbrew tytułowi artykułów (który jest hołdem dla równie fantastycznego Davida Goldberga, co każdy informatyk powinien wiedzieć o arytmetyki zmiennoprzecinkowej ) brak takiego poziomu zrozumienia niekoniecznie powstrzymuje cię od bycia dobrym programistą, po prostu innego rodzaju programista.

isset()vs. strlen()w PHP

Nie znam PHP, więc tak naprawdę nie jest oczywiste, co isset()należy zrobić. Mogę wywnioskować to na podstawie kontekstu, ale oznacza to, że będzie on podobnie niejasny dla początkujących programistów PHP, a może nawet spowodować, że bardziej doświadczeni programiści się podniosą. Jest to rodzaj idiomatycznego użycia języka, który może uczynić utrzymanie koszmarem.

Nie tylko, ale nie ma gwarancji, że isset()zawsze będzie bardziej wydajna, tylko dlatego, że jest teraz bardziej wydajna. Optymalizacja może nie być optymalizacją w przyszłym roku lub za 10 lat. Procesory, systemy, kompilatory poprawiają się i zmieniają z czasem. Jeśli wydajność PHP strlen()jest problemem, PHP może zostać zmodyfikowany w przyszłości, wówczas może być konieczne usunięcie wszystkich optymalizacji isset (), aby zoptymalizować kod jeszcze raz.

Każda optymalizacja może stać się przyszłą antyoptymalizacją , dlatego należy ją uznać za możliwy zapach kodu, który należy ograniczyć do minimum.

Przykład z własnego doświadczenia

Jako przykład takiej antyoptymalizacji musiałem kiedyś zdezynfekować ogromną bazę kodu wypełnioną kodem formularza, if x==0 z=0 else z=x*yponieważ ktoś zakładał, że mnożenie zmiennoprzecinkowe zawsze będzie droższe niż gałąź. W oryginalnej architekturze docelowej ta optymalizacja przyspieszyła działanie kodu o rząd wielkości, ale czasy się zmieniają.

Kiedy próbowaliśmy użyć tego kodu na bardziej nowoczesnym procesorze, który był wysoce potokowy, wydajność była przerażająco słaba - każda z tych instrukcji powoduje opróżnienie potoku. Uproszczenie wszystkich tych linii kodu, aby z=x*yprogram działał szybciej o rząd wielkości w nowej architekturze, przywracając wydajność utraconą przez antyoptymalizację .

Problemy, które zwykle musimy optymalizować na dziś, są bardzo różne od problemów , które musieliśmy optymalizować 20 lub nawet 10 lat temu.

Potem martwi robi najwięcej pracy na cykl zegara, teraz jesteśmy bardziej prawdopodobne martwić uderzenia rurociągu, mispredictions branży i tęskni cache na poziomie procesora, ale zamków i komunikacji międzyprocesowej stają się o wiele bardziej znaczące, jak iść do multi- architektury procesowe i wieloprocesorowe. Artykuł Dreppera może naprawdę pomóc w zrozumieniu wielu z tych problemów.

Mark Booth
źródło
3
Opróżniania potoków i spudłowania z pamięci podręcznej to to, czego chcesz unikać: D Mają straszne koszty. ale tylko na fragmentach kodu, które ekscytują ich wiele, wiele, wiele, wiele razy.
deadalnix
7
Chciałbym dodać, że kompilatory przeszły długą drogę i zoptymalizują wiele rzeczy. AFAIK, lepiej optymalizują czysty, czytelny kod niż podstępne rzeczy.
Becuzz,
3
+1 za dostarczenie prawdziwego przykładu mikrooptymalizacji, która zmarnowała czas - i ujawnienie, że Michael Jackson był programistą.
Boz
1
+1 Na przykład. Doskonale ilustruje, dlaczego należy pozostawić kompilatorowi trywialne przekształcenia.
back2dos,
1
@Rex Kerr> przykładowo, koszt pochodzi z rozgałęzienia, które powoduje opróżnienie potoku procesora. Mnożenie zmiennoprzecinkowe jest również drogie. To, co jest droższe, zależy w dużej mierze od FPU i długości potoku procesora obsługującego kod. Nie zdziwiłbym się, że ten kod działał szybciej na starszych procesorach, które mają krótszy potok i mniej wydajne FPU niż obecny procesor.
deadalnix,
84
  1. Napisz kod, który jest czysty, zwięzły, prosty i zrozumiały.
  2. Wykonaj testy wydajności, aby zidentyfikować wąskie gardła.
  3. Zoptymalizuj krytyczne sekcje.

Zasadniczo: 95% kodu jest uruchamiane przez 5% czasu. Optymalizacja nie ma sensu przed profilowaniem / testowaniem kodu i sprawdzaniem, które 5% są uruchamiane w 95% przypadków.

Każdy idiota może przeprowadzić mikrooptymalizację, a każdy przyzwoity kompilator / środowisko wykonawcze zrobi to za Ciebie.
Optymalizacja dobrego kodu jest banalna. Pisanie zoptymalizowanego kodu i próba jego poprawienia po tym jest nużące, aw najgorszym nie do utrzymania.

Jeśli poważnie zależy Ci na wydajności, nie używaj PHP do kodu krytycznego dla wydajności. Znajdź wąskie gardła i przepisz je z rozszerzeniami C. Nawet mikrooptymalizacja kodu PHP poza punktem zaciemnienia nie zapewni Ci prawie tak dużej prędkości.

Osobiście bardzo lubiłem robić mikrooptymalizację, kiedy zaczynałem programować. Ponieważ to oczywiste. Ponieważ nagradza cię szybko. Ponieważ nie musisz podejmować ważnych decyzji. To idealny sposób na zwlekanie. Pozwala uciec od naprawdę ważnych części tworzenia oprogramowania: projektowania skalowalnych, elastycznych, rozszerzalnych, solidnych systemów.

back2dos
źródło
2
Co ciekawe, najlepszą odpowiedź znalazłem w Przewodniku dla deweloperów Bugzilli: „Jeśli starasz się być sprytny, a nie czytelny, to może próbujesz sprawić, że wszystko będzie„ szybsze? ”. Jeśli tak, pamiętaj : nie rozwiązuj problemu, zanim się zorientujesz. Jeśli nie wiesz (za pomocą rzeczywistych, szczegółowych testów), że Twój kod działa wolno, nie martw się, że będzie on „szybszy”. Nie ogranicza się to tylko do optymalizacja - wielu programistów stale rozwiązuje problemy, których nikt nigdy nie doświadczył. Nie rób tego ”. bugzilla.org/docs/developer.html#general
Marco
7
Generalnie się zgadzam - z wyjątkiem jednej linii, twierdzę, że „każdy idiota myśli, że może mikrooptymalizować” ...;)
Nim
@Nim: Punkt zajęty;)
back2dos
26

Zgadzam się z twoim ojcem: „Jeśli programista nie bierze pod uwagę wydajności swojego kodu nawet na poziomie mikro, nie jest dobrym programistą”. Kluczem jest „rozważenie wydajności”. Nie jest to równoważne z „przeprowadzaniem mikrooptymalizacji na każdym etapie”.

Zgadzam się z większością innych komentarzy - co kiedyś przyspieszało działanie programów C, dziś może tego nie robić - ale należy wziąć pod uwagę inne poważne kwestie: Czy powinienem używać C lub C ++? Klasy z prostymi przeciążonymi operatorami mogą zabić wydajność, jeśli często ich używasz. Czy to ma znaczenie? To zależy od twojej aplikacji, ale jeśli nawet NIE UWAŻASZ, nie jesteś bardzo dobrym programistą. Niektórzy ludzie mogą to rozważyć przez około 2 milisekundy i odrzucić, ale myślę, że zbyt wielu dosłownie nawet tego nie rozważa.

Rzeczywistość jest taka, że ​​dzięki optymalizacji kod może być trudniejszy do odczytania. Napisanie kodu zajmie więcej czasu. Kod znajdzie się gdzieś pomiędzy trochę szybciej a rzędem wielkości szybciej (to rzadkość). Twoi klienci prawdopodobnie nie znają różnicy.

Inną rzeczywistością jest to, że ludzie lubią ponownie wykorzystywać kod, a jego miejsce może być zupełnie inne niż wtedy, gdy go napisałeś. Nagle ludzie mogą się tym przejmować.

Na przykład powiedz, że napisałeś coś w stylu Angry Birds na PC lub na konsolę do gier. Zignorowałeś optymalizację w swoim systemie fizyki i systemie graficznym - ponieważ podwójne rdzenie 2,5 GHz są obecnie w zasadzie minimum, a gra działa wystarczająco dobrze. Potem pojawiają się smartfony i chcesz je przenieść. O rany, rdzeń ARM 600 MHz ?

Pomyśl o stronie internetowej - coś połączonego w weekend, na przykład Hot or Not . Używasz dowolnej bazy danych, pisz wszystko z myślą o szybkim rozwoju, uruchamiaj, wysyłając do znajomych adres URL. Trzy miesiące później twój serwer umiera z powodu przeciążenia i nie możesz nic zrobić, aby go skalować. To się zdarza cały czas. Największe strony internetowe mają rachunki za prąd mierzone w setkach kilowatów, a nawet megawatów. Pomyśl o tym, istnieją megawaty do zapisania dzięki optymalizacji kodu.

Tak jak powiedział twój ojciec, musisz przynajmniej to rozważyć . Większość ludzi nawet nie wie, ile wydajności jest na stole i rzuca na nią okiem szybkim żartem o „przedwczesnej optymalizacji” i „nie rób tego”. To nie są dobrzy programiści.

To nie jest popularna opinia na tych stronach. Do zobaczenia punkty reputacji ....

phkahler
źródło
3
Jasne, powinieneś to rozważyć (z tyłu głowy) i zwykle odrzucić, chyba że jest to warte zachodu. Należy wziąć pod uwagę, że optymalizacje zwykle zmniejszają czytelność kodu i mogą wydłużyć czas potrzebny na kodowanie i utrzymanie go o współczynnik około 10. Jeśli program nie wymaga dużego procesora, często nie jest potrzebny. Uznaj, że twój kompilator jest zwykle znacznie lepszy w optymalizacji niż ty, i że wiele twoich optymalizacji faktycznie obniży wydajność. Jeśli nie warto poświęcić czasu na testowanie optymalizacji i profilu, nie warto poświęcać czasu na optymalizację.
dr jimbob
3
Swój zły ptaków przykład pokazuje dokładnie, dlaczego powinno nie zoptymalizować przedwcześnie. Podczas przenoszenia z komputera na konsolę na urządzenia mobilne masz do czynienia z (co najmniej) trzema bardzo różnymi rodzajami sprzętu i optymalizacja jednego z nich może zaszkodzić zamiast pomóc drugiemu. Co gorsza, optymalizacja sprawi, że kod będzie trudniejszy do zrozumienia, a zatem trudniejszy do przeniesienia. Oczywiście, wybieraj wydajne algorytmy od samego początku, ale oszczędzaj mikrooptymalizację dla fazy dostrajania wydajności, kiedy rzeczywiste dane pokażą, gdzie są problemy na każdej platformie.
Caleb
@Caleb: Przykład Angry Birds ilustruje, dlaczego nie optymalizować pod kątem konkretnego sprzętu. Pokazuje również, jak możesz zbudować całą aplikację bez zawracania głowy ogólnymi optymalizacjami na poziomie „C”, a następnie poparzenia. Właściwie nie spalony, ale mający problemy z wyjściem poza twoje pierwotne zamiary.
phkahler,
25

Najpierw weźmy twoją sprawę: PHP

  • Nie sądzę, że PHP jest rodzajem języka (zarówno ze względu na jego naturę, jak i główną domenę aplikacji), że trzeba się martwić o te „mikrooptymalizacje”. Kod PHP jest głównie zoptymalizowany z buforowaniem opcode.
  • Programy napisane w PHP nie są powiązane z procesorem, są głównie związane z operacjami wejścia / wyjścia , więc te optymalizacje i tak nie będą warte twojego czasu.
  • Wszystko, co MUSISZ zoptymalizować, powinno prawdopodobnie zostać wciągnięte do rozszerzenia C, a następnie dynamicznie załadowane do środowiska wykonawczego PHP
  • Jak widać, nie otrzymujemy zachęty, jeśli mikrooptymalizujemy nasz kod w PHP - z drugiej strony, jeśli poświęcisz ten czas na uczynienie kodu PHP bardziej czytelnym i łatwym w utrzymaniu - to przyniesie ci więcej dywidend.

Ogólnie,

Nie spędzałbym „TOOOOO” dużo czasu na optymalizacji mojego kodu w dynamicznym języku, takim jak Python lub Ruby - ponieważ NIE są one przeznaczone do zadań wymagających dużej liczby procesorów. Rozwiązują różne rodzaje problemów, w których modelowanie rzeczywistej sytuacji w świecie w skomplikowany sposób (który jest łatwy do odczytania i utrzymania) - co nazywa się ekspresją - jest ważniejsze niż szybkość. Gdyby najważniejsza była prędkość, nie byłyby one przede wszystkim dynamiczne.

W przypadku skompilowanych programów (C ++, Java) optymalizacja jest ważniejsza. Ale i tam najpierw musisz spojrzeć na naturę / domenę / cel pisanego programu. Powinieneś także starannie wyważyć czas na mikrooptymalizację w stosunku do zysków z tej optymalizacji. Jeśli potrzebujesz jeszcze większej optymalizacji, równie dobrze możesz rozważyć krok w dół - i zakoduj te fragmenty swojego kodu w asemblerze.

Tak więc, aby odpowiedzieć na twoje pierwotne pytanie - „Czy mikrooptymalizacja jest ważna podczas kodowania?” - odpowiedź brzmi - ZALEŻY -

  • Co robisz: domena aplikacji, złożoność?
  • Czy ulepszenia szybkości w mikrosekundach NAPRAWDĘ są ważne dla Twojego programu?
  • Jaki rodzaj optymalizacji przyniesie największe zyski? Nie zawsze może to być optymalizacja kodu, ale coś zewnętrznego.
  • Ile „dobroci” (pod względem prędkości) czerpiesz z czasu, który inwestujesz w mikrooptymalizację?
  • Czy można osiągnąć lepsze prędkości na inne sposoby - zmieniając sprzęt, pamięć RAM i procesor, wykonując kod równolegle lub w systemie rozproszonym?

Mikrooptymalizacja (optymalizacja kodu pod tym względem) jest nie tylko czasochłonna, ale „zniekształca” naturalną czytelność kodu, przez co wymaga dużej konserwacji. Zawsze traktuj to jako ostateczność - zawsze staraj się zoptymalizować całą aplikację, przyjmując lepszy sprzęt i lepszą architekturę niż optymalizacja poszczególnych plików kodu.

good_computer
źródło
18

Wydaje się, że istnieje wiele odpowiedzi, które mówią, że mikrooptymalizacja jest

wszystko o kompromisach - wydajność, czas, koszt, wysiłek, czytelność / konserwacja i tak dalej.

Ale dobrze wiem, że istnieją pewne optymalizacje, które nie mają wpływu na czytelność, i po prostu lubię robić to dla zabawy. Widziałem niektóre z moich zadań szkolnych (wszystkie oparte na szybkości), że zawsze miło jest wziąć pod uwagę mikrooptymalizację podczas pisania instrukcji warunkowych, takich jak:

if (counter < X && shouldDoThis()) // shouldDoThis() is an expensive function

jest zawsze ładniejszy niż

if (shouldDoThis() && counter < X ) 

Istnieje wiele sposobów na „przyspieszenie” takiego kodu, a różnica jest zwykle nieznaczna (choć nie zawsze), ale czuję się lepiej, gdybym tak napisał.

Nie wiem, czy ktokolwiek w ogóle uważa to za optymalizację, ale myślę, że programista powinien wiedzieć i rozważyć te rzeczy podczas pisania swojego kodu.

zidarsk8
źródło
2
W tym konkretnym przypadku może nie być to ważne . Uważam jednak, że bardzo ważne jest, aby móc rozpoznać takie optymalizacje, aby w przypadku, gdy ma to znaczenie, nie trzeba było tracić czasu na profilowanie i optymalizację po fakcie.
tskuzzy
4
To bardzo niebezpieczny przykład. Optymalizacja powinna nigdy zmienić zachowanie . Nawet sugerowanie, że cheap() && expensive()jest to optymalizacja, expensive () && cheap()zachęca ludzi do ślepego zastępowania siebie nawzajem bez względu na znaczącą zmianę semantyczną, którą powoduje (w językach, w których &&występuje operator zwarcia).
Mark Booth,
5
Jeśli funkcje nie mają skutków ubocznych, są równoważne, a jedna jest szybsza. Jeśli mają one skutki uboczne, nie należy pisać takiego kodu w pierwszej kolejności. Powiedziałbym nawet, że należy to robić z przyzwyczajenia - chyba że faktycznie zmienia zachowanie.
phkahler
3
@MarkBooth Muszę się tutaj zgodzić z phkahlerem, żadna z tych funkcji nie powinna mieć skutków ubocznych! Kolejność warunków w instrukcji if nie może mieć wpływu na wynik programu. Mój przykład lepiej byłoby napisać jako if (x<100 && isPrime(x)), żeby było bardziej jasne.
zidarsk8
1
@ zidarsk8 - Jeśli optymalizacja zmienia coś innego niż szybkość wykonania , to nie jest to optymalizacja . Jako programiści często musimy być pragmatyczni , a czasem oznacza to, że nie możemy zagwarantować, że wszystkie funkcje używane z operatorem zwarciowym są czyste - szczególnie, gdy nasz kod wywołuje biblioteki stron trzecich, nad którymi nie mamy kontroli. W takiej sytuacji musisz uważać, aby niedoświadczeni programiści nie byli zachęcani do wprowadzania błędów w imię optymalizacji .
Mark Booth,
11

Na początku mojej kariery ogólne stwierdzenia takie jak „nie mikrooptymalizuj” doprowadziły do ​​wielu nieporozumień. Wszystko jest poszlakowe; dlatego ludzie mówią „najlepsza praktyka” zamiast „rób to”.

„Najlepsza praktyka” jest najlepszym wyborem, biorąc pod uwagę wszystkie okoliczności. Na przykład LINQ i Entity Framework powinny być używane zamiast wbudowanego SQL. W mojej firmie korzystamy z SQL Server 2000 . SQL Server 2000 nie obsługuje Entity Framework. Najlepsze praktyki wymagają:

  • Sprzedając mojemu szefowi pomysł zakupu nowej wersji SQL Servera, co oznacza kilka tysięcy dolarów.
  • Sprzedawanie programistom pomysłu uczenia się nowych technologii.

Wiem z doświadczenia, że ​​tak się nie stanie. Mogłem więc zrezygnować, stresować się bez końca lub nie stosować najlepszej praktyki.

Decyzje, które wpływają na ogólny wynik, mają względy polityczne, techniczne i monetarne. Pamiętaj o tym przy podejmowaniu decyzji i mądrze wybieraj bitwy.

Na wszystko jest pora, czas na każdą czynność pod niebem ”.

P.Brian.Mackey
źródło
1
BTW, możesz użyć Dappera jako mikro-ORM alternatywy dla wbudowanego SQL.
Dan
2
LINQ and Entity Framework should be used in lieu of inline SQL- Dopóki nie potrzebujesz wbudowanego SQL, aby coś zoptymalizować; SQL, który produkuje EF, nie zawsze jest optymalny.
Robert Harvey
1
FWIW, jeśli twój szef martwi się o koszty licencjonowania SQL 2k8 (lub czegokolwiek innego, co może być aktualna), należy podkreślić, że jest to na tyle stary, aby być zbliża się na EOL BARDZO wkrótce (jeśli nie już)
warren
@warren - Niektóre firmy nie uwzględniają takich rzeczy. W przypadku niektórych, jeśli nadal „działa”, nie zostaną zaktualizowane. W pracy mam na myśli, że serwer nadal działa. Widzimy już brak wsparcia z EF. To po prostu za mało, aby przekonać ich do wydania jakichkolwiek pieniędzy.
P.Brian.Mackey
1
Po prostu wiesz, że możesz używać EF z SQL 2000. Projektant nie działa, ale rzeczywista struktura encji obsługuje SQL 2000. Aby obejść ograniczenia projektanta, możesz utworzyć lokalną bazę danych w SQL Express 2008 z tym samym schematem jako bazę danych SQL 2000, wskaż projektantowi, aby wygenerował wszystkie klasy, a następnie przejdź do pliku .edmx i zmień docelową wersję bazy danych na 2000 i skieruj ciąg połączenia na bazę danych SQL Server 2000. Nie jest to najlepsze rozwiązanie, ale jeśli nie możesz go zaktualizować, działa.
Neil,
8

To zawsze jest kompromis.

Po pierwsze, w branży komputerowej chodzi przede wszystkim o pieniądze. Jako programista musisz wygenerować wartość dla klienta, aby uzyskać pieniądze (to nadmierne uproszczenie, ale najważniejsze jest tutaj).

Czas programisty kosztuje. Moc maszyny również kosztuje. Zwykle ten drugi koszt jest znacznie niższy niż pierwszy. Jest to więc kapitał, aby mieć czytelny i łatwy do utrzymania kod, dzięki czemu deweloper może spędzać większość czasu na dostarczaniu wartości.

Ważna może być w niektórych przypadkach mikrooptymalizacja. Ale zwykle zawierają mniej czytelny kod lub mniej rozszerzalny kod (nie jest tak w przypadku twojego połączonego przykładu, ale ogólnie tak jest). W pewnym momencie będzie to kosztować deweloper. Tym razem jest droższy niż moc maszyny, jest to strata.

Po drugie, mikrooptymalizacja w dużym projekcie może utrudniać utrzymanie / ewolucję. Problem polega na tym, że podczas ewolucji możliwa jest inna optymalizacja. Dzięki rozwijającej się aplikacji zazwyczaj znajdziesz rozwiązanie wolniejsze niż to, co miałbyś bez przeprowadzania tych optymalizacji.

Po trzecie, optymalizacja jest często nieistotna, ponieważ złożoność algorytmu zazwyczaj przezwycięża wszelkie mikrooptymalizacje, które można by wykonać, gdyby zbiór danych wzrastał. Niestety, ponieważ mikrooptymalizacja utrudnia utrzymanie / ewolucję kodu, optymalizacja może być trudniejsza.

Czasami wartość ma tę optymalizację (pomyśl o programach krytycznych dla opóźnienia, takich jak gry wideo lub autopilot samolotu). Ale trzeba to wykazać. Zazwyczaj twój program spędza większość czasu w ograniczonej części kodu. Niezależnie od tego, jaką zrobisz mikrooptymalizację, nigdy nie dostaniesz programów o wiele szybciej bez zidentyfikowania wąskiego gardła i pracy nad tą częścią.

Zadanie pytania w taki sam sposób, jak pokazano, pokazało, że problem nie został porównany z rzeczywistym programem. W takim przypadku mógłbyś zrobić lewę i zauważyć, czy było szybciej, czy nie. Więc pytałeś o to, zanim miałeś jakiś problem. Tu jest problem. Źle radziłeś sobie z problemem optymalizacji.

Ponieważ konserwacja i ewolucja są zwykle cenniejsze niż mikrooptymalizacja, upewnij się, że masz odpowiedni interfejs przed wykonaniem jakiejkolwiek. Następnie, jeśli części twojego programu są dla siebie wystarczająco abstrakcyjne, możesz je mikro-zoptymalizować bez uszczerbku dla całości. Wymaga to, aby Twój interfejs działał wystarczająco długo, aby można było mu zaufać.

deadalnix
źródło
„Zawsze występuje kompromis”. To prawda, że ​​zmniejszenie jednej zmiennej zwiększy drugą, jeśli program znajdzie się na krzywej kompromisu . Z mojego doświadczenia wynika, że ​​większość programów nie znajduje się w pobliżu krzywej kompromisu i ma dużo miejsca na redukcję obu zmiennych.
Mike Dunlavey,
Konserwacja +1 i ewolucja są cenniejsze niż mikrooptymalizacja. Chociaż jestem pewien, że w branży komputerowej chodzi nie tylko o pieniądze? Na przykład, oprogramowanie typu open source, edukacja, innowacje, zarządzanie, społeczność itp. Jestem pewien, że u podstaw znajdują się pieniądze, ale dotyczy to większości rzeczy.
Boz
@Boz kay> To częściowo prawda. Po pierwsze dlatego, że twój szef i klient zazwyczaj nic nie wiedzą o nich i dbają o pieniądze. Jeśli chcesz promować niektóre narzędzia open source, musisz im powiedzieć, w jaki sposób poprawi to markę firmy lub jak obniży koszty rozwoju. Ponadto zadowolenie programistów jest sposobem na uzyskanie dobrego dewelopera w Twojej firmie. Dobry deweloper zarabia pieniądze (głównie rzuca jakością i innowacjami). Na koniec pieniądze są kluczem. Piszę to z mojego komputera z systemem Linux, który jest świetnym zwolennikiem wolnego oprogramowania. To samo dotyczy edukacji.
deadalnix
8

Wydajność to funkcja

Artykuł Jeffa Atwooda jest świetny na temat budowania wysokowydajnej strony internetowej i tego, jak ważne jest to ...

To powiedziawszy, nie koncentruj się na mikrooptymalizacji, dopóki nie będziesz musiał. Można przeprowadzić bardziej opłacalną optymalizację. Skoncentruj się na architekturze, a nie na kodzie. Większość stron internetowych, które widziałem, które działały powoli, miały problemy na wysokim poziomie (niepotrzebna warstwa usług internetowych, zły projekt bazy danych, zbyt skomplikowane architektury), które nie tylko negatywnie wpłynęły na wydajność, ale były głęboko zakorzenione i trudne do naprawienia.

Podczas tworzenia witryny kod po stronie klienta i logika bazy danych znacznie częściej powodują problemy z wydajnością niż kod po stronie serwera. Jakkolwiek, jeśli masz problemy z wydajnością, będziesz wiedzieć, jeszcze lepiej profiluj swój kod i możesz je znaleźć wcześnie.

Mike Cellini
źródło
7

Czas programisty kosztuje więcej niż czas komputerowy. Zazwyczaj chcesz to zoptymalizować. Ale:

  • Istnieje różnica między mikrooptymalizacją a złożonością algorytmiczną. Poświęć wystarczająco dużo czasu, aby mieć pewność, że używasz właściwego algorytmu .
  • Upewnij się, że zadajesz właściwe pytanie, select (select count(*) from foo) >= 1to nie to samo, coselect exists(select 1 from foo) .
  • niektóre idiomy językowe są popularne po prostu dlatego, że są szybsze, można z nich korzystać, ponieważ większość biegłych użytkowników języka będzie je znać. (twój przykład jest dobrym przykładem).
SingleNegationElimination
źródło
7

Co chcesz zoptymalizować?

  • Wydajność oprogramowania?
  • Niezawodność?
  • Wydajność programisty?
  • Satysfakcja konsumenta?
  • Wydajność energetyczna?
  • Konserwowalność?
  • Czas na rynek?
  • Koszt?

„Optymalizacja” nie zawsze oznacza, że ​​kod działa tak szybko, jak to możliwe. Są chwile, kiedy znalezienie absolutnie najszybszego sposobu na zrobienie czegoś jest ważne, ale tak naprawdę nie jest to tak powszechne w większości kodów. Jeśli użytkownicy nie zauważą różnicy między 50 a 100 mikrosekund, nie ma żadnej różnicy między tymi dwoma kodami, które będą działały tylko sporadycznie. Oto przykład:

Jeśli musisz stale aktualizować wyświetlanie długości danych wejściowych użytkownika i czasu, który zajmuje jedna z dwóch procedur, aby ustalić, że długość jest znacznie mniejsza niż czas między dwoma kolejnymi naciśnięciami klawiszy, to naprawdę nie ma znaczenia, która procedura używasz. Z drugiej strony, jeśli chcesz określić długość miliarda łańcuchów, prawdopodobnie będziesz chciał zwrócić szczególną uwagę na różnice w wydajności między różnymi procedurami. W pierwszym przypadku wolisz pisać kod, który jest łatwy do zrozumienia i weryfikacji; w drugim przypadku możesz chcieć zamienić czytelność na szybkość.

W każdym razie, jeśli zamierzasz zoptymalizować swój kod, powinieneś profilować go przed i po wprowadzeniu jakichkolwiek zmian. Programy w dzisiejszych czasach są na tyle skomplikowane, że często trudno powiedzieć, gdzie są wąskie gardła; profilowanie pomaga zoptymalizować odpowiedni kod, a następnie pokazać, że dokonane optymalizacje naprawdę zadziałały.

Nie powiedziałeś, kiedy twój ojciec przeszedł na emeryturę ani jakiego rodzaju programowania dokonał, ale jego reakcja nie jest zaskakująca. Historycznie pamięć, pamięć dodatkowa i czas przetwarzania były drogie, a czasem bardzo drogie. Obecnie wszystkie te rzeczy stały się bardzo tanie w porównaniu do czasu programisty. Jednocześnie procesory i kompilatory są w stanie zoptymalizować kod w sposób, którego programiści nigdy nie byliby w stanie dopasować. Dni, w których programiści używają małych sztuczek, aby wydać kilka instrukcji maszynowych tutaj i tam w większości już minęły.

Caleb
źródło
1
+1 Nie wspominając o tym, że w ciągu ostatnich kilku lat urządzenia mobilne ponownie stały się wysoce zależne od optymalizacji kodu. Ktoś, kto nie pisze zoptymalizowanego kodu lub przynajmniej uważa, że ​​może mieć trudności z płynnym uruchomieniem aplikacji intensywnie wykorzystującej procesor na urządzeniu mobilnym.
Styler
Daj +1 bardzo do listy możliwych optymalizacji. Wykorzystał montaż / fortran
Boz
@Styler: nie potrwa długo, zanim urządzenia mobilne będą miały czterordzeniowy procesor z GB pamięci, mamy już smartfony dwurdzeniowe.
Lie Ryan,
@Lie Ryan: tak, to prawda, ale jak większość pionierów musieli podróżować drewnianymi łodziami;)
Styler
7

Mikrooptymalizacja podczas pisania kodu nie jest ważna. Optymalizacja powinna odbywać się za pomocą profilera, optymalizującego kod tam, gdzie ma to znaczenie.

JEDNAK programista powinien starać się unikać robienia oczywiście głupich rzeczy podczas pisania kodu.

Na przykład nie wykonuj powtarzających się kosztownych operacji w pętli. Zapisz wartość w zmiennej poza pętlą i użyj jej. Nie rób takich rzeczy jak porównania ciągów lub wyrażenia regularne w często wywoływanej funkcji, gdy możesz przejść poziom wyżej, zrobić porównanie i przekształcić je w liczbę całkowitą, odwołanie do funkcji lub klasę pochodną.

Te rzeczy są łatwe do zapamiętania dla doświadczonego programisty i prawie zawsze poprawiają jakość kodu.

Zan Lynx
źródło
Uświadomiłem sobie, że muszę być jaśniejszy w mojej edycji pytania, naprawdę mówiłem to samo - zaktualizowałem to.
Boz
7

Decydując, co zoptymalizować, zawsze pamiętaj o prawie Amdahla . Zobacz link do dokładnej matematyki; ważne jest, aby pamiętać:

Jeśli jedna część twojego programu stanowi 10% czasu jej działania, a Ty zoptymalizujesz tę część, aby działała dwa razy szybciej, program jako całość przyspieszy tylko o 5%.

Dlatego ludzie zawsze mówią, że nie warto optymalizować części programu, które nie zajmują więcej niż kilka procent całkowitego czasu działania. Ale to tylko szczególny przypadek bardziej ogólnej zasady. Prawo Amdahla mówi ci, że jeśli chcesz, aby cały program działał dwa razy szybciej, musisz przyspieszyć każdy kawałek średnio o 50%. Mówi ci, że jeśli potrzebujesz przetworzyć dwadzieścia gigabajtów danych, istnieją tylko dwa sposoby, aby przyspieszyć to niż czas potrzebny do odczytania dwudziestu gigabajtów z dysku: zdobądź szybszy dysk lub zmniejsz dane.

Co więc mówi prawo Amdahla o mikrooptymalizacjach? Mówi, że być może warto, jeśli aplikują na całym forum. Jeśli możesz zmniejszyć o jeden procent czas działania każdej funkcji w programie, gratulacje! Przyspiesziłeś program o jeden procent. Czy było warto? Jako kompilator z przyjemnością znajdę optymalizację, która to zrobiłaby, ale jeśli robisz to ręcznie, powiedziałbym, że szukaj czegoś większego.

Zack
źródło
1
+1 za cytat Amdahla, ale nie zgadzam się z „aby cały program działał dwa razy szybciej, musisz przyspieszyć każdy kawałek”. Powiedziałbym, że tak naprawdę nie przyspieszasz żadnego „kawałka”. Zamiast tego znajdujesz niepotrzebną pracę i ją eliminujesz. Zwłaszcza wywołania funkcji, jeśli program jest większy niż zabawka. Większość powszechnego myślenia o wydajności wydaje się całkowicie ignorować znaczenie znajdowania całych niepotrzebnych gałęzi drzewa wywołań (które mogą być pojedynczymi instrukcjami) i ich usuwania.
Mike Dunlavey,
Diabeł ma tam słowo „średnia”. Matematycznie rzecz biorąc, aby przyspieszyć program o 50%, każdy kawałek musi zostać przyspieszony średnio o 50% . Teraz, jeśli możesz podzielić program na zadanie, które zajmuje 75% czasu wykonywania, a drugie na 25%, i przyspieszyć pierwsze z nich trzykrotnie, daje to 50% ogólnie, mimo że nie wykonałeś nic na drugim. Ale o wiele bardziej powszechnym przypadkiem jest to, że istnieją dziesiątki „zadań”, z których każde zajmuje mniej niż 5% czasu wykonywania - a następnie trzeba przyspieszyć lub pozbyć się wielu z nich.
zwolnić
Myślę, że jest jeszcze bardziej powszechny przypadek. „Praca” zajmuje 50% czasu, ale tak naprawdę jej nie potrzebujesz , więc całkowicie ją usuwasz, skracając całkowity czas o tę kwotę, a następnie powtarzasz. Wiem, że trudno to zaakceptować - że programy mogą spędzać dużo ułamków czasu na robieniu rzeczy, które (z perspektywy czasu) są całkowicie niepotrzebne. Ale oto mój kanoniczny przykład .
Mike Dunlavey,
6

To zależy od tego, na jakim etapie rozwoju jesteś, kiedy na początku zaczynasz coś pisać, mikrooptymalizacje nie powinny być brane pod uwagę, ponieważ zamierzasz uzyskać większy wzrost wydajności dzięki zastosowaniu dobrych algorytmów niż przy użyciu mikrooptymalizacji. Zastanów się także nad tym, co opracowujesz, ponieważ aplikacje wrażliwe na czas przyniosą więcej korzyści z uwagi na mikrooptymalizację niż ogólne aplikacje biznesowe.

Jeśli testujesz i rozszerzasz oprogramowanie, mikrooptymalizacje najprawdopodobniej zaszkodzą, ponieważ utrudniają czytanie kodu, a nawet wprowadzają własny unikalny zestaw błędów, które należy naprawić wraz ze wszystkim, co należy naprawić.

Jeśli faktycznie otrzymujesz skargi od użytkowników na powolny kod, być może warto je rozważyć, ale tylko wtedy, gdy wszystko inne zostało rozwiązane, a mianowicie:

  • Czy kod jest dobrze napisany?
  • Czy aplikacja może uzyskać dostęp do swoich danych bez żadnych problemów?
  • Czy można zastosować lepszy algorytm?

Jeśli na wszystkie pytania udzielono odpowiedzi i nadal występują problemy z wydajnością, być może nadszedł czas, aby zacząć korzystać z mikrooptymalizacji w kodzie, ale są szanse, że inne zmiany (tj. Lepszy kod, lepszy algorytm itp.) Przyniosą korzyści większy przyrost wydajności niż mikrooptymalizacja.

Rob Z
źródło
5

Szybkość wykonania jest jednym z wielu czynników wpływających na jakość programu. Często prędkość ma odwrotną korelację z czytelnością / utrzymywalnością. W prawie wszystkich przypadkach kod musi być czytelny dla człowieka, aby można go było zachować. Jedyny czas, w którym czytelność może być zagrożona, jest wtedy, gdy szybkość jest niezbędnym wymogiem. Wymóg, aby kod był szybszy niż pozwala na to pełna czytelność / łatwość konserwacji, prawie nigdy nie ma zastosowania, ale są pewne przypadki, w których tak się stanie. Najważniejszą rzeczą do zapamiętania jest to, że kod mikrooptymalizowany jest często kodem hackującym, więc jeśli gdzieś nie ma określonego wymagania, prawie zawsze jest to zły sposób rozwiązania problemu. Na przykład użytkownik prawie nigdy nie zauważy różnicy między czasami wykonania 0,55 i 1 sekundy w operacjach CRUD, więc nie musisz iść na hackfest w asemblerze, aby dostać się do tego. 5 sekund. Tak, mógłbym latać helikopterem do pracy i byłoby to 10 razy szybsze, ale nie robię tego ze względu na cenę i fakt, że śmigłowiec jest znacznie trudniejszy do latania.Kiedy niepotrzebnie optymalizujesz kod, robisz dokładnie to, co robisz: dodajesz niepotrzebną złożoność i koszty, aby osiągnąć zbędny cel.

Morgan Herlocker
źródło
5

Mikrooptymalizacja jest ważna, gdy trafisz na ograniczenie. Ważna może być pamięć, przepustowość, opóźnienie lub zużycie energii. Zauważ, że są to cechy na poziomie systemu; nie musisz (i nie możesz) zoptymalizować każdej funkcji pod każdym względem.

Systemy osadzone częściej wymagają mikrooptymalizacji, ponieważ łatwiej jest trafić w ograniczenia. Jednak nawet tam mikrooptymalizacja prowadzi do tej pory; nie można mikrooptymalizować wyjścia ze złego projektu. Istotą dobrego projektu w systemie jest to, że możesz rozumować cały system. Komponenty wymagające mikrooptymalizacji powinny być starannie wyeksponowane i zoptymalizowane w sposób, który nie wpłynie negatywnie na konstrukcję systemu.

Zwróć uwagę, że małe „wbudowane” systemy mogą być dzisiaj bardzo zbliżone do Vaxen lub PDP-11 z przeszłości, więc te problemy występowały częściej. W nowoczesnym systemie ogólnego przeznaczenia wykonującym nowoczesne ogólne obliczenia komercyjne mikrooptymalizacja jest rzadkością. Jest to prawdopodobnie część tego, dlaczego twój ojciec zajmuje stanowisko, które zajmuje.

Jednak nie ma znaczenia, czy masz do czynienia z nanosekundami, milisekundami, sekundami czy godzinami; problemy są takie same. Muszą być ocenione w kontekście systemu i tego, co próbujesz osiągnąć.

Jest to przykład z ostatniego pytania, na które odpowiedziałem na temat przepełnienia stosu w przypadku, gdy konieczna była mikrooptymalizacja: kodery wideo typu open source dla systemu osadzonego .

janm
źródło
4

Największym problemem związanym z mikrooptymalizacją jest trudność w utrzymywaniu kodu.

Inna kwestia polega na tym, że w zależności od konfiguracji komputera mikrooptymalizacja może mieć gorszą wydajność niż bez „optymalizacji”.

Dokonanie wielu mikrooptymalizacji pochłonie mnóstwo czasu na walkę z czymś, co tak naprawdę nie ma znaczenia.

Lepszym rozwiązaniem jest uczynienie kodu czystszym, łatwiejszym w utrzymaniu, a jeśli wystąpią problemy z wydajnością, uruchom profil, aby dowiedzieć się, co tak naprawdę spowalnia kod. I wiedząc dokładnie, co jest naprawdę złe, możesz to naprawić.

Nie twierdzę, że brak robienia mikrooptymalizacji jest usprawiedliwieniem do pisania głupiego kodu.

Daniel Moura
źródło
4

Jeśli zaczniesz się martwić o milisekundy, powinieneś rozważyć rezygnację z PHP i zamiast tego użyć C lub asemblera. Nie to, że chciałbym to zrobić, po prostu nie ma sensu omawiać takich liczb i używać języka skryptowego. Czy twój kod i tak często wykonuje iterację z tym poleceniem?

Czynniki środowiskowe są tutaj wykluczone, te serwery i tak działają 24 godziny na dobę, 7 dni w tygodniu, a jeśli faktycznie coś przetwarzają, będzie to miało znaczenie tylko wtedy, gdy to naprawdę zadanie będzie działać bardzo długo.

Najprawdopodobniej światło w twoim biurze i energia, z której korzystały nasze komputery, podczas gdy wszyscy pisaliśmy pytania i odpowiedzi, zużyły znacznie więcej energii niż jakikolwiek rodzaj mikrooptymalizacji, który możesz rozsądnie zastosować w swoich aplikacjach, który kiedykolwiek zaoszczędzi.

Thorsten Müller
źródło
+1 wyłączenie światła lub brak odpowiedzi na pytania.
Boz
4

Powinieneś wybrać najlepszy, prosty algorytm dla zadania. Powodem, dla którego musi być prosty, jest utrzymanie czytelności kodu. Powodem, dla którego musi być najlepszy, jest unikanie rozpoczynania od złych właściwości środowiska wykonawczego. Nie ślepo wybieraj BubbleSort, gdy wiesz, że będziesz mieć duże zbiory danych. Jest to jednak w porządku dla okazjonalnego rodzaju 10 elementów.

NASTĘPNIE, jeśli liczby profilowania wskazują, że wybór najlepszego, prostego algorytmu nie był wystarczająco dobry, możesz rozpocząć optymalizację (co zwykle stanowi koszt czytelności).

1249
źródło
BubbleSort może być lepszy niż szybkie sortowanie lub scalanie, gdy Twoje dane są prawie posortowane z kilkoma zabłąkanymi elementami, które nie są zbyt daleko od ich ostatecznego miejsca docelowego. Do wszystkich innych zadań należy jednak korzystać z wbudowanej funkcji sortowania, którą zapewnia język programowania; to najprostszy sposób na rozpoczęcie pracy (a wbudowana funkcja sortowania w większości języków ma dobrą wydajność). ZŁA RADA: start out with bad runtime characteristicnie zaczynaj celowo od złej charakterystyki środowiska uruchomieniowego.
Lie Ryan,
@ Lie, jeśli WIESZ, że Twoje dane są już prawie posortowane i WTEDY możesz korzystać z bąbelkowego sortowania, nie wybierasz dokładnie swojego algorytmu na ślepo ... Dziękujemy również za wskazanie literówki.
4

Powiedziałem to już wcześniej i powiem tutaj: „Przedwczesna optymalizacja jest źródłem wszelkiego zła” . To powinna być jedna z zasad w centrum każdego programisty.

Kod może do pewnego stopnia zawsze być szybszy niż obecnie. O ile nie zajmujesz się ręcznym pakowaniem z myślą o konkretnym układzie, zawsze możesz coś zyskać dzięki optymalizacji. Jednakże, chyba że CHCESZ być ręcznym zestawem do wszystkiego, co robisz, musi istnieć cel ilościowy, który po osiągnięciu celu powiesz „to wystarczy” i przestaniesz optymalizować, nawet jeśli wciąż patrzysz rażąco na frajera ty w twarz.

Piękny, elegancki, niezwykle wydajny kod jest bezużyteczny, jeśli nie działa (a przez „work” rozumiem, że generuje oczekiwane dane wyjściowe przy wszystkich oczekiwanych danych wejściowych). Dlatego tworzenie działającego kodu powinno ZAWSZE być priorytetem. Po tym, jak działa, oceniasz wydajność, a jeśli jej brakuje, szukasz sposobów na poprawę, aż do momentu, w którym będzie wystarczająco dobra.

Są pewne rzeczy, które musisz zdecydować z góry, które wpłyną na wydajność; bardzo podstawowe decyzje, takie jak język / środowisko wykonawcze, którego użyjesz do wdrożenia tego rozwiązania. Wiele z nich wpłynie na wydajność o wiele rzędów wielkości w większym stopniu niż połączenie jednej metody z drugą. Szczerze mówiąc, PHP jako język skryptowy jest już hitem wydajności, ale ponieważ bardzo niewiele stron skryptowych jest budowanych od podstaw w C / C ++, jest porównywalne z innymi technologiami, które prawdopodobnie wybierzesz (Java Servlets, ASP.NET itp.).

Następnie rozmiar komunikatu we / wy jest kolejnym co do wielkości zabójcą wydajności. Optymalizacja tego, co czytasz i zapisujesz na dysku twardym, portach szeregowych, potokach sieciowych itp. Zwykle poprawi czas działania programu o wiele rzędów wielkości, nawet jeśli algorytmy operacji we / wy były wydajne. Następnie zmniejsz złożoność samego algorytmu Big-O, a jeśli to absolutnie konieczne, możesz „mikrooptymalizować”, wybierając tańsze wywołania metod i podejmując inne ezoteryczne decyzje na niskich poziomach.

KeithS
źródło
2
+1 Tworzenie kodu, który działa powinien ZAWSZE być priorytetem.
Boz
2
@ Keith, właściwie Knuth powiedział to pierwszy, a on powiedział coś więcej.
„Spraw, by działało, a następnie spraw, aby działało tak szybko, jak musi działać”, Anon.
John Saunders,
1
W rzeczywistości religia jest źródłem wszelkiego zła, ale dygresuję.
Thomas Eding,
4

Wspominasz, że twój tata jest emerytowanym programistą. Programiści pracujący w świecie komputerów mainframe musieli bardzo martwić się wydajnością. Pamiętam, jak studiowałem działalność marynarki wojennej USA, w której ich komputer mainframe był ograniczony sprzętowo do 64 KB pamięci na użytkownika. W tym świecie programowania musisz wydobywać każdy możliwy kawałek.

Teraz sprawy wyglądają zupełnie inaczej i większość programistów nie musi się tak bardzo przejmować mikrooptymalizacjami. Jednak programiści systemów wbudowanych nadal tak robią, a osoby korzystające z baz danych nadal bardzo potrzebują kodu zoptymalizowanego.

HLGEM
źródło
3

Kod powinien być napisany, aby był absolutnie jasny o tym, co robi. Następnie, jeśli i tylko jeśli jest zbyt wolny, wróć i przyspiesz go. Kod można zawsze zmienić, aby był szybszy później, jeśli można go zrozumieć - ale powodzenia, aby był wyraźny, jeśli jest szybki.

DeadMG
źródło
3

Ważne jest, jeśli:

1) Życie kogoś zależy od twojego kodu. Funkcja zajmująca 25ms w czyimś monitorze pracy serca jest prawdopodobnie złym pomysłem.

Osobiście podchodzę do dwóch zasad - istnieją mikrooptymalizacje, które możesz zrobić, co nie wpłynie na czytelność - oczywiście chcesz z nich skorzystać. Ale jeśli wpływa to na czytelność, odsuń się - nie dostaniesz dużych korzyści i może potrwać dłużej w debugowaniu na dłuższą metę.

ansiart
źródło
2
Tylko kilka drobnych punktów na twoim przykładzie: funkcja czujnika tętna, która zajmuje 25 ms, nie byłaby problemem, o ile inne niezbędne zadania mogłyby się zdarzyć z wymaganym czasem reakcji. Przerwania są do tego dobre. Opóźnienie 25 ms dla czegoś, co po prostu monitoruje rzeczywiste zdarzenia w celu zaktualizowania wyświetlacza do spożycia przez ludzi, prawdopodobnie nie stanowi problemu.
Janm
3

Czy mikro-optymalizacja jest ważna podczas kodowania?

Nie, biorąc pod uwagę, że istnieją platformy takie jak JVM i .NET, w których kod jest napisany dla maszyny wirtualnej, dlatego próba zoptymalizowania wykonania może nie działać tak dobrze, a to, co jest optymalne na pulpicie programisty, niekoniecznie jest takie samo na serwerze. Zobacz, jak daleko od sprzętu niektóre z tych programów wysokiego poziomu znajdują się w innym miejscu. Biorąc pod uwagę różnorodność sprzętu, należy zastanowić się nad tym, jak realistyczna jest optymalizacja kodu dla konkretnych układów, takich jak procesor lub GPU, kiedy nowy model prawdopodobnie pojawi się za mniej niż rok?

Kolejnym pytaniem do rozważenia jest wydajność mierzona za pomocą tego, co mierzy: szybkość wykonania, pamięć użyta do wykonania, szybkość rozwoju nowych funkcji, rozmiar bazy kodu na serwerze w skompilowanych lub zdekompilowanych formularzach, skalowalność, łatwość konserwacji itp. .? Zasadniczo pytanie staje się trywialne, ale nie jestem pewien, jak szeroko chciałeś wziąć wydajność, tak naprawdę może to być prawie wszystko, o ile można ją w jakiś sposób zmierzyć.


Niektóre mikrooptymalizacje mogą działać, a inne mogą nie działać, dlatego można się zastanawiać, jak opłacalne jest wykonywanie takiej pracy w porównaniu z innymi pracami, które mogą być postrzegane jako o wyższym priorytecie, takie jak nowe funkcje lub naprawianie błędów. Drugim pytaniem byłoby, czy aktualizacja sprzętu lub oprogramowania może również złamać niektóre z tych optymalizacji.

JB King
źródło
1
Należy pamiętać, że można absolutnie przeprowadzić mikrooptymalizacje na platformach takich jak JVM i .NET, przyjmują one tylko nieco inne formy. Ale to samo dotyczy porównania starego i prostego kompilatora C z bardziej nowoczesnym, wysoce optymalizującym kompilatorem: optymalizacje, które użytkownik może wykonać, będą wyglądać inaczej.
Joachim Sauer
1

Myślę, że istnieje duża różnica między dobrym programowaniem a mikrooptymalizacją.

Jeśli są dwa sposoby wykonania tego samego zadania, jedno jest szybsze od drugiego i oba mają tę samą czytelność, powinieneś użyć szybszego. Zawsze. I to jest dobre programowanie. Nie ma powodu, aby nie używać lepszego algorytmu do rozwiązania problemu. A nawet udokumentowanie tego jest łatwe: podaj nazwę algorytmu, każdy będzie mógł google go znaleźć i znaleźć więcej informacji na temat jego działania.

Dobre algorytmy są już zoptymalizowane. Będą szybkie. Będą małe. Wykorzystają minimalną wymaganą pamięć.

Nawet jeśli korzystasz z nich, twój program wciąż nie ma takiej wydajności, możesz rozważyć mikrooptymalizację. Musisz naprawdę znać język, aby móc mikrooptymalizować.

I zawsze jest miejsce na wydawanie większej ilości pieniędzy na sprzęt. Sprzęt jest tani, programiści są kosztowni . Nie marnuj zbyt wiele czasu / pieniędzy, optymalizując, kiedy możesz po prostu kupić sprzęt.

woliveirajr
źródło
1

Czytelność kodu IMHO jest ważniejsza niż mikrooptymalizacja, ponieważ w większości przypadków mikrooptymalizacja nie jest tego warta.

Artykuł o nieoptymalnych mikrooptymalizacjach :

Jak większość z nas, mam dość czytania postów na blogu o niesensownych mikrooptymalizacjach, takich jak zamiana print na echo, ++ $ i na $ i ++ lub podwójne cudzysłowy na pojedyncze cudzysłowy. Dlaczego? Ponieważ 99,999999% czasu jest bez znaczenia. Dlaczego? Ponieważ 99,99% czasu, lepiej zainstaluj akcelerator PHP, taki jak APC, lub dodaj te brakujące indeksy do kolumn bazy danych, lub spróbuj uniknąć 1000 żądań bazy danych, które masz na stronie głównej.

print używa jeszcze jednego kodu operacyjnego, ponieważ faktycznie coś zwraca. Możemy stwierdzić, że echo jest szybsze niż drukowanie. Ale jeden kod operacyjny nic nie kosztuje, naprawdę nic.

Próbowałem na nowej instalacji WordPress. Skrypt zatrzymuje się, zanim zakończy się z błędem „Bus Error” na moim laptopie, ale liczba kodów operacyjnych wynosiła już ponad 2,3 miliona. Wystarczająco powiedziane.

W większości przypadków mikrooptymalizacja oszczędza 1 operację spośród milionów, ale pogarsza czytelność.

webvitaly
źródło
1

Inne odpowiedzi dotyczą pieniędzy. Ale dodam kolejny punkt, w którym należy rozróżnić, co jest przedwczesna optymalizacja / mikrooptymalizacja i napisać kod wykonawczy, który odzwierciedla zrozumienie zachowania konstrukcji języka / frameworka (przepraszam, nie mogłem znaleźć jednego słowa na ostatnie) . Ten ostatni jest dobrą praktyką kodowania i na ogół należy to zrobić!

Wyjaśnię. Zła optymalizacja (odczyt przedwczesna / mikrooptymalizacja) nie występuje, gdy optymalizujesz sekcje kodu bez profilowania, aby wiedzieć, czy tak naprawdę są wąskie gardła. To wtedy, gdy optymalizujesz na podstawie swoich założeń, przesłuchań i zachowań nieudokumentowanych. Jeśli jest to udokumentowane i robi coś w bardziej wydajny / logiczny sposób, jakkolwiek jest mały, nazywam to dobrą optymalizacją . Jak powiedzieli inni, oba z nich mają wady i prawie nie mają żadnych zalet, jeśli chodzi o zarabianie dobrego interesu, ale nadal robię to drugie, a nie pierwsze, jeśli nie całkowicie pogarsza czytelność. Tak, czytelność / konserwacja ma ogromne znaczenie i zależy od tego, gdzie wyznaczasz linię.

Powtórzę argumenty przedstawione przez innych tutaj jako bezcelowość zarówno dobrych, jak i złych optymalizacji:

  1. Twoje zależności od konkretnego problemu mogą się zmienić, a czas poświęcony na optymalizację przed ukończeniem logicznej sekcji aplikacji jest stratą czasu. Mam na myśli optymalizację na stosunkowo wczesnym etapie. Dzisiaj masz List<T>i zanim Twoja aplikacja zostanie dostarczona, musisz ją zmienić, LinkedList<T>a teraz wszystkie testy porównawcze były stratą czasu i wysiłku.

  2. Przeważnie prawdziwe wąskie gardło twojej aplikacji (odczytane jako mierzalna różnica) może wynosić 5% twojego kodu (głównie SQL), a optymalizacja pozostałych 95% nie daje twoim klientom żadnych korzyści.

  3. Zwykle „technicznie” lepiej działający kod oznacza większą szczegółowość, co z kolei oznacza więcej kodu podatnego na błędy, co z kolei oznacza trudniejszą konserwację i więcej czasu, co z kolei oznacza, że ​​zarabiasz mniej pieniędzy.

  4. Ślad węglowy, który oszczędzasz na całym świecie dzięki zwiększeniu wydajności o 1%, łatwo zmniejsza się w wyniku gazów cieplarnianych, które Twój zespół będzie musiał emitować podczas debugowania i utrzymywania tego kodu.

Negatywami złej optymalizacji są w szczególności:

  1. Często nie zapewnia oczekiwanej wydajności. Zobacz to pytanie na stronie SO, gdzie nie udały się optymalizacje . W rzeczywistości może mieć negatywne skutki. To jest problem z nieudokumentowanym zachowaniem.

  2. Zresztą i tak zrobią to w większości nowoczesne kompilatory.

Podam kilka przykładów złej i dobrej optymalizacji:

Źli -

  1. użycie mniejszych typów całkowitych zamiast Int32.

  2. ++i używane zamiast i++

  3. forzamiast foreach(najgorsze, jakie widziałem, całkowicie pokonuje logikę)

  4. unikanie zamkniętych zmiennych

    string p;
    foreach (var item in collection)
        p = ...;
    
  5. używanie charzamiast łańcucha podczas konkatenacji łańcucha, takie jak:

    string me = 'i' + "me myself"; // something along that line - causes boxing
    

Dobra (ze świata .NET. Powinna być zrozumiała) -

  1. Podwójne wyszukiwanie

    if (Dictionary<K, V>.TryGetValue(K, out V))
        do something with V
    

    zamiast

    if (Dictionary<K, V>.ContainsKey(K))
        do something with Dictionary<K, V>[K]
    
  2. Załaduj je wszystkie

    DirectoryInfo.EnumerateFiles();
    

    zamiast

    DirectoryInfo.GetFiles();
    
  3. Dwustopniowy casting:

    s = o as string;
    if (s != null)
        proceed
    

    zamiast

    if (o is string)
        s = (string)o;
    
  4. Jeśli zamówienie nie ma znaczenia

    if (counter < X || expensiveFunction())
    

    zamiast

    if (expensiveFunction() || counter < X)
    
  5. Boks

    void M<T>(T o) //avoids boxing
    {
    
    }
    

    zamiast

    void M(object o)
    {
    
    }
    

Jeśli zapytasz mnie, czy dają one zauważalne korzyści w zakresie wydajności, powiedziałbym, że nie. Sugerowałbym jednak, aby ich użyć, ponieważ wynika to ze zrozumienia zachowania tych konstruktów. Po co nawiązywać dwa połączenia, skoro można wykonać tylko 1? Z filozoficznego punktu widzenia jest to dobra praktyka kodowania. I 1 i 3 są również nieco mniej czytelne w ścisłych kategoriach, ale czy mają one przewagę nad czytelnością? Nie, niewiele, więc używam. Teraz to jest klucz - utrzymanie przyzwoitego stosunku wydajności do czytelności. A kiedy to, to chodzi o to, gdzie narysujesz linię.

nawfal
źródło
1

„Warto” potrzebuje kontekstu, na przykład o ile łatwiej jest pisać, czytać i utrzymywać w porównaniu do tego, o ile szybciej sprawia, że użytkownik jest znacznie bardziej responsywny, interaktywny i wymaga mniej czasu na czekanie.

Zaoszczędzenie kilku groszy na zakup puszki z napojem nie przyniesie mi wiele dobrego, jeśli będę musiał pokonać odległość, aby zaoszczędzić te grosz, szczególnie biorąc pod uwagę, że w dzisiejszych czasach rzadko piję napoje gazowane. Oszczędność kilku groszy na puszkę przy zakupie miliona puszek napojów gazowanych może być ogromną sprawą.

Tymczasem oszczędzając kilka groszy, gdy dwie osoby są tuż obok mnie, a jedna oferuje dokładnie to samo za kilka groszy taniej, a druga nie, a ja wybieram droższą, ponieważ podoba mi się ich kapelusz, wydaje się głupotą pesymizacji.

To, co często uważam za ludzi nazywających „mikrooptymalizacje”, wydaje się być dziwnie pozbawione pomiarów, kontekstu i dyskusji użytkowników, kiedy absolutnie wszystkie trzy powinny rozważyć takie optymalizacje, jeśli nie są trywialne w zastosowaniu. Dla mnie właściwa mikrooptymalizacja dotyczy obecnie takich układów, jak układy pamięci i wzorce dostępu, i chociaż mogą wydawać się „mikro” w centrum uwagi, nie działają one tak naprawdę.

Nie tak dawno temu udało mi się zredukować operację z 24 sekund do 25 milisekund (około 960 razy szybciej), z identycznymi wyjściami (zabezpieczonymi automatycznymi testami), bez zmiany złożoności algorytmicznej, dla skórowania z dyfuzją objętościową poprzez „mikrooptymalizacje” (największa z nich polegała na zmianie układu pamięci, która zmniejszyła się do około 2 sekund, następnie pozostałe rzeczy to SIMD i dalsza analiza braków pamięci podręcznej w VTune oraz pewne dalsze zmiany układu pamięci).

Wolfire wyjaśnia tutaj technikę i zmagał się z wymaganym czasem: http://blog.wolfire.com/2009/11/volumetric-heat-diffusion-skinning/

Moja implementacja zdołała to zrobić w milisekundach, gdy starał się sprowadzić ją do mniej niż minuty: wprowadź opis zdjęcia tutaj

Po „mikrooptymalizowaniu” go z 24 sekund do 25 ms było to przełomem w przepływie pracy. Teraz artyści mogą zmieniać swoje zestawy w czasie rzeczywistym przy ponad 30 klatkach na sekundę, bez czekania 24 sekund za każdym razem, gdy dokonają jakichkolwiek drobnych zmian w swoim urządzeniu. I to faktycznie zmieniło cały projekt mojego oprogramowania, ponieważ nie potrzebowałem już paska postępu i tego rodzaju rzeczy, wszystko stało się interaktywne. Może to być „mikrooptymalizacja” w tym sensie, że wszystkie ulepszenia pojawiły się bez żadnej poprawy złożoności algorytmu, ale w efekcie była to raczej „mega optymalizacja”, która sprawiła, że ​​wcześniej był to bolesny, nieinteraktywny proces w interaktywny w czasie rzeczywistym, który całkowicie zmienił sposób działania użytkowników.

Pomiar, wymagania użytkownika końcowego, kontekst

Naprawdę podobał mi się komentarz Roberta i być może nie udało mi się wskazać tego, co chciałem:

No dalej. Nikt nie będzie argumentował, że taka zmiana nie jest „warta”. Udało ci się wykazać namacalną korzyść; wiele tak zwanych mikrooptymalizacji nie może.

Jest to, pomimo pracy w bardzo krytycznym dla wydajności polu z często wymaganiami czasu rzeczywistego, jedyny raz, kiedy rozważam jakąkolwiek mikrooptymalizację, która wymaga zejścia mi z drogi.

Chciałbym podkreślić nie tylko pomiary, ale także stronę użytkownika. Jestem dziwakiem, ponieważ przyszedłem do mojej bieżącej dziedziny (i wcześniej gamedev) jako użytkownik / fan jako pierwszy, a programista jako drugi. Więc nigdy nie byłem tak podekscytowany zwykłymi rzeczami, które ekscytują programistów, takimi jak rozwiązywanie zagadek technicznych; Uznałem, że to dla nich ciężar, ale przetrwałbym je poprzez sen użytkowników końcowych, który podzieliłem się z innymi użytkownikami. Ale pomogło mi to upewnić się, że jeśli coś zoptymalizuję, miałoby to realny wpływ na użytkowników z rzeczywistymi korzyściami. To moje zabezpieczenie przed mikrooptymalizacją bezcelowo.

Moim zdaniem jest to tak samo ważne, jak profiler, ponieważ miałem kolegów, którzy robili takie rzeczy, jak mikrooptymalizacja podziału kostki na miliard aspektów tylko po to, aby udusić rzeczywiste modele produkcyjne, takie jak postacie i pojazdy. Ich wynik był imponujący w pewnym sensie „tech demo”, ale prawie bezużyteczny dla rzeczywistych użytkowników, ponieważ profilowali, mierzyli i analizowali przypadki, które nie były zgodne z rzeczywistymi przypadkami użycia. Dlatego tak ważne jest, aby najpierw zrozumieć, co jest ważne dla użytkowników, ucząc się myśleć i korzystać z takiego oprogramowania lub współpracując z nimi (najlepiej oba, ale przynajmniej współpracuj z nimi).

Dragon Energy
źródło
2
No dalej. Nikt nie będzie argumentował, że taka zmiana nie jest „warta”. Udało ci się wykazać namacalną korzyść; wiele tak zwanych mikrooptymalizacji nie może.
Robert Harvey
1
@RobertHarvey To był rodzaj punktu miałem nadzieję zrobić, ponieważ to, co niektórzy nazywają „mikro-optymalizacja” niekoniecznie jest mikroskopijny w rzeczywistości, ale to jest tak zależny od kontekstu, pomiary itd issetporównaniu strlenwydaje się malutkie w centrum uwagi brak kontekstu i pomiarów. :-D
Dragon Energy
1
@RobertHarvey Miałem nadzieję powiedzieć, choć pośrednio, że jeśli istnieje negatywny kontekst dla „mikrooptymalizacji”, to jest to typ, który jest pozbawiony tych pomiarów, kontekstów i potrzeb użytkownika. Mógłbym też mówić o ostatniej sprawie, ponieważ miałem kolegę, który zoptymalizował piekło z czegoś, co było fajne, tyle że nikt tego nie wykorzystał. Myślę nawet, że odpowiednia optymalizacja wymaga pewnego zrozumienia przez użytkownika, w przeciwnym razie moglibyśmy profilować i dostrajać rzeczy, na których użytkownicy nie dbają.
Dragon Energy
1
Niektóre optymalizacje napędzane są naglącą potrzebą, podczas gdy inne napędzane są ciekawością (dążenie intelektualne i awanturnictwo). Potrzebujemy obu. W historii Dragon Energy prawdopodobnie nie była to „nagląca potrzeba”, ponieważ artyści najwyraźniej nie narzekali głośno, że nie widzieli żadnych wyników renderowania do 24 sekund po każdej edycji. W rzeczywistości użytkownicy mogą nie wiedzieć, jak szybko to mogło być, dopóki programista nie zainwestuje wszystkich wysiłków, aby pobić rekord prędkości. Ograniczanie się do napędzanego popytu ma sens z biznesowego punktu widzenia, ale w ten sposób stracisz niesamowite możliwości optymalizacji lub zmieniarki gier.
rwong
1
Mówiąc o sensie biznesowym, istnieje również kwestia monetyzacji. Każdy ruch (np. Programista pracujący nad optymalizacją wydajności) kosztuje, a koszty należy odzyskać, aby było to uzasadnione z biznesowego punktu widzenia. W związku z tym należy zapytać, czy zmiana prędkości, która zmienia grę, może zostać „sprzedana” lub ile pieniędzy „zaoszczędzić”, jeśli programista musi uzyskać zgodę od menedżera biznesowego.
rwong
0

Ujmę to w ten sposób - mikrooptymalizacja to proces optymalizacji czegoś, co wcale nie jest wąskim gardłem. Na przykład, jeśli twój program wywołuje dwie funkcje A i B, a wykonanie A zajmuje 100 milisekund, a B zajmuje 2 mikrosekundy, a ty nadal optymalizujesz funkcję B. To nie tylko nie jest ważne, to jest absolutnie złe. Ale funkcja optymalizacji B nazywa się optymalizacją, a nie mikrooptymalizacją. Znaczenie optymalizacji zależy. Powiedz, że nie masz nic innego do roboty, a twój program jest wolny od błędów, więc tak, to ważne. Ale generalnie masz priorytety. Powiedzmy, że musisz dodać / zapisać funkcję C. Jeśli uważasz, że funkcja pisania C przyniesie Ci więcej pieniędzy niż przyspieszenie programu bez tej funkcji, przejdź do optymalizacji. W przeciwnym razie dąż do funkcjonalności. Również, doświadczeni programiści skoncentrowani na wydajności nie poświęcają dużo czasu na optymalizację, po prostu piszą szybkie programy. Przynajmniej wiedzą, jakich narzędzi użyć, a czego nie robić przez lata, robiąc bezsensowne (czytaj mikro) optymalizacje.

użytkownik11408
źródło
ten post jest raczej trudny do odczytania (ściana tekstu). Czy mógłbyś edytować go w lepszym kształcie?
komar