Dlaczego tak wielu programistów uważa, że ​​wydajność, czytelność i łatwość konserwacji nie mogą współistnieć?

34

Odpowiadając na to pytanie , zacząłem się zastanawiać, dlaczego tak wielu programistów uważa, że ​​dobry projekt nie powinien uwzględniać wydajności, ponieważ wpłynie to na czytelność i / lub łatwość konserwacji.

Uważam, że dobry projekt uwzględnia również wydajność w momencie pisania, i że dobry programista z dobrym projektem może napisać wydajny program bez negatywnego wpływu na czytelność lub łatwość konserwacji.

Chociaż zdaję sobie sprawę z tego, że zdarzają się przypadki ekstremalne, dlaczego wielu programistów twierdzi, że efektywny program / projekt spowoduje słabą czytelność i / lub słabą konserwację, a w związku z tym wydajność nie powinna być rozważana przy projektowaniu?

justin
źródło
9
Rozumowanie na dużą skalę byłoby prawie niemożliwe, ale w przypadku małych fragmentów kodu jest to dość oczywiste. Wystarczy porównać czytelną i wydajną wersję, powiedzmy, szybkiego sortowania.
SK-logic
7
Mu. Powinieneś zacząć od poparcia swojego stwierdzenia, że ​​wielu programistów twierdzi, że wydajność prowadzi do niemożności utrzymania.
Peter Taylor
2
SK-logika: Moim zdaniem jest to jedna z najlepszych części wszystkich stron wymiany stosów, ponieważ można zakwestionować to, co oczywiste, co może być zdrowe od czasu do czasu. To, co może być dla ciebie oczywiste, może nie być oczywiste dla kogoś innego i odwrotnie. :) Dzielenie się jest dbaniem o innych.
Andreas Johansson
2
@Justin, no. Wydaje mi się, że ten wątek zakłada sytuację, w której istnieje wymuszony wybór między wydajnym kodem a kodem możliwym do utrzymania. Pytający nie mówi, jak często znajduje się w takiej sytuacji, a osoby udzielające odpowiedzi nie twierdzą, że często bywają w takiej sytuacji.
Peter Taylor
2
-1 dla pytania. Kiedy to przeczytałem, pomyślałem, że to słaby człowiek, który eksmituje jedyną prawdziwą odpowiedź: „Ponieważ nie używają pytona”.
Ingo

Odpowiedzi:

38

Myślę, że takie poglądy są zwykle reakcjami na próby przedwczesnej (mikro) optymalizacji , która wciąż jest powszechna i zwykle wyrządza więcej szkody niż pożytku. Kiedy ktoś próbuje przeciwstawić się takim poglądom, łatwo wpaść w - lub przynajmniej wyglądać - drugą skrajność.

Prawdą jest jednak, że w związku z ogromnym rozwojem zasobów sprzętowych w ostatnich dziesięcioleciach, w przypadku większości pisanych obecnie programów, wydajność przestała być głównym czynnikiem ograniczającym. Oczywiście należy wziąć pod uwagę oczekiwaną i możliwą do osiągnięcia wydajność na etapie projektowania, aby zidentyfikować przypadki, w których wydajność może (przyjść) poważnym problemem . A potem naprawdę ważne jest, aby projektować od samego początku. Jednak ogólna prostota, czytelność i łatwość konserwacji są jeszcze ważniejsze . Jak zauważyli inni, kod zoptymalizowany pod kątem wydajności jest bardziej złożony, trudniejszy do odczytania i utrzymania oraz bardziej podatny na błędy niż najprostsze działające rozwiązanie. Dlatego każdy wysiłek włożony w optymalizację musi zostać udowodniony - a nie tylko uwierzony- przynieść rzeczywiste korzyści, przy jak najmniejszym ograniczeniu długoterminowej możliwości utrzymania programu. Tak więc dobry projekt izoluje skomplikowane części wymagające dużej wydajności od reszty kodu , który jest tak prosty i czysty, jak to możliwe.

