Możesz podać jakiś konkretny przykład utrudniania życia prze GC? Pracuje z różnymi językami programowania, ale głównie z Javą i GC nigdy mi życia nie utrudniał osobiście.
Przy tym co robisz zapewne garbage collector nie sprawia problemów, bo to są pewnie jakieś użytkowe, może serwerowe rozwiązania w których nie ma znaczenia, że nagle jeden rdzeń przymuli na 1/30 sekundy. Ja niestety miałem nieprzyjemność zetknąć się z GC w czymś co musiało koniecznie być płynne i takie nieprzewidywalne przerwy na zwolnienie śmieci bardzo widocznie wpływały na całość. Zaznaczam, że to było dawniej, gdy sprzęt nie był tak absurdalnie szybki jak dzisiaj i przede wszystkim procesory były jednordzeniowe.
Przypadek 1
Dawno temu, w czasach pierwszego publicznego Androida (HTC G1 z Androidem 1.3), chwilowo brałem udział w portowaniu jakiejś tetrisopodobnej gry z Java2ME na tego Androida. No i nawet jakoś to poszło ale widać było, że klocki czasem na ułamek sekundy się zatrzymują. Okazało się, że to był moment działania GC. Byłem przy tym zadaniu tylko chwilę ale z tego co wiem tak to zostawiono, bo nie znaleziono na to lekarstwa. Ja w tym czasie pisałem dla telefonów z Mophunem, które były wielokrotnie słabsze, a programy działały szybciej i bez niespodzianek, bo to był natywny kod C.
Przypadek 2
Miałem taki okres w życiu (po epoce Java2ME/Symbian, a przed epoką iOS/Android) w którym próbowałem coś zrobić na Xbox Live Arcade. To były takie (sprzedawane tylko online) małe (początkowo chyba do 40MB) gry dla Xbox 360). Nie lubię używać cudzych silników, a wtedy Microsoft promował XNA, przysięgając, że kiedyś zastąpi DirectX (a właściwie go nadbuduje). Pisało się tam to w C# więc szybko usiadłem do poznania podstaw tego języka. Wtedy istniało jeszcze takie świetne forum twórców gier forum.warsztat.gd. Było tam sporo pomocnych ludzi (np. znany dzisiaj w amigowym świecie twórca Dreada), którzy jeszcze wtedy potrafili coś stworzyć bez cudzych silników. No i szybko ostrzegli mnie - pozbądź się garbage collectora, bo później będziesz płakał gdy co jakiś czas będziesz tracił kilka FPS. Podali metodę jak sprawić w C# żeby pamięć po usuniętych obiektach była zwalniana na bieżąco, a nie w dużych partiach (co zajmowało sporo czasu). Nic z tego już nie pamiętam, bo całe to przedsięwzięcie związane z Xbox Live Arcade okazało się bez sensu, a ostatecznie Microsoft i tak uśmiercił XNA (wraz z Zune i ZuneHD - konkurencją iPod Touch). Ja złożyłem przysięgę, że będę omijał rozwiązania Microsoftu i języki działające na jakiejś wirtualnej maszynie.
Przypadek 3
Pisząc jeszcze gry na Java2ME ciągle był problem z GC. Java z założenia multiplatformowa, na telefonach zupełnie nie była multiplatformowa i żeby zrobić coś sensownie działającego na 300 modelach telefonów to trzeba było przygotować kilkanaście wersji. Na przykład jakiś model chyba Sharpa (chociaż tu mogę źle pamiętać) miał małe ale stałe wycieki pamięci i jedynym rozwiązaniem było wrzucenie System.gc() to pętli głównej. Zupełnie mu to nie przeszkadzało i wszystko było ok. Taka Nokia N70 też maiła to w nosie i wywoływanie GC co klatkę nie robiło na niej wrażenia ale... dźwięk nie działał. No a Nokia N-Gage przy tym umierała - było dosłownie 1-2FPS. Dlatego niby przenośny kod, a trzeba było mieć masę takich głupich warunków, wycinanego albo wklejanego kodu na etapie kompilacji (oszczędność była wymagana, bo czasem JAR nie mógł być większy niż 128, 100 czy 64KB).
Przypadek 4
No to chyba właśnie ten JavaScript w Wayfarer. Ale tutaj nie wiem nic ponad to co zostało napisane tutaj w komentarzach.

