Jestem młodszym programistą i zastanawiałem się, kiedy najlepiej zoptymalizować oprogramowanie w celu uzyskania lepszej wydajności (szybkości).
Zakładając, że oprogramowanie nie jest zbyt duże i skomplikowane w zarządzaniu, czy lepiej poświęcić więcej czasu na jego optymalizację na początku, czy powinienem po prostu opracować oprogramowanie, które poprawnie wykonuje wszystkie funkcje, a następnie przystąpić do optymalizacji w celu uzyskania lepszej wydajności?
Odpowiedzi:
Najważniejszą rzeczą powinna być zawsze i na zawsze czytelność. Jeśli jest wolny, ale czytelny, mogę to naprawić. Jeśli jest zepsuty, ale czytelny, mogę to naprawić. Jeśli jest to nieczytelne, muszę zapytać kogoś innego, co to miało zrobić.
Zadziwiające jest, jak wydajny może być Twój kod, gdy koncentrujesz się tylko na jego czytelności. Tak bardzo, że generalnie ignoruję wydajność, dopóki nie mam powodu, aby się tym przejmować. To nie powinno oznaczać, że nie dbam o szybkość. Ja robię. Właśnie odkryłem, że jest bardzo mało problemów, których rozwiązania są szybsze, gdy są trudne do odczytania.
Tylko dwie rzeczy wykluczają mnie z tego trybu:
W każdym razie unikaj porażenia analizy , sprawiając, że nie powinieneś wypróbowywać rozwiązania, ponieważ może nie być najszybsze. Twój kod rzeczywiście skorzysta, jeśli wypróbujesz wiele rozwiązań, ponieważ wprowadzenie zmian zmusi cię do użycia projektu, który ułatwia zmianę. Elastyczna baza kodu może być później przyspieszona tam, gdzie naprawdę tego potrzebuje. Wybierz opcję elastyczną zamiast prędkości i możesz wybrać potrzebną prędkość.
źródło
Jeśli konieczny jest określony poziom wydajności (wymaganie niefunkcjonalne), powinien to być cel projektowy od samego początku. Np. Może to wpłynąć na to, które technologie mogą być odpowiednie lub na strukturę przepływu danych w programie.
Ale ogólnie rzecz biorąc, nie jest możliwa optymalizacja przed napisaniem kodu: najpierw spraw, by działał, następnie popraw go, a na koniec spraw , by był szybki .
Jednym z dużych problemów z optymalizacją przed wdrożeniem większości funkcji jest to, że zablokowałeś się w nieoptymalnych decyzjach projektowych w niewłaściwych miejscach. Często istnieje (ale niekoniecznie) kompromis między utrzymywalnością a wydajnością. Większość części twojego programu jest całkowicie nieistotna dla wydajności! Typowe programy mają tylko kilka gorących punktów, które naprawdę warto zoptymalizować. Tak więc poświęcenie możliwości utrzymania w celu uzyskania wydajności we wszystkich tych miejscach, które nie wymagają wydajności, to naprawdę zły handel.
Optymalizacja pod kątem łatwości konserwacji jest lepszym podejściem. Jeśli poświęcisz swoją spryt na łatwość konserwacji i przejrzyste projekty, na dłuższą metę łatwiej będzie ci zidentyfikować krytyczne sekcje i bezpiecznie je zoptymalizować bez uszczerbku dla ogólnego projektu.
źródło
Zacznij od usunięcia z umysłu koncepcji, że wydajność jest tym samym, co prędkość. Wydajność jest tym, co użytkownik uważa za wydajność .
Jeśli sprawisz, że aplikacja zareaguje dwa razy szybciej na kliknięcie myszą i przejdziesz od dziesięciu mikrosekund do pięciu mikrosekund, użytkownik nie będzie się tym przejmował. Jeśli sprawisz, że aplikacja zareaguje dwa razy szybciej na kliknięcie myszą i przejdziesz od czterech tysięcy lat do dwóch tysięcy lat, znowu, użytkownik nie będzie się tym przejmował.
Jeśli twoja aplikacja będzie dwa razy szybsza i zużyjesz całą pamięć na komputerze i ulegnie awarii, użytkownik nie będzie się przejmował, że teraz jest dwa razy szybsza.
Wydajność to nauka polegająca na skutecznych kompromisach dotyczących zużycia zasobów w celu uzyskania określonego komfortu użytkowania. Czas użytkownika jest ważnym zasobem , ale nigdy nie chodzi tylko o „szybsze”. Osiągnięcie celów w zakresie wydajności prawie zawsze wymaga kompromisów, a często poświęcają czas na miejsce lub odwrotnie.
To okropne założenie.
Jeśli oprogramowanie nie jest duże i skomplikowane w zarządzaniu, prawdopodobnie nie rozwiązuje interesującego problemu, na którym dba użytkownik, i prawdopodobnie jest bardzo łatwe do optymalizacji.
Siedzisz na pustej stronie i piszesz
void main() {}
Czy zaczynasz optymalizować? Nie ma nic do optymalizacji! Właściwa kolejność to:Jeśli spróbujesz to zrobić w dowolnej innej kolejności, skończy się to błędnym kodem, który jest bałaganem, a teraz masz program, który naprawdę szybko udziela błędnych odpowiedzi i jest odporny na zmiany.
Ale brakuje tam kroku. Prawdziwe prawo zamówienia jest:
źródło
Zasadniczo najlepiej jest optymalizować wydajność później, ale widziałem, że wiele projektów się psuje, gdy programiści zdają sobie sprawę, że skończyli z oprogramowaniem, które spowalnia, gdy dodawane jest do niego znaczne obciążenie lub dane.
Tak więc moim zdaniem najlepsze byłoby podejście pośrednie; nie kładź na to zbyt dużego nacisku, ale nie lekceważ całkowicie wydajności.
Podam przykład, który widziałem wiele razy; biorąc pod uwagę bibliotekę ORM, mamy encję użytkownika, która może mieć jedno lub więcej zamówień. Zapętlmy wszystkie zamówienia dla użytkownika i dowiedzmy się, ile użytkownik wydał w naszym sklepie - naiwne podejście:
Widziałem, jak programiści piszą podobne rzeczy, nie myśląc o implikacjach; najpierw otrzymujemy użytkownika, który, mam nadzieję, będzie tylko jednym zapytaniem SQL w tabeli użytkowników (ale może obejmować znacznie, znacznie więcej), a następnie przeglądamy zamówienia, które mogą obejmować uzyskanie wszystkich odpowiednich danych dla wszystkich wierszy zamówienia w zamówieniu , informacje o produkcie itp. - wszystko po to, aby uzyskać jedną liczbę całkowitą dla każdego zamówienia!
Liczba zapytań SQL może Cię zaskoczyć. Oczywiście zależy to od struktury twoich bytów.
W tym przypadku poprawnym podejściem byłoby najprawdopodobniej dodanie oddzielnej funkcji w celu pobrania sumy z bazy danych za pomocą osobnego zapytania zapisanego w języku zapytań dostarczonym przez ORM, i zalecałbym zrobienie tego za pierwszym razem , a nie odkładanie tego na później na później; ponieważ jeśli to zrobisz, prawdopodobnie będziesz mieć dużo więcej problemów do załatwienia i nie wiesz, od czego zacząć.
źródło
Całkowita wydajność systemu jest wynikiem złożonych interakcji wszystkich elementów systemu. To system nieliniowy. Dlatego wydajność będzie zależna nie tylko od indywidualnej wydajności komponentów, ale także od wąskich gardeł między nimi.
Oczywiście nie można testować wąskich gardeł, jeśli wszystkie elementy systemu nie są jeszcze zbudowane, więc nie można naprawdę bardzo dobrze testować wcześnie. Z drugiej strony po zbudowaniu systemu może nie być łatwo wprowadzić zmiany, które należy wprowadzić, aby uzyskać żądaną wydajność. To jest kość Catch-22 .
Aby utrudnić sprawę, profil wydajności może się drastycznie zmienić po przejściu do środowiska produkcyjnego, które często nie jest dostępne wcześnie.
Więc co robisz? Cóż, kilka rzeczy.
Bądź pragmatyczny. Od samego początku możesz wybrać funkcje platformy, które są „najlepszą praktyką” w zakresie wydajności; na przykład wykorzystuj pule połączeń, transakcje asynchroniczne i unikaj stanowości, co może być śmiercią wielowątkowej aplikacji, w której różni pracownicy walczą o dostęp do współużytkowanych danych. Zwykle nie testowałbyś tych wzorów pod kątem wydajności, po prostu wiedziałeś z doświadczenia, co działa dobrze.
Bądź iteracyjny. Podejmij bazowe pomiary wydajności, gdy system jest stosunkowo nowy, i od czasu do czasu ponownie testuj, aby upewnić się, że nowo wprowadzony kod nie obniżył wydajności zbyt mocno.
Nie zbyt wcześnie optymalizuj. Nigdy nie wiesz, co będzie ważne, a co nie będzie miało znaczenia; superszybki algorytm parsowania ciągów może nie pomóc, jeśli twój program na przykład stale czeka na operacje we / wy.
Szczególnie w aplikacjach internetowych możesz skupić się nie tyle na wydajności, co na skalowalności. Jeśli aplikacja może zostać skalowana, wydajność prawie nie ma znaczenia, ponieważ możesz dodawać węzły do farmy, dopóki nie będzie wystarczająco szybka.
Szczególną uwagę przywiązuje się do bazy danych. Ze względu na ograniczenia integralności transakcyjnej baza danych jest wąskim gardłem, które dominuje w każdej części systemu. Jeśli potrzebujesz wysokowydajnego systemu, upewnij się, że masz utalentowanych ludzi, którzy pracują po stronie bazy danych, przeglądają plany zapytań oraz opracowują struktury tabel i indeksów, dzięki którym wspólne operacje są tak wydajne, jak to możliwe.
Większość z tych działań nie jest na początku lub na końcu projektu, ale należy stale brać w nich udział .
źródło
Zrozum, że istnieją 2 bardzo różne skrajności.
Pierwszą skrajnością są rzeczy, które wpływają na dużą część projektu, takie jak podział pracy na liczbę procesów i / lub wątków oraz sposób komunikacji elementów (gniazda TCP / IP? Bezpośrednie wywołania funkcji?), Czy zaimplementować zaawansowany JIT lub interpreter „jeden kod operacji na raz”, albo czy planować struktury danych, które będą podatne na SIMD, lub… Te rzeczy mają zwykle duży wpływ na implementację i stają się zbyt trudne / kosztowne, aby później je dopasować.
Druga skrajność to mikrooptymalizacje - drobne drobne poprawki w każdym miejscu. Te rzeczy zwykle nie mają prawie żadnego wpływu na implementację (i często najlepiej jest to zrobić przez kompilator), a optymalizacje, gdy masz na to ochotę, są trywialne.
Pomiędzy tymi skrajnościami znajduje się ogromny szary obszar.
To, co tak naprawdę sprowadza się do tego, to doświadczenie / wykształcone domysły wykorzystywane do odpowiedzi na pytanie „czy korzyści uzasadniają koszty”. W przypadku optymalizacji na poziomie ekstremalnym lub zbliżonym do jednego skrajnego, jeśli często się mylicie, oznacza to wyrzucenie całej pracy i ponowne uruchomienie od zera lub awarii projektu (zbyt dużo czasu poświęconego na niepotrzebnie zbyt skomplikowany projekt). W / przeciw drugiej skrajności znacznie sensowniej jest pozostawić ją, dopóki nie będziesz w stanie udowodnić, że ma to znaczenie za pomocą pomiaru (np. Profilowania).
Niestety żyjemy w świecie, w którym zdecydowanie zbyt wiele osób uważa, że optymalizacja obejmuje tylko (głównie nieistotne) rzeczy z „trywialnego” ekstremum.
źródło
Najłatwiej jest napisać kod, który nie jest porformantem ani nie jest łatwy do utrzymania. Trudniej jest pisać kod porformant. Jeszcze trudniej jest napisać możliwy do utrzymania kod. I najtrudniej jest napisać kod, który jest zarówno łatwy w utrzymaniu, jak i wydajny.
Ale łatwiej jest uczynić kod wykonalnym możliwym do utrzymania, niż uczynić kod wykonalnym możliwym do utrzymania.
Teraz, oczywiście, zależy to od rodzaju tworzonego systemu, niektóre systemy będą bardzo krytyczne pod względem wydajności i będą wymagały tego od samego początku. Dla niezwykle utalentowanych ludzi, takich jak Eric Lippert, którzy odpowiedzieli powyżej, systemy te mogą być wspólne; ale dla większości z nas stanowią mniejszość systemów, które budujemy.
Biorąc jednak pod uwagę stan nowoczesnego sprzętu, w większości systemów nie trzeba od samego początku zwracać szczególnej uwagi na optymalizację, ale zwykle wystarcza uniknięcie zniszczenia wydajności . Rozumiem przez to, że nie robię po prostu głupich rzeczy, takich jak przywoływanie wszystkich rekordów tabeli, aby uzyskać liczbę, zamiast tylko zapytania
select count(*) from table
. Po prostu unikaj błędów i staraj się zrozumieć narzędzia, których używasz.Następnie skoncentruj się na tym, aby Twój kod był łatwy w utrzymaniu. Rozumiem przez to:
Utrzymywalny kod jest znacznie łatwiejszy do optymalizacji, gdy statystyki pokazują, że jest on potrzebny.
Następnie upewnij się, że Twój kod ma wiele automatycznych testów, ma to kilka zalet. Mniej błędów oznacza więcej czasu na optymalizację w razie potrzeby . Ponadto, gdy wykonujesz optymalizację, możesz iterować i znaleźć najlepsze rozwiązanie znacznie szybciej, ponieważ błędy w swoich implementacjach są znacznie szybsze.
Zautomatyzowane skrypty wdrażania i infrastruktura skryptowa są również bardzo przydatne do dostrajania wydajności, ponieważ ponownie umożliwiają szybsze iterowanie; nie wspominając o innych jego zaletach.
Jak zawsze, są wyjątki (które będą wymagały doświadczenia, aby lepiej zidentyfikować), ale ogólnie moja rada jest następująca: najpierw naucz się swoich narzędzi i unikaj wąskich gardeł w kodowaniu. Po drugie, upewnij się, że kod jest możliwy do utrzymania. Po trzecie, zautomatyzowane testy. Po czwarte, w pełni zautomatyzowane wdrożenia. Dopiero po wykonaniu tych czynności należy się martwić optymalizacją.
źródło
Mogę być stronniczy w pracy w obszarach o krytycznym znaczeniu dla wydajności, takich jak przetwarzanie obrazu i raytracingu, ale nadal twierdzę, że optymalizuję „tak późno, jak to możliwe” . Bez względu na to, jak ważne są Twoje wymagania, po pomiarach zawsze jest o wiele więcej informacji i jasności niż z góry, co oznacza, że nawet najskuteczniejsze optymalizacje są zazwyczaj stosowane później po zdobyciu takiej wiedzy.
Szczególne przypadki
Ale czasami „tak późno, jak to możliwe” jest wciąż dość cholernie wczesna w niektórych szczególnych przypadkach. Jeśli mówimy o mechanizmach renderujących offline, na przykład o strukturach danych i technikach używanych do osiągnięcia wydajności faktycznie przenikają do projektu użytkownika. Może to zabrzmieć obrzydliwie, ale pole jest tak przełomowe i tak krytyczne pod względem wydajności, że użytkownicy akceptują kontrolki użytkownika specyficzne dla technik optymalizacji mających zastosowanie do konkretnego raytracera (np. Buforowanie napromieniowania lub mapowanie fotonów), ponieważ niektóre z nich są używane godzin oczekiwania na wyrenderowanie obrazu, a inne są przyzwyczajone do wyrzucania ogromnych sum pieniędzy na wynajem lub posiadanie farmy renderującej za pomocą maszyn przeznaczonych do renderowania. Użytkownicy mogą znacznie skrócić czas i pieniądze, jeśli konkurencyjny renderer offline może zaoferować niebanalne skrócenie czasu renderowania. Jest to rodzaj obszaru, w którym 5% skrócenie czasu faktycznie podnieca użytkowników.
W takich szczególnych przypadkach nie można po prostu wybrać jednej techniki renderowania chcąc nie chcąc i mamy nadzieję ją później zoptymalizować, ponieważ cały projekt, w tym projekt użytkownika, obraca się wokół wykorzystywanych struktur danych i algorytmów. Nie zawsze możesz po prostu pójść z tym, co działało dobrze dla innych ludzi, ponieważ tutaj, jako osoba, a także twoje szczególne mocne i słabe strony, w znacznym stopniu przyczyniają się do zapewnienia konkurencyjnego rozwiązania. Sposób myślenia i wrażliwość głównego programisty Arnolda różnią się od tych pracujących nad VRay, którzy stosowali zupełnie inne podejście; niekoniecznie muszą zamieniać miejsca / techniki i wykonywać najlepszą robotę (mimo że obaj są liderami branży). Musisz w pewnym sensie eksperymentować, prototypować i testować oraz znaleźć to, co „ jest szczególnie dobry w robieniu, biorąc pod uwagę nieskończony wachlarz najnowocześniejszych technik, jeśli masz nadzieję wysłać coś konkurencyjnego, co faktycznie się sprzedaje. Tak więc w tym szczególnym przypadku problemy z wydajnością przenoszą się na pierwszy plan, być może najważniejszą kwestią jeszcze przed rozpoczęciem rozwoju.
Jednak niekoniecznie jest to naruszenie optymalizacji „tak późno, jak to możliwe” , po prostu „tak późno, jak to możliwe” jest raczej wczesne w tych ekstremalnych i osobliwych przypadkach. Dowiedzenie się, kiedy i co nie potrzebuje tak wczesnych problemów z wydajnością, jeśli w ogóle, jest prawdopodobnie głównym wyzwaniem dla dewelopera. Czego nie optymalizować może być jedną z najcenniejszych rzeczy do nauczenia się i uczenia się w karierze programisty, ponieważ nie brakuje naiwnych programistów, którzy chcą wszystko zoptymalizować (i niestety nawet niektórzy weterani, którym udało się jakoś utrzymać pracę pomimo ich kontrproduktywności).
Tak późno jak to możliwe
Być może najtrudniejszą częścią jest próba zrozumienia, co to znaczy. Wciąż się uczę i programuję od prawie trzech dekad. Ale szczególnie teraz, w trzeciej dekadzie, zaczynam zdawać sobie sprawę, że to nie takie trudne. To nie jest nauka o rakietach, jeśli bardziej skupiasz się na projektowaniu niż na implementacji. Im bardziej twoje projekty pozostawiają oddech dla odpowiednich optymalizacji później bez zmian w projekcie, tym później możesz zoptymalizować. Coraz więcej produktywności zyskałem, szukając takich projektów, które pozwalają mi oddychać.
Zaprojektuj, które oferują pokój oddechowy do późniejszej optymalizacji
Tego rodzaju projekty w rzeczywistości nie są trudne do osiągnięcia w większości przypadków, jeśli możemy zastosować „zdrowy rozsądek”. Jako osobista historia zajmuję się sztukami wizualnymi jako hobby (uważam, że w pewnym stopniu pomaga to programować artystów, którzy sami rozumieją ich potrzeby i mówią w ich języku) i spędziłem trochę czasu na początku 2000 roku, używając apletów Oekaki online jako szybki sposób na doodle i udostępnianie mojej pracy oraz kontakt z innymi artystami.
W szczególności moja ulubiona strona i aplet były usiane wadami wydajnościowymi (każdy nietrywialny rozmiar pędzla spowolniłby do indeksowania), ale miał bardzo miłą społeczność. Aby obejść problemy z wydajnością, użyłem malutkich pędzli 1 lub 2-pikselowych i po prostu zapisałem moją pracę w ten sposób:
W międzyczasie ciągle dawałem autorowi sugestie oprogramowania w celu poprawy wydajności, a on zauważył, że moje sugestie mają szczególnie techniczny charakter, mówiąc o optymalizacji pamięci i algorytmach i tak dalej. Więc właściwie zapytał, czy jestem programistą, a ja odpowiedziałem tak i zaprosił mnie do pracy nad kodem źródłowym.
Więc spojrzałem na kod źródłowy, uruchomiłem go, profilowałem i ku mojemu przerażeniu zaprojektował oprogramowanie wokół koncepcji „abstrakcyjnego interfejsu pikselowego”, na przykład
IPixel
, który stał się główną przyczyną gorących miejsc dla wszystkiego z dynamiką przydziały i wysyłka dla każdego piksela każdego obrazu. Jednak nie było praktycznego sposobu na zoptymalizowanie tego bez ponownego przemyślenia całego projektu oprogramowania, ponieważ projekt uwięził go w kącie, w którym nie ma nic poza najbardziej trywialnymi mikrooptymalizacjami, gdy nasze abstrakcje działają na poziomie ziarnistym pojedynczego abstrakcyjnego piksela i wszystko zależy od tego abstrakcyjnego piksela.Myślę, że jest to naruszenie „zdrowego rozsądku”, ale oczywiście nie było to takie rozsądne dla dewelopera. Ale to tak, jakby nie abstrakcjonować rzeczy na tak szczegółowym poziomie, w którym miliony będą tworzyć nawet najbardziej podstawowe przypadki użycia, takie jak piksele, cząstki lub małe jednostki w gigantycznej symulacji armii. Faworyzuj
IImage
(możesz obsłużyć wszystkie potrzebne formaty obrazów / pikseli na tym większym zbiorczym poziomie) lubIParticleSystem
doIPixel
lubIParticle
, a następnie możesz wprowadzić najbardziej podstawowe i szybkie do napisania i łatwe do zrozumienia implementacje za takimi interfejsami i mieć całą przestrzeń do oddychania, którą trzeba będzie później zoptymalizować bez ponownego rozważania projektu całego oprogramowania.I taki jest cel, jaki widzę obecnie. Z wyłączeniem szczególnych przypadków, takich jak renderery offline powyżej, projektuj z wystarczającą ilością miejsca do oddychania, aby zoptymalizować jak najdłużej, z możliwie największą ilością informacji z perspektywy czasu (w tym pomiarów), i zastosuj wszelkie niezbędne optymalizacje tak późno, jak to możliwe.
Oczywiście niekoniecznie sugeruję zacząć od użycia algorytmów złożoności kwadratowej na wejściach, które łatwo osiągają niebanalny rozmiar w typowych przypadkach użytkowników końcowych. Kto to robi? Ale nawet nie sądzę, że jest to taka wielka sprawa, jeśli wdrożenie można łatwo wymienić później. To nadal nie jest poważny błąd, jeśli nie musisz ponownie rozważać żadnych projektów.
źródło
To zależy od tego, co ta wydajność oznacza dla twojej aplikacji. I czy możliwe jest nawet zoptymalizowanie wydajności, zanim aplikacja zakończy się funkcjonalnie.
Najczęściej nie powinieneś się tym przejmować, dopóki nie będziesz miał nic lepszego do roboty, ale może być tak, że pewien poziom wydajności ma kluczowe znaczenie dla powodzenia Twojej aplikacji. Gdyby tak było i podejrzewasz, że może to nie być łatwe, powinieneś zacząć patrzeć na wydajność ze względu na „szybkie zawodzenie”.
Ważną zasadą w każdym projekcie jest skupienie się na twardych częściach. W ten sposób, jeśli okaże się, że nie możesz tego zrobić, będziesz wiedział wcześniej i będzie czas na wypróbowanie czegoś zupełnie innego lub projekt może zostać anulowany, zanim zostanie na to zbyt wiele wydane.
źródło
Mam zamiar zasugerować, że wydajność to coś więcej niż prędkość. Obejmuje skalę (setki do tysięcy jednoczesnych użytkowników). Na pewno nie chcesz, aby aplikacja zaczęła tankować, gdy otrzyma obciążenie produkcyjne. Wydajność obejmuje ilość zasobów (np. Pamięci) zużywanych przez aplikację.
Wydajność to także łatwość użycia. Niektórzy użytkownicy wolą, aby 1 naciśnięcie klawisza wykonało zadanie w 10 sekund, niż 2 naciśnięcia klawisza wykonały zadanie w ciągu 1 sekundy. O takie rzeczy zapytaj kierownika projektu. Nie lubię wcześniej tego robić użytkownikom. W próżni mogą powiedzieć X, ale kiedy pracują z funkcjonalnym wstępnym wydaniem, mogą powiedzieć Y.
Najlepszą indywidualną prędkością jest utrzymanie zasobu, takiego jak połączenie z bazą danych. Ale dla wagi powinieneś uzyskać połączenie tak późno, jak to możliwe i zwolnić go tak szybko, jak to możliwe. Jedna podróż do bazy danych w celu uzyskania 3 rzeczy jest szybsza niż 3 osobne wycieczki do bazy danych.
Czy podróżujesz po informacje, które nie zmieniają się podczas sesji. Jeśli tak, weź go na początku sesji i przytrzymaj, to pamięć.
Wybierając typ kolekcji, weź pod uwagę funkcjonalność, szybkość i rozmiar.
Czy na pewno musisz przechowywać przedmioty w kolekcji? Częstym problemem jest wczytywanie wszystkich linii z pliku do listy, a następnie przetwarzanie listy pojedynczo. Znacznie wydajniej jest czytać plik po jednym wierszu i pomijać listę.
Zapętlasz trzy razy, kiedy możesz zapętlić raz i zrobić trzy rzeczy.
Czy jest miejsce, w którym może być konieczne przetworzenie innego wątku z oddzwanianiem. Jeśli tak, spakuj kod z uwzględnieniem tej możliwej potrzeby, jeśli nie koliduje on z bezpośrednimi potrzebami projektowymi.
Duża wydajność to także czysty kod.
Istnieje przedwczesna optymalizacja i po prostu robi się zdrowy rozsądek, co tak naprawdę nie zajmuje więcej czasu.
W bazie danych widzę przedwczesną optymalizację. Odnormalizuje prędkość, zanim wystąpi problem z prędkością. Argument, który otrzymuję, jest taki, że jeśli później zmienimy tabelę, musimy wszystko zmienić. Często można utworzyć widok prezentujący dane w ten sposób i być może trzeba będzie później zamienić go na zdenormalizowaną tabelę.
źródło