Péter Török
źródło
8
„Kiedy ktoś próbuje przeciwstawić się takim poglądom, łatwo jest wpaść w - lub przynajmniej wyglądać - w drugą skrajność”. Mam problemy z ludźmi, którzy myślą, że mam odmienny pogląd, kiedy tylko równoważę profesjonalistów z Wady. Nie tylko w programowaniu, we wszystkim.
jhocking
1
Mam już dość rozmawiania na ten temat, że się denerwuję i biorę skrajności ..
Thomas Bonini
Było kilka dobrych odpowiedzi, ale myślę, że twoja postarała się najlepiej opisać genezę tej mentalności. Dzięki wszystkim zaangażowanym!
justin
Moja odpowiedź ... większość programistów źle
radzi
38

W odpowiedzi na twoje pytanie ze strony programisty, który pracuje nad kodem o wysokiej wydajności, przy projektowaniu należy wziąć pod uwagę kilka kwestii.

  • Nie pesymalizuj przedwcześnie. Jeśli masz wybór między dwoma projektami o jednakowej złożoności, wybierz ten, który ma najlepszą charakterystykę wydajności. Jednym ze słynnych przykładów C ++ jest rozpowszechnienie liczników (lub iteratorów) w pętlach. Jest to całkowicie niepotrzebna przedwczesna pesymizacja, która MOŻE nic nie kosztować, ale MOŻE, więc nie rób tego.
  • W wielu przypadkach nie musisz jeszcze iść blisko mikrooptymalizacji. Optymalizacje algorytmiczne są owocem niżej wiszącym i prawie zawsze są o wiele łatwiejsze do zrozumienia niż optymalizacje na niskim poziomie.
  • Jeśli i TYLKO jeśli wydajność jest absolutnie krytyczna, upadasz i brudzisz się. Właściwie najpierw izolujesz kod tak bardzo, jak potrafisz, a następnie zejdziesz na dół i ubrudzisz się. I robi się tam naprawdę brudno, ze schematami buforowania, leniwą oceną, optymalizacją układu pamięci do buforowania, blokami wbudowanych elementów wewnętrznych lub zestawu, warstwami szablonów itp. Testujesz i dokumentujesz jak szalony tutaj, wiesz, że to idzie zaszkodzić, jeśli musisz wykonać jakąkolwiek konserwację tego kodu, ale musisz, ponieważ wydajność jest absolutnie krytyczna. Edycja: Nawiasem mówiąc, nie mówię, że ten kod nie może być piękny i powinien być tak piękny, jak to możliwe, ale nadal będzie bardzo złożony i często zawiły w porównaniu do mniej zoptymalizowanego kodu.

Zrób to dobrze, zrób to pięknie, zrób to szybko. W tej kolejności.

Joris Timmermans
źródło
Podoba mi się zasada: „spraw, by było pięknie, szybko. W tej kolejności'. Zacznę z tego korzystać.
Martin York,
Dokładnie. I izoluj kod w trzecim punkcie, na ile to możliwe. Ponieważ po przejściu na inny sprzęt, nawet coś tak małego jak procesor o innym rozmiarze pamięci podręcznej, te rzeczy mogą się zmienić.
KeithB
@ KeithB - ​​masz rację, dodam to do mojej odpowiedzi.
Joris Timmermans
+1: „Zrób to dobrze, zrób to pięknie, zrób to szybko. W tej kolejności”. Bardzo fajne podsumowanie, z którym zgadzam się w 90%. Czasami mogę naprawić niektóre błędy (naprawić to poprawnie), gdy tylko będę piękny (i bardziej zrozumiały).
Giorgio
+1 za „Nie przedwcześnie pesymalizuj”. Rada, aby uniknąć przedwczesnej optymalizacji, nie jest pozwoleniem na bezmyślne stosowanie algorytmów z kością. Jeśli piszesz Javę i masz kolekcję, do containsktórej często będziesz dzwonić , użyj, a HashSetnie ArrayList. Wydajność może nie mieć znaczenia, ale nie ma powodu, aby tego nie robić. Wykorzystaj zgodność między dobrym projektem a wydajnością - jeśli przetwarzasz pewną kolekcję, spróbuj zrobić wszystko w jednym przejściu, które prawdopodobnie będzie zarówno bardziej czytelne, jak i szybsze (prawdopodobnie).
Tom Anderson
16