Ale mniej więcej wiemy jak wygląda dzisiejszy kod nawet prostych implementacji. Gigabajt RAMu, 50 obcych bibliotek i grube dziesiątki megabajtów alokowanej i zwalnianej pamięci na różnych warstwach w ciągu ułamka sekundy, tylko po to żeby pokazać prosta listę czy trzy obrazki. Niewyobrażalne ilości operacji, które idą prosto w komin zakładając, że CPU i tak jest wielordzeniowe i taka niefrasobliwość nie wpłynie w widoczny sposób na finalny produkt. Ale ale gdy MOSTeam przy pomocy MorphOSa zaczyna pukać do dzisiejszych rozwiązań (WebKit, GCC10) ze sprzętem z lat 2000-2005 i systemem z kulą u nogi (kompatybilność z AmigaOS3) to wychodzi to całe "nowoczesne" programowanie. Dopiero wtedy uświadamiamy sobie jak bardzo nieoptymalnie jest to wszystko dzisiaj pisane. Świetnie to było widać podczas śledzenia postępów prac na amigową wersją gry "Tower 57" - od kilku FPS do 60 FPS (u mnie w 1440x960). Daję sobie głowę uciąć, że każda gra z ostatnich 20 lat robi tonę nadmiarowych operacji (nawet niezwiązanych z rysowaniem po ekranie). Nikt się nie przejmuje tym, że co klatkę przewala zupełnie niepotrzebnie jakieś słowniki czy tablice z tysiącami elementów i każdy z tych elementów też odwołuje się do tysięcy innych sprawdzając coś zupełnie nieptrzebnie.

Tak się dzisiaj pisze i lepiej nigdy już nie będzie. Chyba, że AI będzie takie momenty wskazywało. Ale i tak będzie się to ignorowało, bo takie poprawki są "biznesowo nieuzasadnione".

Komercyjny programista w pracy czeka przede wszystkim na piątek i wycieczkę do egzotycznego kraju. Niemal niemożliwe jest dzisiaj znalezienie dzisiaj zarośniętego nerda w kraciastej koszuli, który tylko dla własnej satysfakcji, programistycznego honoru i żeby móc w nocy zasnąć, poprawia coś co już działa.
Jeżeli coś działa jednowątkowo i ma działać płynnie to takie nagłe odśmiecanie sporej porcji jest straszne. Jest cały czas 60FPS i dosyć regularnie np. raz na 4 sekundy jest przez moment 40FPS. To jest tak irytujące, że można oszaleć. Maszyna niby jest szyba, nawet znacznie za szybka ale te przestoje są straszne. To już lepiej chyba wszystko zdołować sztucznie do 30FPS (ale na wolniejszych maszynach i tak pewnie będą co jakiś czas zwolnienia).

Dzisiaj sprzęt jest tak absurdalnie szybki i przede wszystkim wielordzeniowy, że to nie ma znaczenia i animacja jest płynna, bo takie rzeczy pewnie są robione na nie UI-owym wątku. Jednak takie nieprzewidywalne przestoje nadal uważam za bardzo słabe rozwiązanie. Zwłaszcza, że od lat istnieją, moim zdaniem, lepsze rozwiązania.
W grze zdecydowanie lepiej jest gdy w momencie "uśmiercania" jakiegoś obiektu pamięć po nim jest od razu wyrzucana, a nie zbierana do kosza na śmieci, a potem co kilka sekund procesor robi sobie przerwę żeby wynieść śmieci.

Wolę już delete z C++, free z C czy reference counter albo automatic reference counter z Objective-C (czy Swift), bo tego problemu nie ma (a w przypadku ARC zarządzać pamięcią tez nie trzeba jak w C/C++ i wycieków pamięci nie ma jeżeli nie zrobi się szkolnego błędu z reference cycle). W hobbystycznej zabawie w C++ używam własnoręcznie stworzonego reference countera (nawet słabe referencje sam sobie zrobiłem), bo na serio nad tym panuję i nie mam niespodzianek. Ale czegoś takiego oczywiście nie polecam, bo to jest raczej hobby niż rozwiązanie "biznesowe". Generalnie dzisiaj nie polecam nikomu robienia czegoś bez gotowych silników, bo to jest zabawa na długie lata. No chyba, że dla kogoś jest to pasja - wtedy przybijam piątkę i uśmiecham się porozumiewawczo, bo rozumiem ten nałóg.
Ostatnia aktualizacja: 28.03.2024 16:42:28 przez MDW