Po przyjrzeniu się trochę optymalizacji, odkryłem (dosłownie wszędzie), że zbyt wcześnie optymalizacja gry wydaje się być powszechnie uznanym grzechem.
Naprawdę tego nie rozumiem, czy nie byłoby niewiarygodnie trudno zmienić niektóre podstawowe struktury gry na końcu, zamiast rozwijać je po raz pierwszy z myślą o wydajności?
Dostaję to, że czekanie, aż gra się zakończy, powie ci, czy w ogóle potrzebujesz optymalizacji, ale czy nie powinieneś tego zrobić, w końcu może poszerzyć różnorodność urządzeń, na których gra może działać, co zwiększy liczbę potencjalnych gracze.
Czy ktoś mógłby mi wyjaśnić, dlaczego zbyt zły pomysł na optymalizację zbyt wcześnie?
performance
optimization
mr-matt
źródło
źródło
Odpowiedzi:
Preambuła:
W komentarzach zgłoszono kilka zastrzeżeń i myślę, że w dużej mierze wynikają one z niezrozumienia tego, co mamy na myśli, gdy mówimy „przedwczesna optymalizacja” - dlatego chciałem dodać trochę wyjaśnienia na ten temat.
„Nie optymalizuj przedwcześnie” nie oznacza „pisz kod, o którym wiesz, że jest zły, ponieważ Knuth twierdzi, że nie możesz go wyczyścić do końca”
Oznacza to, że „nie poświęcaj czasu i czytelności na optymalizację, dopóki nie dowiesz się, które części twojego programu rzeczywiście potrzebują pomocy, by być szybszym”. Ponieważ typowy program spędza większość czasu w kilku wąskich gardłach, inwestowanie w optymalizację „wszystkiego” może nie dać takiego samego przyspieszenia, jak skupienie tej samej inwestycji tylko na wąskim kodzie.
Oznacza to, że w razie wątpliwości powinniśmy:
Preferuj kod, który jest prosty do napisania, zrozumiały i łatwy do modyfikacji na początek
Sprawdź, czy potrzebna jest dalsza optymalizacja (zwykle poprzez profilowanie działającego programu, chociaż jeden komentarz poniżej zauważa analizę matematyczną - jedyne ryzyko, które musisz sprawdzić, czy matematyka jest poprawna)
Przedwczesna optymalizacja to nie :
Architektoniczne decyzje dotyczące struktury kodu w sposób dostosowujący się do twoich potrzeb - rozważne wybranie odpowiednich modułów / obowiązków / interfejsów / systemów komunikacji.
Proste wydajności, które nie wymagają dodatkowego czasu lub utrudniają odczytanie kodu. Używanie silnego pisania może być zarówno wydajne, jak i wyraźne. Kolejnym przykładem jest buforowanie referencji zamiast jej wielokrotnego wyszukiwania (o ile twoja sprawa nie wymaga skomplikowanej logiki unieważniania pamięci podręcznej - być może wstrzymasz się z pisaniem tego, dopóki nie profilujesz najpierw w prosty sposób).
Korzystanie z właściwego algorytmu dla zadania. * Jest bardziej optymalny i bardziej złożony niż wyczerpujące przeszukiwanie wykresu ścieżki. To także standard branżowy. Powtarzanie tematu, stosowanie sprawdzonych metod takich jak ten może faktycznie ułatwić zrozumienie kodu, niż jeśli robisz coś prostego, ale sprzecznego ze znanymi najlepszymi praktykami. Jeśli masz doświadczenie w napotykaniu wąskich gardeł we wdrażaniu funkcji gry X w jeden sposób w poprzednim projekcie, nie musisz ponownie uderzać w to samo wąskie gardło w tym projekcie, aby wiedzieć, że to prawda - możesz i powinieneś ponownie użyć rozwiązań, które działały w przeszłości Gry.
Wszystkie te typy optymalizacji są dobrze uzasadnione i na ogół nie byłyby oznaczone jako „przedwczesne” (chyba że wybierasz się do króliczej nory i wdrażasz najnowocześniejsze ścieżki wyszukiwania dla twojej mapy szachownicy 8x8 ...)
Teraz wyjaśniono, dlaczego ta polityka może być przydatna w grach:
Szczególnie w gamedev szybkość iteracji jest najcenniejszą rzeczą. Często wdrażamy i wdrażamy o wiele więcej pomysłów, niż ostatecznie dostarczymy z gotową grą, starając się „znaleźć zabawę”.
Jeśli potrafisz prototypować mechanika w prosty i może nieco naiwny sposób i testujesz go następnego dnia, jesteś w znacznie lepszej sytuacji, niż gdybyś spędził tydzień, tworząc najpierw najbardziej optymalną wersję. Zwłaszcza, jeśli okaże się, że jest do bani, a wyrzucicie tę funkcję. Wykonanie tego w prosty sposób, abyś mógł wcześnie przetestować, może zaoszczędzić mnóstwo marnowanej pracy, optymalizując niepotrzebny kod.
Niezoptymalizowany kod jest również ogólnie łatwiejszy do zmodyfikowania i wypróbowania różnych wariantów niż kod, który jest precyzyjnie dostrojony do robienia jednej precyzyjnej rzeczy optymalnie, która jest krucha i trudniejsza do modyfikacji bez jej łamania, wprowadzania błędów lub spowalniania. Dlatego utrzymanie prostoty i łatwości zmiany kodu jest często warte niewielkiej nieefektywności w czasie wykonywania przez większość prac programistycznych (zwykle pracujemy na komputerach powyżej specyfikacji docelowej, abyśmy mogli wchłonąć koszty ogólne i skupić się na uzyskaniu docelowego doświadczenia), dopóki nie zablokowaliśmy to, czego potrzebujemy od tej funkcji, i możemy zoptymalizować części, o których wiemy, że są wolne.
Tak, refaktoryzacja części projektu na późnym etapie rozwoju w celu optymalizacji wolnych miejsc może być trudna. Ale tak samo jest w trakcie opracowywania aplikacji, ponieważ optymalizacje, które wprowadziłeś w zeszłym miesiącu, nie są zgodne z kierunkiem rozwoju gry od tego czasu lub naprawiały coś, co okazało się nie być prawdziwym wąskim gardłem, gdy uzyskasz więcej funkcji i treści w.
Gry są dziwne i eksperymentalne - trudno przewidzieć, jak ewoluuje projekt gry i jego potrzeby techniczne oraz gdzie wydajność będzie najściślejsza. W praktyce często martwimy się niewłaściwymi rzeczami - poszukaj tutaj pytań o wydajność, a zobaczysz wspólny motyw twórców rozpraszanych przez rzeczy na papierze, które prawdopodobnie nie stanowią żadnego problemu.
Weźmy na przykład dramatyczny przykład: jeśli twoja gra jest związana z GPU (nierzadko), cały ten czas poświęcony hiperoptymalizacji i wątkowi pracy procesora może nie przynieść żadnych wymiernych korzyści. Wszystkie te godziny deweloperskie można by zamiast tego poświęcić na wdrożenie i dopracowanie funkcji gry, aby uzyskać lepsze wrażenia z gry.
Ogólnie rzecz biorąc, większość czasu spędzonego na pracy nad grą nie zostanie przeznaczona na kod, który ostatecznie będzie wąskim gardłem. Szczególnie, gdy pracujesz nad istniejącym silnikiem, bardzo drogie pętle wewnętrzne w systemach renderowania i fizyki są w dużej mierze poza twoimi rękami. W tym momencie Twoim zadaniem w skryptach rozgrywki jest po prostu trzymanie się z dala od silnika - dopóki nie wrzucisz w to klucza, prawdopodobnie wyjdziesz całkiem dobrze na pierwszą kompilację.
Więc oprócz odrobiny higieny i budżetowania (np. Nie wyszukuj wielokrotnie / konstruuj rzeczy, jeśli możesz je łatwo ponownie użyć, zachowaj skrupulatne zapytania / fizyki lub odczyty GPU skromne itp.), Nawyk nie przesadzania - optymalizacja, zanim dowiemy się, gdzie są prawdziwe problemy, okazuje się być korzystna dla produktywności - oszczędzając nam marnowania czasu na optymalizację niewłaściwych rzeczy, a także utrzymując nasz kod prostszy i łatwiejszy do ulepszenia.
źródło
uwaga: ta odpowiedź zaczęła się jako komentarz do odpowiedzi DMGregory, więc nie powiela ona bardzo dobrych punktów, które wysuwa.
„Czy nie byłoby niewiarygodnie trudne zmienić niektóre podstawowe struktury gry na końcu, zamiast rozwijać je po raz pierwszy z myślą o wydajności?”
To jest dla mnie sedno pytania.
Tworząc oryginalny projekt, powinieneś starać się projektować pod kątem wydajności - na najwyższym poziomie. Jest to mniej optymalizacji, a więcej o strukturze.
Przykład:
Musisz stworzyć system przekraczania rzeki. Oczywistymi projektami są most lub prom, więc który wybierasz?
Odpowiedź zależy oczywiście od wielkości przejazdu i natężenia ruchu. To nie jest optymalizacja, zamiast tego zaczyna się od projektu odpowiedniego dla twojego problemu.
Kiedy pojawi się wybór projektu, wybierasz ten, który najlepiej pasuje do tego, co chcesz zrobić.
Załóżmy więc, że nasz ruch jest dość niski, dlatego postanowiliśmy zbudować dwa terminale i kupić prom, aby obsłużyć ruch. Ładna prosta implementacja
Niestety, kiedy już ją uruchomimy, stwierdzimy, że ruch jest większy niż oczekiwano. Musimy zoptymalizować prom! (ponieważ to działa, a budowanie mostu nie jest teraz dobrym planem)
Opcje:
W tym miejscu powinieneś spróbować uczynić swój oryginalny projekt tak modularnym, jak to możliwe.
Wszystkie powyższe są możliwymi optymalizacjami, a nawet możesz zrobić wszystkie trzy.
Ale jak wprowadzić te zmiany bez dużych zmian strukturalnych?
Jeśli masz modułową konstrukcję z jasno określonymi interfejsami, wdrożenie tych zmian powinno być proste.
Jeśli kod nie jest ściśle powiązany, zmiany w modułach nie wpływają na otaczającą strukturę.
Rzućmy okiem na dodanie dodatkowego promu.
„Zły” program mógłby zostać zbudowany wokół idei pojedynczego promu i miałby stany dokowania oraz stan promu i pozycję wszystkie połączone razem i stan współdzielenia. Będzie to trudne do zmodyfikowania, aby umożliwić dodanie dodatkowego promu do systemu.
Lepszym rozwiązaniem byłoby posiadanie doków i promów jako osobnych jednostek. Nie ma między nimi żadnego ścisłego połączenia, ale mają interfejs, do którego prom może przybyć, rozładować pasażerów, przyjąć nowych i wyjść. Dok i prom współużytkują tylko ten interfejs, co ułatwia wprowadzanie zmian w systemie, w tym przypadku poprzez dodanie drugiego promu. Dok nie dba o to, jakie promy są w rzeczywistości, chodzi tylko o to, że coś (cokolwiek) korzysta z jego interfejsu.
tl; dr:
Następnie możesz zmienić mechanizmy w każdym module bez konieczności restrukturyzacji całej bazy kodu, gdy trzeba zoptymalizować.
źródło
IRiverCrossing
, a gdy stanie się jasne, że natężenie ruchu jest zbyt duże, aby ustawić prom, zaimplementuj mostIRiverCrossing
i zrzuć go. Cała rzecz polega oczywiście na zmniejszeniu zewnętrznego interfejsu API promu i most do wspólnej funkcjonalności, aby mogły być reprezentowane przez ten sam interfejs.„Nie optymalizuj wcześnie” nie oznacza „wybierz najgorszy możliwy sposób”. Nadal musisz wziąć pod uwagę wpływ na wydajność (chyba że tylko prototypujesz). Nie chodzi o to, aby okaleczyć inne, ważniejsze rzeczy na tym etapie rozwoju - takie jak elastyczność, niezawodność itp. Wybierz proste, bezpieczne optymalizacje - wybierz rzeczy, które ograniczasz, i rzeczy, które pozostawiasz za darmo; śledzić koszty. Czy powinieneś używać silnego pisania? Większość gier działała i działa dobrze; ile kosztowałoby to usunięcie, gdybyś znalazł ciekawe zastosowania elastyczności w rozgrywce?
Znacznie trudniej jest zmodyfikować zoptymalizowany kod, zwłaszcza kod „inteligentny”. Zawsze jest to wybór, który czyni niektóre rzeczy lepszymi, a inne gorszymi (na przykład możesz handlować czasem procesora na zużycie pamięci). Dokonując takiego wyboru, musisz zdawać sobie sprawę ze wszystkich implikacji - mogą być katastrofalne, ale mogą być również pomocne.
Na przykład Commander Keen, Wolfenstein i Doom zostały zbudowane na zoptymalizowanym silniku renderującym. Każdy z nich miał swoją „sztuczkę”, dzięki której gra istniała w pierwszej kolejności (z czasem opracowano także dalsze optymalizacje, ale nie jest to tutaj ważne). To dobrze . Dobrze jest zoptymalizować sam rdzeń gry, myśl, która umożliwia grę; szczególnie jeśli eksplorujesz nowe terytorium, gdzie ta szczególna zoptymalizowana funkcja pozwala rozważyć projekty gier, które nie były zbytnio badane. Ograniczenia, które wprowadza optymalizacja, mogą również dać ci interesującą rozgrywkę (np. Limity liczby jednostek w grach RTS mogły zacząć jako sposób na poprawę wydajności, ale mają również wpływ na rozgrywkę).
Pamiętaj jednak, że w każdym z tych przykładów gra nie mogłaby istnieć bez optymalizacji. Nie wystartowali z „w pełni zoptymalizowanym” silnikiem - zaczęli od absolutnej konieczności i ruszyli w górę. Opracowywali nowe technologie i używali ich do tworzenia zabawnych gier. A sztuczki silnika ograniczono do jak najmniejszej części bazy kodu - cięższe optymalizacje wprowadzono tylko wtedy, gdy rozgrywka była w większości ukończona lub tam, gdzie pozwoliła na pojawienie się ciekawej nowej funkcji.
Teraz rozważ grę, którą możesz chcieć zrobić. Czy naprawdę jest jakiś technologiczny cud, który tworzy lub psuje tę grę? Może planujesz grę w otwartym świecie w nieskończonym świecie. Czy to naprawdę centralny element gry? Czy gra po prostu nie działałaby bez niego? Może myślisz o grze, w której teren jest odkształcalny bez ograniczeń, z realistyczną geologią i tym podobne; czy możesz sprawić, by działał z mniejszym zakresem? Czy działałoby to w 2D zamiast 3D? Jak najszybciej uzyskaj coś dobrej zabawy - nawet jeśli optymalizacja może wymagać przerobienia dużej części istniejącego kodu, być może warto; a może nawet zdasz sobie sprawę, że powiększanie rzeczy tak naprawdę nie poprawia gry.
Jako przykład ostatniej gry z wieloma optymalizacjami wskazałbym Factorio. Jedną z kluczowych części gry są pasy - jest ich wiele tysięcy i zawierają wiele pojedynczych kawałków materiałów w całej fabryce. Czy gra zaczęła się od mocno zoptymalizowanego silnika pasowego? Nie! W rzeczywistości oryginalna konstrukcja paska była prawie niemożliwa do zoptymalizowania - w pewnym sensie wykonała fizyczną symulację przedmiotów na pasku, co stworzyło kilka interesujących rzeczy, które możesz zrobić (w ten sposób uzyskujesz „wschodzącą” rozgrywkę - rozgrywka, która zaskakuje projektant), ale oznaczało to, że musiałeś zasymulować każdy element na pasku. Dzięki tysiącom pasków otrzymujesz dziesiątki tysięcy symulowanych fizycznie przedmiotów - nawet samo ich usunięcie i pozwolenie pasom na wykonanie pracy pozwala skrócić związany z tym czas procesora o 95-99%, nawet bez uwzględnienia takich rzeczy jak lokalizacja pamięci. Ale warto to zrobić tylko wtedy, gdy faktycznie osiągniesz te limity.
Prawie wszystko, co miało coś wspólnego z pasami, musiało zostać przerobione, aby umożliwić optymalizację pasów. Pasy musiały zostać zoptymalizowane, ponieważ potrzebowaliśmy dużo pasów do dużej fabryki, a duże fabryki to jedna atrakcja gry. W końcu jeśli nie możesz mieć dużych fabryk, dlaczego masz nieskończony świat? Zabawne, że powinieneś zapytać - wczesne wersje tego nie zrobiły :) Gra została przerobiona i wielokrotnie przekształcana, aby dotrzeć tam, gdzie są teraz - w tym 100% remake, gdy zdali sobie sprawę, że Java nie jest dobrym rozwiązaniem taka gra i przeszła na C ++. I zadziałało świetnie dla Factorio (chociaż nadal dobrze było, że nie było zoptymalizowane od samego początku - zwłaszcza, że był to projekt hobbystyczny, który w przeciwnym razie mógłby się nie udać z powodu braku zainteresowania).
Ale chodzi o to, że sąwiele rzeczy, które możesz zrobić z fabryką o ograniczonym zasięgu - i wiele gier właśnie to pokazało. Granice mogą być jeszcze bardziej inspirujące dla zabawy niż wolności; czy Spacechem byłby bardziej zabawny, gdyby „mapy” były nieskończone? Gdybyście zaczęli od mocno zoptymalizowanych „pasów”, bylibyście zmuszeni pójść tą drogą; i nie mogłeś odkryć innych kierunków projektowania (np. zobaczyć, co ciekawego możesz zrobić z symulowanymi fizycznie taśmami przenośnikowymi). Ograniczasz swoją potencjalną przestrzeń projektową. Może się tak nie wydawać, ponieważ nie widzisz wielu niedokończonych gier, ale trudność polega na zapewnieniu dobrej zabawy - na każdą zabawną grę, którą widzisz, prawdopodobnie są setki, które po prostu nie mogły się tam dostać i zostały złomowane (lub gorzej, wydany jako okropne bałagany). Jeśli optymalizacja ci to pomoże - śmiało. Jeśli nie ... to prawdopodobnie przedwczesne. Jeśli uważasz, że jakaś mechanika gry działa świetnie, ale potrzebuje optymalizacji, aby naprawdę zabłysnąć - śmiało. Jeśli nie masz ciekawej mechaniki,nie optymalizuj ich . Najpierw znajdź zabawę - przekonasz się, że większość optymalizacji nie pomaga w tym i często jest szkodliwa.
Wreszcie masz świetną, zabawną grę. Czy warto teraz optymalizować ? Ha! To wciąż nie jest tak jasne, jak mogłoby się wydawać. Czy jest coś zabawnego?możesz zamiast tego zrobić? Nie zapomnij, że Twój czas jest nadal ograniczony. Wszystko wymaga wysiłku, a Ty chcesz skoncentrować się na tym, co najważniejsze. Tak, nawet jeśli tworzysz „darmową grę” lub grę „open source”. Zobacz, jak gra się w tę grę; zauważ, gdzie wydajność staje się wąskim gardłem. Czy optymalizacja tych miejsc sprawia więcej radości (jak budowanie coraz większych, coraz bardziej splątanych fabryk)? Czy pozwala to przyciągnąć więcej graczy (np. Słabszymi komputerami lub na różnych platformach)? Zawsze musisz ustalić priorytety - poszukaj stosunku wysiłku do wydajności. Prawdopodobnie znajdziesz wiele nisko wiszących owoców, po prostu grając w grę i obserwując, jak inni w nią grają. Ale zwróć uwagę na ważną część - aby się tam dostać, potrzebujesz gry . Skoncentruj się na tym.
Podsumowując, weź pod uwagę, że optymalizacja nigdy się nie kończy. To nie jest zadanie z małym znacznikiem wyboru, który kończysz i przechodzisz do innych zadań. Zawsze można zrobić „jeszcze jedną optymalizację”, a dużą część każdego projektu stanowi zrozumienie priorytetów. Nie robisz optymalizacji ze względu na optymalizację - robisz to, aby osiągnąć określony cel (np. „200 jednostek na ekranie jednocześnie na Pentium 333 MHz” to świetny cel). Nie trać tropu celu końcowego tylko dlatego, że zbytnio koncentrujesz się na celach pośrednich, które mogą nawet nie być warunkiem wstępnym dla celu końcowego.
źródło
Wydaje się, że wiele odpowiedzi skupia się na aspekcie wydajności „optymalizacji”, podczas gdy ja lubię patrzeć na optymalizację i całą próbę optymalizacji zbyt wcześnie na bardziej abstrakcyjnym poziomie.
Humor mnie, gdy staram się rozwinąć moją perspektywę za pomocą poliominoes.
Załóżmy, że mamy ustalone granice określone przez platformę lub silnik, z którym pracujemy.
Następnie przystępujemy do tworzenia pierwszej warstwy / modułu gry.
Idąc dalej, budujemy naszą drugą warstwę / moduł.
W tym momencie możemy zauważyć, że między dwoma modułami jest trochę miejsca i możemy ulec pokusie zoptymalizowania go, aby w pełni wykorzystać przydzielone nam granice.
Idealnie, teraz aplikacja w pełni wykorzystuje dostępne nam zasoby, aplikacja jest lepsza, dobrze, prawda?
Kontynuujemy budowę trzeciej warstwy / modułu naszej aplikacji i nagle dochodzimy do wniosku (być może nawet takiego, którego nie moglibyśmy przewidzieć podczas wstępnego planowania), że trzecia warstwa / moduł nie działa dla nas.
Szukamy alternatywy, znajdujemy ją, a na koniec wymaga to również zmiany drugiego modułu naszej aplikacji, ponieważ jest on niezgodny z naszym nowo wybranym trzecim modułem. (Na szczęście jest nieco kompatybilny z naszym pierwszym modułem, więc nie musimy przepisywać wszystkiego od nowa).
Więc złożyliśmy to wszystko razem ...
Hmm, widzisz co się stało?
Optymalizując zbyt wcześnie, poprawiliśmy efektywność, ponieważ optymalizacja nie jest tym, co zakończyliśmy.
A jeśli chcielibyśmy później dodać dodatkowe moduły lub dodatkowe ciekawostki, moglibyśmy już nie mieć możliwości ich wykonania w tym momencie.
A dostosowanie najniższego poziomu naszego systemu nie jest już tak wykonalne, ponieważ został on pochowany pod wszystkimi innymi warstwami.
Gdybyśmy jednak zdecydowali się poczekać z chęcią zoptymalizowania go natychmiast, otrzymalibyśmy coś takiego:
A teraz, jeśli przeprowadzimy optymalizację w tym momencie, otrzymamy coś satysfakcjonującego.
Mam nadzieję, że przynajmniej niektórzy z was czytali to tak dobrze, jak ja to robiłem :) i jeśli teraz macie wrażenie, że lepiej rozumiecie ten temat - tym lepiej.
źródło
Pieniądze.
Wszystko sprowadza się do tego. Pieniądze. Ponieważ czas to pieniądz *, im więcej czasu poświęcisz na działania, które nie gwarantują wygenerowania większej ilości pieniędzy (tj. Nie możesz traktować tych działań jako inwestycji ), tym więcej pieniędzy ryzykujesz zmarnowaniem i tym mniej pieniędzy zarobisz dzięki gra.
Oto kilka potencjalnych skutków ubocznych zbyt wczesnej optymalizacji i powody, dla których należy tego unikać:
* Inne odpowiedzi wystarczająco dobrze podkreśliły część dotyczącą „czasu”
Na marginesie, ogólnie rzecz biorąc , doświadczenie pomaga określić, co jest, a co nie jest przedwczesną optymalizacją i co ma wartość dla firmy, a co nie.
Na przykład, jeśli pracowałeś nad grą A i pod koniec projektu zdałeś sobie sprawę, że funkcja XYZ była szczególnie obciążona w twojej pętli, i ostatecznie zaczynasz pracę nad grą B, która ma dokładnie tę samą funkcję, decydując się na przepisz tę funkcję i optymalizacja od samego początku nie jest tak naprawdę przedwczesną optymalizacją, ponieważ wiesz, że będzie to wąskie gardło, jeśli nic nie zostanie zrobione.
źródło
Optymalizacja jest z definicji procesem zwiększania wydajności rozwiązania do momentu, w którym traci on swoją skuteczność. Proces ten oznacza następnie zmniejszenie przestrzeni rozwiązania.
Na wczesnym etapie tworzenia oprogramowania nadal mogą istnieć „ukryte wymagania”: jeśli zbytnio zmniejszysz przestrzeń swojego rozwiązania, możesz skończyć w sytuacji, w której nie będziesz w stanie spełnić „ukrytego wymagania”, gdy się pojawi. na późniejszym etapie rozwoju, zmuszając cię do modyfikacji architektury, dodając w ten sposób niestabilność i możliwą masę niepożądanych zachowań.
Chodzi o to, aby całe rozwiązanie działało, a dopiero wtedy, gdy wszystkie wymagania zostaną ustalone i zaimplementowane, zaostrz kod. Zobaczysz wtedy, że wiele optymalizacji, które bezproblemowo wdrożysz od razu podczas kodowania, nie są już możliwe z powodu interakcji z późnymi wymaganiami.
Rzeczywista przestrzeń rozwiązania jest zawsze większa niż ta, której oczekujemy na początku, ponieważ nie możemy mieć doskonałej wiedzy o bardzo złożonym systemie.
Spraw, by działało pierwsze. Następnie napnij liny.
źródło
Krótko mówiąc, bardzo często wczesna optymalizacja staje się zmarnowanym wysiłkiem, jeśli chcesz zmienić rzeczy później, a potem okazuje się, że zoptymalizowałeś łatwo zmienialne struktury kodu na coś znacznie niższego poziomu, a teraz musisz zmienić go z powrotem na wysoki podejście do poziomu i ponownie zoptymalizuj wynik.
Jest to powszechny błąd dla początkujących programistów, którzy lubią skupiać się na czerpaniu przyjemności z „wykonywania użytecznej pracy”, takiej jak optymalizacja, nie zastanawiając się, czy jest to właściwy moment, aby to zrobić. W miarę zdobywania doświadczenia w programowaniu dużych projektów, takich jak gry, dowiesz się, kiedy jest to uzasadnione, aby zoptymalizować istniejącą bazę kodów, a kiedy będzie za wcześnie. Nie bój się popełnić tego błędu, skorzystasz tylko z nauki.
Zasadniczo optymalizuj tylko, jeśli naprawdę nie możesz pracować z kompilacją programistyczną w tym momencie. Na przykład, jeśli tworzysz i usuwasz miliony obiektów 60 razy na sekundę.
Tak więc powiedziałbym, że warto, jeśli chodzi o doświadczenie uczenia się, optymalizować kilka razy wcześniej: str
źródło
Optymalizacja koncentruje się na tym, aby komputer działał najlepiej na kodzie, podczas gdy programowanie wymaga, aby programista działał najlepiej na kodzie.
Optymalizacja nie zapewnia wglądu. To sprawia, że komputer działa mniej, a programista więcej.
Oczywiście istnieją różne kategorie, na przykład przy projektowaniu samochodu. Nie ma nic złego w optymalizacji silnika przed zbudowaniem pierwszego podwozia, ale optymalizacja podwozia, zanim nie wiadomo, jaki kształt ma silnik, może skończyć się stratą czasu. Modułowość i specyfikacje mogą zapewnić wiele miejsc wykonalnych do prac optymalizacyjnych, nawet zanim produkt jako całość zostanie zmontowany.
źródło
Zdecydowanie nie zgadzam się ze wszystkimi tymi stwierdzeniami, że kodu nie należy optymalizować na wczesnych etapach. To zależy od tego, na jakim etapie jesteś. Jeśli jest to MVP - prototyp, a ty po prostu starasz się spojrzeć na grę, która zajmuje od 1 do 2 tygodni, że jesteś gotowy przepisać wszystko, co już napisałeś. Tak, optymalizacja nie ma znaczenia. Ale jeśli już pracujesz nad grą, o której wiesz, że zostanie wydana, powinna ona cały czas mieć zoptymalizowany kod. Opowieści, które ludzie mówią o nowych funkcjach i rzeczach, które można dodać, są nieporozumieniem. Jest to źle zaprojektowana architektura kodu zamiast kodu zoptymalizowanego. Nie musisz niczego przepisywać, aby dodać nowe elementy, jeśli masz ładny design kodu.
Na przykład, jeśli masz algorytm wyszukiwania ścieżki A *, czy nie lepiej byłoby napisać go w najbardziej optymalny sposób? Zamiast później zmienić połowę posiadanego kodu, ponieważ musiałeś wprowadzić pewne zmiany w algorytmie, ponieważ teraz potrzebuje on innych wywołań metod i wywołań zwrotnych? A jeśli masz już zoptymalizowany kod od samego początku, zaoszczędzi ci to dużo czasu. Ponieważ możesz narysować relacje między obiektami i sposób ich interakcji, zamiast ślepo tworzyć mnóstwo nowych skryptów i od razu nawiązywać wszystkie połączenia - prowadzi to do niejasnego kodu sfagetti.
Ostatnią rzeczą, którą chcę dodać, jest to, że później, nawet jeśli nie chcesz już tworzyć gry, masz zoptymalizowany algorytm A *, którego możesz użyć do następnych gier. Wielokrotnego użytku. Na przykład wiele gier ma inwentaryzację, wyszukiwanie ścieżek, generowanie procedur, interakcje między NPC, systemem walki, AI, interakcją interfejsu, zarządzaniem danymi wejściowymi. Teraz powinieneś zadać sobie pytanie: „Ile razy przepisałem te elementy od zera?” Stanowią one 70–80% gry. Czy naprawdę musisz je ciągle przepisywać? A jeśli nie zostaną zoptymalizowane?
źródło