Jeśli mogę założyć „pożyczyć” ładny diagram @ greengit i zrobić mały dodatek:

|
P
E
R
F
O  *               X <- a program as first written
R   * 
M    *
A      *
N        *
C          *  *   *  *  *
E
|
O -- R E A D A B I L I T Y --

Wszyscy zostali „nauczeni”, że istnieją krzywe kompromisów. Ponadto wszyscy założyliśmy, że jesteśmy tak optymalnymi programistami, że każdy program, który piszemy, jest tak napięty, że jest na dobrej drodze . Jeśli program jest na krzywej, każda poprawa w jednym wymiarze koniecznie wiąże się z kosztem w drugim wymiarze.

Z mojego doświadczenia wynika, że ​​programy zbliżają się do dowolnej krzywej tylko wtedy, gdy są dostrajane, modyfikowane, młotkowane, woskowane i ogólnie zamieniane w „golfa kodowego”. Większość programów ma dużo miejsca na ulepszenia we wszystkich wymiarach. Oto co mam na myśli.

Mike Dunlavey
źródło
Osobiście uważam, że istnieje inny koniec krzywej, w którym znów idzie ona w górę po prawej stronie (o ile poruszasz się wystarczająco daleko w prawo (co prawdopodobnie oznacza ponowne przemyślenie algorytmu)).
Martin York,
2
+1 za „Większość programów ma dużo miejsca na ulepszenia we wszystkich wymiarach”.
Steven
5

Właśnie dlatego, że wysoce wydajne komponenty oprogramowania są na ogół o rząd wielkości bardziej złożone niż inne komponenty oprogramowania (wszystkie inne rzeczy są równe).

Nawet wtedy nie jest to tak jednoznaczne, jeśli wskaźniki wydajności są niezwykle ważnym wymogiem, konieczne jest, aby projekt miał złożoność, aby sprostać takim wymaganiom. Niebezpieczeństwo polega na tym, że deweloper marnuje sprint na stosunkowo prostą funkcję, próbując wycisnąć kilka dodatkowych milisekund z jego komponentu.

Niezależnie od tego złożoność projektu ma bezpośredni związek ze zdolnością programisty do szybkiego uczenia się i zapoznania się z takim projektem, a dalsze modyfikacje funkcjonalności złożonego komponentu mogą powodować błędy, które mogą nie zostać wykryte przez testy jednostkowe. Złożone projekty mają wiele innych aspektów i możliwych przypadków testowych, aby rozważyć uczynienie celu 100% pokrycia testem jednostkowym jeszcze bardziej marzeniem.

Biorąc to pod uwagę, należy zauważyć, że słabo działający komponent oprogramowania może działać słabo tylko dlatego, że został niemądrze napisany i niepotrzebnie skomplikowany w oparciu o ignorancję oryginalnego autora (wykonanie 8 wywołań bazy danych w celu zbudowania pojedynczego elementu, gdy tylko jeden zrobiłby to , całkowicie niepotrzebny kod, który skutkuje pojedynczą ścieżką kodu, niezależnie od tego, itp.). Te przypadki są bardziej związane z poprawą jakości kodu i wzrostem wydajności zachodzącym w wyniku refaktora, a niekoniecznie zamierzonej konsekwencji.

Zakładając dobrze zaprojektowany komponent, zawsze będzie on jednak mniej skomplikowany niż podobnie dobrze zaprojektowany komponent dostrojony pod kątem wydajności (wszystkie inne rzeczy będą takie same).

wałek klonowy
źródło
3

Nie chodzi o to, że te rzeczy nie mogą współistnieć. Problem polega na tym, że kod każdego jest powolny, nieczytelny i niemożliwy do utrzymania przy pierwszej iteracji. Resztę czasu poświęca się na doskonalenie tego, co najważniejsze. Jeśli to jest wydajność, wybierz ją. Nie pisz złośliwie okropnego kodu, ale jeśli po prostu musi być X szybki, to spraw, by był X szybki. Uważam, że wydajność i czystość są w zasadzie nieskorelowane. Kod wykonawczy nie powoduje brzydkiego kodu. Jeśli jednak spędzasz czas na dostrajaniu każdego kawałka kodu, aby być szybkim, zgadnij, czego nie poświęciłeś? Twój kod jest czysty i łatwy w utrzymaniu.

