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) lub IParticleSystem
do IPixel
lub IParticle
, 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.