Często widziałem ten cytat usprawiedliwiający oczywisty zły kod lub kod, który, choć nie został zmierzony jego wydajności, prawdopodobnie mógłby zostać przyspieszony dość łatwo, bez zwiększania rozmiaru kodu lub pogarszania jego czytelności.
Ogólnie uważam, że wczesne mikrooptymalizacje mogą być złym pomysłem. Jednak optymalizacje makr (takie jak wybór algorytmu O (log N) zamiast O (N ^ 2)) są często opłacalne i powinny być wykonane wcześnie, ponieważ pisanie algorytmu O (N ^ 2) i marnotrawstwem może być następnie wyrzuć to całkowicie na korzyść podejścia O (log N).
Zauważ, że słowa mogą być następujące : jeśli algorytm O (N ^ 2) jest prosty i łatwy do napisania, możesz go wyrzucić później bez większego poczucia winy, jeśli okaże się on zbyt wolny. Ale jeśli oba algorytmy są podobnie złożone lub jeśli oczekiwane obciążenie jest tak duże, że wiesz, że będziesz potrzebować szybszego, wtedy optymalizacja na wczesnym etapie jest rozsądną decyzją inżynieryjną, która zmniejszy całkowite obciążenie w dłuższej perspektywie.
Ogólnie rzecz biorąc, myślę, że właściwym podejściem jest sprawdzenie, jakie masz opcje, zanim zaczniesz pisać kod i świadomie wybranie najlepszego algorytmu dla twojej sytuacji. Co najważniejsze, zwrot „przedwczesna optymalizacja jest źródłem wszelkiego zła” nie usprawiedliwia ignorancji. Programiści powinni mieć ogólne wyobrażenie o koszcie typowych operacji; powinni wiedzieć na przykład
- że ciągi kosztują więcej niż liczby
- języki dynamiczne są znacznie wolniejsze niż języki o typie statycznym
- zalety list tablic / wektorów w porównaniu z listami połączonymi i odwrotnie
- kiedy korzystać z tablicy mieszającej, kiedy korzystać z posortowanej mapy, a kiedy ze stosu
- że (jeśli działają z urządzeniami mobilnymi) „double” i „int” mają podobną wydajność na komputerach stacjonarnych (FP może być nawet szybszy), ale „double” może być sto razy wolniejszy na niższych urządzeniach mobilnych bez FPU;
- że przesyłanie danych przez Internet jest wolniejsze niż dostęp do dysku twardego, dyski twarde są znacznie wolniejsze niż pamięć RAM, pamięć RAM jest znacznie wolniejsza niż pamięć podręczna L1 i rejestry, a operacje internetowe mogą blokować się na czas nieokreślony (i w dowolnym momencie mogą ulec awarii).
Ponadto programiści powinni zapoznać się z zestawem struktur danych i algorytmów, aby mogli łatwo korzystać z odpowiednich narzędzi do danego zadania.
Posiadanie dużej wiedzy i osobistego zestawu narzędzi umożliwia optymalizację niemal bez wysiłku. Wkładanie wielu wysiłków w optymalizację, która może być niepotrzebna, jest złem (i przyznaję, że wpadłem w tę pułapkę więcej niż raz). Ale jeśli optymalizacja jest tak prosta, jak wybranie zbioru / tablicy mieszającej zamiast tablicy lub przechowywanie listy liczb w podwójnym [] zamiast ciągu [], to dlaczego nie? Może nie zgadzam się z Knuthem tutaj, nie jestem pewien, ale myślę, że mówił o optymalizacji niskiego poziomu, podczas gdy mówię o optymalizacji wysokiego poziomu.
Pamiętaj, że ten cytat pochodzi z 1974 roku. W 1974 roku komputery działały wolno, a moc obliczeniowa była droga, co dało niektórym programistom tendencję do nadmiernej optymalizacji, linia po linii. Myślę, że właśnie temu naciskał Knuth. Nie mówił „wcale nie przejmuj się wydajnością”, ponieważ w 1974 roku to byłaby szalona rozmowa. Knuth wyjaśniał, jak zoptymalizować; w skrócie, należy skupić się tylko na wąskich gardłach, a zanim to zrobisz, musisz wykonać pomiary, aby znaleźć wąskie gardła.
Zauważ, że nie możesz znaleźć wąskich gardeł, dopóki nie napiszesz programu do pomiaru, co oznacza, że niektóre decyzje dotyczące wydajności muszą zostać podjęte, zanim cokolwiek zostanie zmierzone. Czasami decyzje te trudno zmienić, jeśli się pomylisz. Z tego powodu dobrze jest mieć ogólny obraz tego, co kosztuje, abyś mógł podejmować rozsądne decyzje, gdy żadne twarde dane nie są dostępne.
To, jak wcześnie zoptymalizować i jak bardzo martwić się o wydajność, zależy od zadania. Pisząc skrypty, które uruchomisz tylko kilka razy, martwienie się o wydajność zwykle jest kompletną stratą czasu. Ale jeśli pracujesz dla Microsoft lub Oracle i pracujesz nad biblioteką, z której tysiące innych programistów będą korzystać na tysiące różnych sposobów, może opłacić się optymalizacja, abyś mógł pokryć wszystkie różnorodne efektywnie wykorzystuj skrzynki. Mimo to potrzeba wydajności musi być zawsze zrównoważona z potrzebą czytelności, łatwości konserwacji, elegancji, rozszerzalności i tak dalej.