Morgan Herlocker
źródło
2
    |
    P.
    mi
    R
    fa
    O *
    R * 
    M *
    A *
    N *
    C * * * * *
    mi
    |
    O - CZYTELNOŚĆ -

Jak widzisz...

  • Poświęcenie czytelności może zwiększyć wydajność - ale tylko w bardzo dużym stopniu. Po pewnym momencie musisz uciekać się do „rzeczywistych” oznacza jak lepsze algorytmy i sprzęt.
  • Również utrata wydajności kosztem czytelności może się zdarzyć tylko do pewnego stopnia. Następnie możesz uczynić swój program tak czytelnym, jak chcesz, bez wpływu na wydajność. Na przykład dodanie bardziej pomocnych komentarzy nie wpływa na wydajność.

Wydajność i czytelność są jednak w niewielkim stopniu powiązane - w większości przypadków nie ma naprawdę dużych zachęt, które preferowałyby te pierwsze. Mówię tu o językach wysokiego poziomu.

treecoder
źródło
1

Moim zdaniem wydajność powinna być brana pod uwagę, gdy jest to rzeczywisty problem (lub np. Wymóg). Nieprzestrzeganie tego prowadzi do mikrooptymalizacji, co może prowadzić do bardziej zaciemnionego kodu, aby zaoszczędzić kilka mikrosekund tu i tam, co z kolei prowadzi do mniej konserwowalnego i mniej czytelnego kodu. Zamiast tego należy w razie potrzeby skoncentrować się na prawdziwych wąskich gardłach systemu i położyć nacisk na wydajność.

Andreas Johansson
źródło
1

Chodzi o to, że czytelność nie powinna zawsze przewyższać wydajności. Jeśli od samego początku wiesz, że Twój algorytm musi być bardzo wydajny, będzie to jeden z czynników, które wykorzystasz do jego opracowania.

Chodzi o to, że większość przypadków użycia nie wymaga oślepiającego szybkiego kodu. W wielu przypadkach interakcja IO lub użytkownika powoduje znacznie większe opóźnienie niż wykonanie algorytmu. Chodzi o to, że nie powinieneś starać się uczynić czegoś bardziej wydajnym, jeśli nie wiesz, że to szyjka butelki.

Optymalizacja kodu pod kątem wydajności często czyni go bardziej skomplikowanym, ponieważ zazwyczaj wymaga robienia rzeczy w sprytny sposób, a nie w najbardziej intuicyjny sposób. Bardziej skomplikowany kod jest trudniejszy w utrzymaniu i trudniejszy do pobrania dla innych programistów (oba są kosztami, które należy wziąć pod uwagę). Jednocześnie kompilatory są bardzo dobre w optymalizacji typowych przypadków. Możliwe, że próba ulepszenia zwykłego przypadku oznacza, że ​​kompilator nie rozpoznaje już wzorca, a zatem nie może pomóc w szybkim utworzeniu kodu. Należy zauważyć, że nie oznacza to pisania, co chcesz, bez względu na wydajność. Nie powinieneś robić niczego, co jest wyraźnie nieefektywne.

Chodzi o to, aby nie martwić się drobiazgami, które mogłyby ulepszyć. Użyj profilera i przekonaj się, że 1) masz teraz problem i 2) zmieniłeś go na ulepszenie.

unholysampler
źródło
1

Myślę, że większość programistów odczuwa to przeczucie po prostu dlatego, że przez większość czasu kod wydajności jest kodem opartym na dużo większej ilości informacji (o kontekście, wiedzy o sprzęcie, globalnej architekturze) niż jakikolwiek inny kod w aplikacjach. Większość kodu wyraża tylko niektóre rozwiązania określonych problemów, które są enkapsulowane w niektórych abstrakcjach w sposób modułowy (jak funkcje), a to oznacza ograniczanie znajomości kontekstu tylko do tego, co wchodzi w tę enkapsulację (jak parametry funkcji).

Kiedy piszesz w celu uzyskania wysokiej wydajności, po naprawieniu jakiejkolwiek optymalizacji algorytmicznej, wchodzisz w szczegóły, które wymagają znacznie większej wiedzy na temat kontekstu. To naturalnie może przytłoczyć każdego programistę, który nie czuje się wystarczająco skoncentrowany na tym zadaniu.

Klaim
źródło
1

Ponieważ koszt globalnego ocieplenia (z tych dodatkowych cykli procesora skalowanych przez setki milionów komputerów PC oraz ogromne zaplecze centrum danych) i przeciętnej żywotności baterii (na urządzeniach mobilnych użytkownika), wymaganej do uruchomienia ich źle zoptymalizowanego kodu, rzadko pojawia się na większości wydajność programisty lub recenzje.

Jest to ekonomiczny negatywny efekt zewnętrzny, podobny do formy ignorowanego zanieczyszczenia. Tak więc stosunek kosztów do korzyści myślenia o wydajności w ogóle jest mentalnie wypaczony z rzeczywistości.

Projektanci sprzętu ciężko pracują, dodając funkcje oszczędzania energii i skalowania zegara do najnowszych procesorów. Programiści powinni pozwolić sprzętowi częściej korzystać z tych możliwości, nie rozgryzając każdego dostępnego cyklu zegara procesora.

DODANO: W czasach starożytnych koszt jednego komputera wynosił miliony, więc optymalizacja czasu procesora była bardzo ważna. Wtedy koszt opracowania i utrzymania kodu stał się większy niż koszt komputerów, więc optymalizacja wypadła zdecydowanie nie na korzyść w porównaniu z wydajnością programisty. Teraz jednak inny koszt staje się większy niż koszt komputerów, koszt zasilania i chłodzenia wszystkich tych centrów danych jest teraz większy niż koszt wszystkich procesorów w środku.

hotpaw2
źródło
Oprócz pytania, czy komputery osobiste przyczyniły się do globalnego ocieplenia, nawet gdyby były rzeczywiste: błędem jest, że większa efektywność energetyczna prowadzi do mniejszego zapotrzebowania na energię. Prawie na odwrót jest prawda, jak widać od pierwszego dnia pojawienia się komputera na rynku. Wcześniej kilkaset lub trzydzieści komputerów mainframe (każdy praktycznie wyposażony we własną elektrownię) zużywało znacznie mniej energii niż obecnie, gdzie 1 minuta procesora oblicza znacznie więcej niż wtedy przy ułamku kosztów i zapotrzebowania na energię. Jednak całkowite zapotrzebowanie na energię do obliczeń jest wyższe niż wcześniej.
Ingo
1

Myślę, że trudno jest osiągnąć wszystkie trzy. Dwa, jak sądzę, mogą być wykonalne. Na przykład myślę, że w niektórych przypadkach możliwe jest osiągnięcie wydajności i czytelności, ale łatwość konserwacji może być trudna w przypadku mikrodostrojenia kodu. Najbardziej wydajnemu kodowi na tej planecie na ogół brakuje zarówno łatwości konserwacji, jak i czytelności, co prawdopodobnie jest oczywiste dla większości, chyba że jesteś osobą, która rozumie ręcznie wektoryzowany SoA, wielowątkowy kod SIMD, który Intel zapisuje z wbudowanym złożeniem lub najbardziej wycinany algorytmy krawędziowe stosowane w branży z 40-stronicowymi artykułami matematycznymi opublikowanymi zaledwie 2 miesiące temu i kodem o wartości 12 bibliotek dla jednej niezwykle złożonej struktury danych.

Mikroefektywność

Sugeruję, że może być sprzeczne z popularną opinią, że najmądrzejszy kod algorytmiczny jest często trudniejszy w utrzymaniu niż najbardziej precyzyjny algorytm. Pomysł, że ulepszenia skalowalności przynoszą większe zyski w porównaniu z mikrodostrojonym kodem (np. Wzorce dostępu przyjazne dla pamięci podręcznej, wielowątkowość, SIMD itp.) Jest czymś, co rzuciłbym wyzwanie, przynajmniej pracując w branży wypełnionej niezwykle złożonym struktury danych i algorytmy (branża efektów wizualnych), szczególnie w obszarach takich jak przetwarzanie siatki, ponieważ huk może być duży, ale złotówka jest niezwykle droga, gdy wprowadzasz nowe algorytmy i struktury danych, o których nikt wcześniej nie słyszał, ponieważ są marką Nowy. Ponadto ja

Pomysł, że optymalizacje algorytmiczne zawsze przebijają, powiedzmy, optymalizacje związane z wzorcami dostępu do pamięci, jest zawsze czymś, z czym się nie zgadzam. Oczywiście, jeśli używasz sortowania bąbelkowego, żadna ilość mikrooptymalizacji nie może ci w tym pomóc ... ale z uzasadnionego powodu nie sądzę, że zawsze jest to tak jednoznaczne. Prawdopodobnie optymalizacje algorytmiczne są trudniejsze do utrzymania niż mikrooptymalizacje. Łatwiej byłoby mi powiedzieć, powiedzmy, Embree Intela, który pobiera klasyczny i prosty algorytm BVH i po prostu mikro-tuninguje bzdury z niego niż kod OpenVDB Dreamwork dla najnowszych metod algorytmicznego przyspieszania symulacji płynów. Przynajmniej w mojej branży chciałbym zobaczyć więcej osób zaznajomionych z mikrooptymalizacją architektury komputerów, tak jak Intel, gdy wkroczyli na scenę, w przeciwieństwie do wymyślania tysięcy nowych algorytmów i struktur danych. Dzięki skutecznym mikrooptymalizacjom ludzie mogą znaleźć coraz mniej powodów do wymyślania nowych algorytmów.

Pracowałem wcześniej w bazie kodu, gdzie prawie każda operacja użytkownika miała swoją unikalną strukturę danych i algorytm (dodając setki egzotycznych struktur danych). I większość z nich miała bardzo wypaczoną charakterystykę działania, ponieważ ma bardzo wąskie zastosowanie. Byłoby o wiele łatwiej, gdyby system mógł obracać się wokół kilkudziesięciu bardziej rozpowszechnionych struktur danych, i myślę, że mogłoby tak być, gdyby były one znacznie lepiej zoptymalizowane pod kątem mikro. Wspominam o tym przypadku, ponieważ mikrooptymalizacja może potencjalnie znacznie poprawić łatwość konserwacji w takim przypadku, jeśli oznacza to różnicę między setkami mikropesymizowanych struktur danych, których nie można nawet bezpiecznie używać do celów ścisłego odczytu, które wiążą się z brakami pamięci podręcznej i prawda vs.

Języki funkcjonalne

Tymczasem niektóre z najbardziej konserwowalnych kodów, jakie kiedykolwiek spotkałem, były dość wydajne, ale bardzo trudne do odczytania, ponieważ zostały napisane w językach funkcjonalnych. Ogólnie, moim zdaniem, czytelność i łatwość konserwacji są sprzecznymi pomysłami.

Naprawdę trudno jest uczynić kod czytelnym, łatwym w utrzymaniu i wydajnym jednocześnie. Zazwyczaj trzeba trochę pójść na kompromis w jednym z tych trzech, jeśli nie w dwóch, na przykład pogarszając czytelność pod kątem łatwości konserwacji lub podważając łatwość konserwacji pod względem wydajności. Zazwyczaj jest to łatwość utrzymania, gdy szukasz wielu pozostałych dwóch.

Czytelność a łatwość konserwacji

Jak już powiedziano, uważam, że czytelność i łatwość konserwacji nie są harmonijnymi koncepcjami. W końcu najbardziej czytelny kod dla większości z nas śmiertelników bardzo intuicyjnie odwzorowuje ludzkie wzorce myślowe, a wzorce ludzkich myśli są z natury podatne na błędy: „ Jeśli tak się stanie, zrób to. Jeśli tak się stanie, zrób to. W przeciwnym razie zrób to. Ups , Zapomniałem czegoś! Jeśli te systemy współdziałają ze sobą, powinno to się zdarzyć, aby ten system mógł to zrobić ... och, czekaj, co z tym systemem, gdy to zdarzenie zostanie wywołane?„Zapomniałem dokładnego cytatu, ale ktoś kiedyś powiedział, że gdyby Rzym zbudowano jak oprogramowanie, wystarczyłoby ptaka lądującego na ścianie, aby go przewrócić. Tak jest w przypadku większości programów. Jest to bardziej delikatne, niż nam się często wydaje Pomyśl o tym. Kilka wierszy pozornie nieszkodliwego kodu tu i tam może zatrzymać go do tego stopnia, że ​​zmusimy nas do ponownego przemyślenia całego projektu, a języki wysokiego poziomu, które mają być jak najbardziej czytelne, nie są wyjątkiem od takich błędów w projektowaniu przez ludzi .

Czyste języki funkcjonalne są prawie tak niewrażliwe na to, jak to tylko możliwe (nawet bliskie niewrażliwości, ale stosunkowo dużo bliżej niż większość). A częściowo dlatego, że nie odwzorowują intuicyjnie ludzkich myśli. Nie są czytelne. Wymuszają na nas wzorce myślenia, które powodują, że musimy rozwiązywać problemy w jak najmniejszej liczbie przypadków szczególnych, wykorzystując minimalną możliwą wiedzę i nie powodując żadnych skutków ubocznych. Są niezwykle ortogonalne, pozwalają często zmieniać i zmieniać kod bez niespodzianek tak epickich, że musimy przemyśleć projekt na desce kreślarskiej, nawet do tego stopnia, że ​​zmieniamy zdanie na temat ogólnego projektu, bez przepisywania wszystkiego. Wydaje się, że nie jest łatwiejsze do utrzymania niż to ... ale kod jest nadal bardzo trudny do odczytania,


źródło
1
„Mikroefektywność” przypomina powiedzenie „Nie ma czegoś takiego jak dostęp do pamięci O (1)”
Caleth,
0

Jednym z problemów jest to, że skończony czas programisty oznacza, że ​​wszystko, co chcesz zoptymalizować, zabiera poświęcanie czasu na inne kwestie.

Jest dość dobry eksperyment na tym, o którym mowa w Meyer Code Complete. Poproszono różne grupy programistów o optymalizację pod kątem szybkości, wykorzystania pamięci, czytelności, odporności i tak dalej. Stwierdzono, że ich projekty uzyskały wysokie wyniki we wszystkich aspektach optymalizacji, ale niższe we wszystkich innych aspektach.

deworde
źródło
Oczywiście możesz poświęcić więcej czasu, ale w końcu zaczynasz zastanawiać się, dlaczego programiści biorą wolne od programowania emacs, aby wyrazić miłość do swoich dzieci, i w tym momencie jesteś zasadniczo Sheldon z teorii wielkiego podrywu
deworde
0

Ponieważ doświadczeni programiści nauczyli się, że to prawda.

Pracowaliśmy z kodem, który jest oszczędny i wredny i nie ma problemów z wydajnością.

Pracowaliśmy nad wieloma kodami, które w celu rozwiązania problemów z wydajnością są BARDZO złożone.

Jednym z bezpośrednich przykładów, który przychodzi mi na myśl, jest to, że mój ostatni projekt obejmował 8192 ręcznie dzielonych tabel SQL. Było to potrzebne z powodu problemów z wydajnością. Konfiguracja wyboru z 1 tabeli jest o wiele prostsza niż wybranie i utrzymanie 8192 odłamków.

Michael Durrant
źródło
0

Istnieją również słynne fragmenty wysoce zoptymalizowanego kodu, który wygina mózgi większości ludzi, które wspierają przypadek, w którym wysoce zoptymalizowany kod jest trudny do odczytania i zrozumienia.

Oto najbardziej znany, jak sądzę. Zaczerpnięte z Quake III Arena i przypisane Johnowi Carmakowi, chociaż myślę, że było kilka iteracji tej funkcji i nie została przez niego pierwotnie stworzona ( czy Wikipedia nie jest świetna? ).

float Q_rsqrt( float number )
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;                       // evil floating point bit level hacking
    i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
    y  = * ( float * ) &i;
    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
    //      y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

    return y;
}
fwgx
źródło