Czy zaawansowane gry w javie byłyby mniej wydajne od tych napisanych np. w c++?

Odpowiedz Nowy wątek
ffffffffff
2014-08-17 18:47
ffffffffff
0

W javie to znam minecrafta i właściwie tyle gier nie licząc mniejszych. Nie znam żadnych gier z grafiką jak w call of duty, battlefieldy, crysis.
Czy gdyby twórcy gry Crysis 3 (DX11) napisali identyczną grę w Javie, to czy wydajność Crysis 3 w Javie byłaby taka sama, czy gorsza, albo dużoooo gorsza i wręcz niegrywalna?

Pozostało 580 znaków

2014-08-17 19:19

Rejestracja: 8 lat temu

Ostatnio: 6 dni temu

1

w javie nie ma zarzadzaniem pamieci recznej. Jest Garbage Collector. Wyobraz sobie ze grasz i co jakis czas gra Ci zamraza bo musi wyczyscic to co zadelkarowal program

zreszta
naucz sie szukac sam odpowiedzi bo byla juz milion razy

w google wpisujemy
why games are not written in java

pierwszy link
http://stackoverflow.com/ques[...]t-video-games-written-in-java

Pozostało 580 znaków

msm
2014-08-19 22:53
msm
Administrator

Rejestracja: 11 lat temu

Ostatnio: 2 tygodnie temu

12

Czy gdyby twórcy gry Crysis 3 (DX11) napisali identyczną grę w Javie, to czy wydajność Crysis 3 w Javie byłaby taka sama, czy gorsza, albo dużoooo gorsza i wręcz niegrywalna?

Wydaje mi się że Twórcy Gry Crysis 3 to programiści C++ (a przynajmniej ta część twórców która programuje), więc gdyby napisali grę w Javie to byłaby dużoooo gorsza i wręcz niegrywalna.

w javie nie ma zarzadzaniem pamieci recznej. Jest Garbage Collector. Wyobraz sobie ze grasz i co jakis czas gra Ci zamraza bo musi wyczyscic to co zadelkarowal program

Kontrargument (tak, to C#, ale przypadek wystarczająco podobny):
http://unity3d.com/showcase/gallery

Jeśli chodzi o programowanie gier w językach z GC: sam zaczynając programować interesowałem się grami (jak niejeden pewnie), tylko zamiast grać wolałem je tworzyć. No więc na temat podejść do pisania gier w C#:

Po pierwsze: nie alokować (a.k.a. /hackować/ zamiast alokować)
Najprostsze koncepcyjnie i najbardziej ekstremalne podejście - nie alokować nic. A konkretnie nie alokować nic w pętli głównej gry (zdarzenia dynamiczne jakby nie próbować, nową pamięć brać muszą, ale tak jest wszędzie). Żeby to osiągnąć trzeba:

  • cachować obiekty (tzw. object pools). Ilość typów obiektów w grze jest ograniczona. Po prostu zamiast pisać obj = new Obiekt() można pisać obj = Cache<Obiekt>.Create() (...oraz Cache<obiekt>.Free(obj) - i mamy wszystkie problemy pilnowania pamięci w zarządzanym świecie - świetnie). Jest to dużo wolniejsze (i brzydsze) niż "prawdziwe new" w C# (ktore 99.5% czasu jest równie szybką operacją co np. dodawanie)
  • używać struktur gdzie się da/gdzie to ma sens (ok, to się na javę nie przenosi). Struktury są alokowane na stosie zamiast na stercie, ale jest catch - JIT jest optymalizowany pod typowe przypadki, a typowym przypadkiem w C# są klasy. Z tego powodu sporo koniecznych optymalizacji nie działa dla value types (np. inlining! Przy prymitywnych operacjach jak np. dodawanie wektorów to znaczący problem), i albo mamy wolny kod (poza tym że samo przekazywanie sturktur jest wolniejsze niż klas), albo używamy hacków (jak przekazywanie struktur przez referencję).
  • przepisywać funkcje z biblioteki standardowej od zera. Cóż, większość funkcji "leakuje" pamięć, więc jeśli chcemy "całą dla nas", trzeba je napisać samodzielnie zamiast koncentrować się na pisaniu gry.
    disclaimer: nie piszę co robić. Piszę co można zrobić. Żeby nie było że promuję kod nadający się do programistycznego WTF

Po drugie: alokować mało lub krótko
Pogłoski o tym że GC w trakcie gry to śmierć są mocno przesadzone. Nie znam się na ekosystemie i technologiach w świecie javy, więc znowu od strony dotnetu, jak to naprawdę jest z GC:

  • GC gen 0 jest szybki. Mokrym snem projektantów było to żeby zajmował nie więcej czasu niż zwykły cache miss - jesteśmy "not quite there yet", ale to coś na co trzeba zwrócić uwagę - po to obiekty są podzielone na generacje żeby typowy GC wykonywał się w mgnienie oka.
  • z Gen1 i Gen2 nie ma już tak fajnie. Ale to może nie być problemem, jeśli obiekty nie przeżywają gen0 - to znaczy jeśli wszystkie obiekty w grze są albo bardzo ulotne (np. żywe jedną klatkę gry), albo trwałe (np. żywe cały level) to te kolekcje mogą wcale nie nastąpić.
  • z uwag odnośnie GC, sam nie benchmarkowałem nigdy (ani nie korzystałem świadomie) ale podobno duże znaczenia ma ilość rootów (korzeni?) GC. Root = wszystko co globalne zasadniczo (czyli rzeczy statyczne), czyli rzeczy od których GC zaczyna czyszczenie i które musi przejrzeć za każdym razem.
  • jeszcze więcej uwag odnośnie GC. Dotnetowy GC (javowcy też chyba mają analogiczną mechanikę) korzysta z techniki write-barrier, przy pomocy struktury danych nazywającej się cardtable. Cardtable to po prostu tablica bitów, gdzie każdy bit odpowiada pewnemu obszarowi pamięci (np. 1 kb). Zapisanie czegoś do obiektu z niezerowej generacji powoduje zapalenie bitu w cardtable odpowiadającemu pamięci gdzie znajduje się ten obiekt (piszę po polsku? Inaczej ujmując, cardtable mówi mniej-więcej które obszary pamięci zostały zmodyfikowane). Dzięki temu np. GC wykonując mark&sweep w gen1/gen2 ma uproszczoną robotę. Nigdy z tego celowo nie skoszystałem (i nie polecam), ale kolejny przykład na to że GC nie jest musi być głupi.

Po trzecie: skoro trzeba to alokować

  • GC gen 2 jest wolny. Ale od czego są wątki? Od początków dotnetu GC może działać w wielu trybach. Domyślnym z nich do .net 4.5 był concurrent. Dzięki temu przy GC gen 2 większość operacji jest wykonywana równolegle, wątki zatrzymywane są tylko po to żeby poprawić referencje po wykonanej robocie (chyba że wyczerpią ephemeral segment, bo GC gen1 i GC gen0 nie mogą być wykonywać się równocześnie z concurrent GC.
  • GC gen 2 jest wolny. Ale od czego są wątki! Od .net 4.5 domyślnym trybem GC jest nowy 'cutting edge' tryb Background. Background GC potrafi wykonywać jednocześnie GC gen1/gen0 oraz GC gen2 (dodatkowo w server mode na każdy procesor przypada jeden wątek GC, ale to akurat nie dotyczy gier). Przerwy na GC 2 robią się jeszcze krótsze. (Dla ciekawych - http://blogs.msdn.com/b/dotne[...]r-client-and-server-apps.aspx)

Chętnie napisałbym więcej o GC (a jest o czym - brick tables, Large Object Heap, problemy z pinowaniem, managed pointers, finalizacją i rezurekcją, thread hijacking...) ale to by był OT i w dodatku specyficzny dla .net a pytanie o javę ;).

Podsumowanie: czy warto?
Tak chciałem rzucić losowe rzeczy które mi przyszły do głowy z tego co robiłem. Wracając do tematu - gdyby pytanie było po prostu o pisanie gier (gry na komórkę, minigry, gry webowe/flashowe) to odpowiedź byłaby oczywista (że warto - ignorując większość uwag o wydaności z tego posta. Po prostu przy zwykłych grach to nie taki problem).
Z drugiej strony skoro mówimy o "zaawansowanych" grach, czyli grach "przesuwających granicę tego co możliwe" (jak pamiętam np. Crysisa) - nie jestem przekonany (no i pewnie ilosć programistów C#/Javy znających się na pisaniu gier jest... nikła. Podobnie jak wsparcie, chociaż w przypadku C# dzięki Unity to się zmienia). Może i DA SIĘ pisać wydajnie, ale tak naprawdę pytanie jest czy opłaca się to robić.
A z trzeciej strony to i tak jakość współczesnych gier obecnie ogranicza nie wydajność PC tylko konsole (które są ważniejsze z punktu widzenia producentów) ;)

PS. jeszcze zostawię to tutaj: http://superhotgame.com/ (unity)

edit: łał, ale mi post wyszedł. W dodatku rozpisałem się o GC zamiast odpowiadać na pytanie. Cóż, każdy ma jakieś hobby - jedni interesują się samochodami, inni Garbage Collectorami ;).

edytowany 1x, ostatnio: msm, 2014-08-19 22:55
Fajnie, wiedzy o .NETowej śmieciarce nigdy za wiele ;) - AlfaLeporis 2014-08-19 23:04
zaden kontrargument z unity3d. Silnik jest napisany w c++. Skrypty piszesz w c#. W kazdym silniku, baaa w kazdej wielkiej grze AAA nikt o zdrowych rozsadkach nie bedzie pisal w czystym c++ tylko bedzie do tego skryptowy jezyk (unity dodalo c# jako skryptowy jezyk). A silnik napisze sie w c / c++ - fasadin 2014-08-20 09:33
drugie spostrzezenie, zawsze pisze sie wlasny stl (jezeli chodzi o c++) wiec przepisywanie kolekcji i ogolnie funkcji ktore sa. Nie jest niczym szczegolnym :) - fasadin 2014-08-20 09:36
I nie tylko C#, boo i js też (a w sumie ichnią odmianę js). Fakt, to zupełnie co innego (czyli w sumie temat o pisaniu /silników/ do gier). Ogólnie myślą przewodnią postu (którą trochę zgubiłem, ale.) było to że problemy z GC w grach da się obejść, tylko że okazuje się wtedy że pisze się prawie jak w C++ i do tego walcząc co chwilę z językiem (który nie jest przeznaczony za bardzo do takiego użycia) ;). Ad. przepisywania STL to ciekawe, nie wiedziałem (ale nie znam się na gamedevie) - dlaczego 'standardowy' STL nie wystarcza (zoptymalizowany raczej jest, więc coś innego?)? - msm 2014-08-20 09:44
przede wszystkim jest alokowana pamiec na stercie. Co jest wolniejsza operacja niz alokowanie na stosie malych obiektow (ale tak wiem, mozna swoj wlasny alokator napisac). Ale informacje moje byly juz niepoprawne :) Zawsze to slyszalem, jednak prawda jest troszke inna. http://gamedev.stackexchange.[...]/268/stl-for-games-yea-or-nay Zaakceptowana odpowiedz. Do tego dochodzi jeszcze http://www.open-std.org/jtc1/[...]1/docs/papers/2007/n2271.html STL pod konsole. No i jeszcze problem z stlem teraz jest. Ze jest inny dla gcc, msvc, intel itd itp. - fasadin 2014-08-20 10:07
"zawsze pisze sie wlasny stl" - ja myślę że taki Boost ma tyle wariantów różnych kontenerów, że któryś nada w konkretnym zastosowaniu i nie trzeba pisać od zera. - Azarien 2014-08-20 11:09

Pozostało 580 znaków

fsadsafdfdsa
2014-08-21 09:08
fsadsafdfdsa
0
fasadin napisał(a):

w javie nie ma zarzadzaniem pamieci recznej. Jest Garbage Collector. Wyobraz sobie ze grasz i co jakis czas gra Ci zamraza bo musi wyczyscic to co zadelkarowal program

a co chcesz deklarować przy rysowaniu? przecież nie będziesz tworzyć przeciwników przy każdej klatce obrazu; przy ładowaniu poziomu tworzysz obiekty, później je tylko przesuwasz; ewentualnie doczytujesz mapę w którymś miejscu ale przecież nie musisz tego robić cały czas

ostatnio chyba nawet na tym forum ktoś miał problem przycinania się co którąś klatkę gry - rozwiązaniem było ręczne odpalanie GC co klatkę; w ten sposób gra działała niezauważalnie wolniej ale bez przycięć

kod zarządzany po kilkukrotnym odpaleniu zazwyczaj jest tak samo szybki jak natywny
ba - nawet widziałem że javascript potrafi być szybszy od c++

Pojawila sie jakas nowosc w Javie ze mozna GC recznie wywolac? (dawniej to bylo tylko pobozne zyczenie aby sie wywolal) - WhiteLightning 2014-08-21 09:18
Nie wiem czemu, ale jak dla mnie - w tym temacie - wygląda to mniej więcej tak: "Haha, tato, tym razem byłem lepszy!"'; "Tak tak synku, dobra robota :]" - spartanPAGE 2014-08-21 09:32
Od zawsze można w Javie GC ręcznie wywołać. System.gc() (specyfikacja stwierdza, że jest to tylko "hint" i nie musi działać, ale fakty są takie, że implementacja od Oracle zawsze wywoływała GC przy tym wywołaniu, o ile ktoś specjalnie tego nie wyłączył w opcjach aplikacji). Natomiast inna rzecz, że jeśli musisz to robić, to na pewno robisz coś źle i problem leży gdzie indziej. - Krolik 2014-08-21 20:59

Pozostało 580 znaków

2014-08-21 09:25
Moderator

Rejestracja: 16 lat temu

Ostatnio: 6 minut temu

0

@fsadsafdfdsa nie przesadzajmy. JIT to jest fajna rzecz, ale jest mocno empiryczna, niedeterministyczna i w jednej sytuacji przyspieszy kod 10 razy a w innej ani trochę.
Dla tych którzy nie wierzą że język z JIT (np. Java czy Python) mogą być szybsze niż C/C++, nawet pomimo tego że mają narzut maszyny wirtualnej, krótkie wyjaśnienie:

  1. Kompilator języka natywnego może dokonać optymalizacji tylko w czasie kompilacji. W trakcie uruchomienia jest już tylko kod maszynowy interpretowany przez procesor.
  2. Środowisko wykonania dla języków z kodem pośrednim może dokonywać optymalizacji także w trakcie wykonania programu, w trakcie tłumaczenia bajtkodu na kod maszynowy. To jest właśnie JIT - kompilacja Just in Time
    Krótki przykład jak sprawić żeby Java była szybsza niż C. Wyobraźmy sobie że mamy kod który wykonuje miliardy operacji dzielenia przez zmienną podaną przez użytkownika. Kompilator C/C++ niewiele może tu zoptymalizować, w końcu nie wiadomo przez co będziemy dzielić. Co się dzieje jeśli użytkownik poda jako dzielnik liczbę 2? Kod w C/C++ będzie działał identycznie niezależnie od podanej liczby. Kompilator JIT w Javie będzie za to w stanie wykryć że dzielimy przez 2 i będzie mógł zamienić te wszystkie operacje dzielenia na dużo szybsze przesunięcia bitowe. I voila, kod w Javie pomyka szybciej niż kod natywny.

Przykład jest oczywiście przejaskrawiony, ale wcale nie taki nierealny. Ciekawostka: interpreter CPython jest ~5 razy wolniejszy od interpretera PyPy właśnie dlatego że ten drugi posiada kompilator JIT.

Jeśli chodzi o GC to kolejne generacje tych narzędzi są coraz lepsze, nie ma już efektu stop-the-world itd. Nie zmienia to oczywiście faktu że mimo to pewien narzut istnieje. Ale z drugiej strony szansa na wycieki jest dużo mniejsza, czas debugowania też :)


Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...

Pozostało 580 znaków

2014-08-21 09:50
Moderator

Rejestracja: 13 lat temu

Ostatnio: 39 sekund temu

Lokalizacja: Stacktrace

0

Dużo zależy od konkretnego problemu. Zapewne znacznie szybciej napiszesz grę, która będzie miała ograniczoną grafikę (kosztowne obliczenia realizowane GPU, z którymi java sobie średnio radzi) i dużó AI (planszóweczki w stylu Panzer General czy HoMMIII) niż takiego Crysisa

W Javie można zarządzać pamiecią "ręcznie" za pomocą klasy Unsafe > http://www.slideshare.net/mishadoff/unsafe-java-18168628 oczywiście przypomina to sekswakacje w Tajlandii bez użycia gumy, ale zawsze...

Kolejna rzecz to algorytmy i ich implementacja. To już jest czynnik ludzki i dużo zależy od tego kto pisze kod. Mam takie wrażenie, że programiści C++ sa w tym lepsi niż javowcy.

JIT, jak wspomniano powyżej pozwala na optymalizację w czasie wykonania i pewne związane z tym bonusy.


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
"Mam takie wrażenie, że programiści C++ sa w tym lepsi niż javowcy." Nie chcę tu jakiegoś flame'a robić, ale z ciekawości - po czym wnosisz? Bo ja mam dokładnie odwrotne wrażenie. Tzn. większość programistów C/C++ jakich znam, to świeżo upieczeni absolwenci, którzy znają C++ bo było obowiązkowe na studiach, i którzy z wyższością patrzą na Javę, której nie znają (no, bo tylko jeden fakultet mieli, na którym napisali hello-world i było wolniejsze niż C, przeto Java jest powolna i się do niczego nie nadaje). - Krolik 2014-08-21 21:03
Mówię o ludziach z kilkuletnim już stażem. Po prostu trochę inna specyfika tworzonych aplikacji powoduje, że programiści c++ nabywają praktycznych umiejętności w zakresie np. matematyki "graficznej" czy implementacji algorytmów z zakresu fizyki w wydajny sposób. Javowcy za to znacznie lepiej ogarniają problemy związane ze specyfiką aplikacji biznesowych. Dla nich ogarnięcie złożonego przepływu na poziomie biznesowym nie jest problemem. Mają odpowiednie narzędzia i wiedzę. - Koziołek 2014-08-21 21:28

Pozostało 580 znaków

2014-08-21 10:13

Rejestracja: 8 lat temu

Ostatnio: 6 dni temu

0
<student> Java jest szybsza od C++. W C++ nie ma JIT <inny student="student"> i java zjada mniej pamięci niż C++. Bo w C++ nie ma garbage collector edit. Zaraz opisze sie ;) takze za godzinke bedzie tu cos dlaczego c#/java nie sa dobre jak c++. C++ jest natywnym jezykiem programowania z "runtime library" wiec kiedy aplikacja w c++ jest wywolywana w maszynowym kodzie uzywa funkcji z "runtime" i to jest kompletnie oddzielone od OS aplikacji. To zyje w swoich wlasnych procesach/watkach i uzywa zasobow systemowych jako standardowa aplikacje na OS. Aplikacja jest zrobiona pod konkretnego OS z c#/java jest inaczej, na poczatku sa uruchamiane za pomoca byte-codu i ten byte code jest jedyna rzecza ktora jest natywna. wtedy aplikacja napisana przez nas, jest przekazywana do runtime. Runtime tlumaczy kod na maszynowy i go wykonuje. To jest ogolna idea, ale jest tego troszke wiecej. Kazdy zasob systemowy jest wrappowany przez runtime sybsystem. Wiec kazde wywolanie bedzie liczba "wrapow" dla tych sub-calls W c/c++ mozemy powiedziec ze "ta linia jest tlumaczona na N op-codes" w c# java mozemy powiedziec podobnie ze ta linia zostala przetlumaczona na M op-codow. ALE zawsze M>N Niektorzy moga powiedziec "to nie jest prawda daj mi algorytm i zrobie M=N". Zgadza sie, nawet moga byc to te same algorytmy, ale jezeli chodzi o prawdziwe aplikacje jak np gra napisana w openGL wtedy to nie jest mozliwe chocby ze wzgledu na architekture Ponownie mozecie powiedziec "to nie prawda" ale przy nastepnej optymalizacji znajdzie sie asm, c++ itd i juz nie bedzie to dluzej natywny kod c#/java No i kolejna rzecz. Bezpieczenstwo. W roznych frameworkach pojawiaja sie bugi calkiem czesto. Jezeli ktos znajdzie takie cos, wszystki applikacje sa narazone. I co mozesz zrobic? Tak na prawde nic, z wyjatkiem modlenia sie. Bugi w c++ w runtime oczywiste tez sa mozliwe, ale sa bardzo rzadkie i mozesz napisac dla nich "workaround" dla prawie kazdego przypadku. No i bugi w c++ sa raczej naprawiane super wczesnie - poniewaz ten bug zapewne tez bedzie w danym OS
edytowany 2x, ostatnio: fasadin, 2014-08-21 10:29

Pozostało 580 znaków

2014-08-21 11:01
Moderator

Rejestracja: 16 lat temu

Ostatnio: 6 minut temu

0

@fasadin

  1. Może i M>N ale generalnie niekoniecznie jest to wielka różnica.
  2. Nie rozumiem fragmentu o frameworkach. Porównujesz frameworki z gołym językiem. Przeciez we frameworkach C++ też mogą być bugi i to jeszcze groźniejsze bo java mimo wszystko działa w pewnym sandboxie maszyny wirtualnej.

Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...
Ja bym jeszcze dorzucił trochę inną kulturę kodowania w Javie. - Koziołek 2014-08-21 11:18

Pozostało 580 znaków

2014-08-21 21:12
Moderator

Rejestracja: 16 lat temu

Ostatnio: 13 godzin temu

3

W c/c++ mozemy powiedziec ze "ta linia jest tlumaczona na N op-codes" w c# java mozemy powiedziec podobnie ze ta linia zostala przetlumaczona na M op-codow. ALE zawsze M>N

To jest akurat w ogólności nieprawda. Może być zarówno M < N, M == N jak i M > N. Wszystko zależy od tego, jakie optymalizacje wykona kompilator. A do tego więcej opcodów nie zawsze oznacza wolniejsze wykonanie, bo procesory robią pod spodem kolejną warstwę optymalizacji (np. zmieniają kolejność wykonania), więc wnioskowanie na tej podstawie o wydajności nie jest słuszne.

Bezpieczenstwo. W roznych frameworkach pojawiaja sie bugi calkiem czesto. Jezeli ktos znajdzie takie cos, wszystki applikacje sa narazone. I co mozesz zrobic? Tak na prawde nic, z wyjatkiem modlenia sie. Bugi w c++ w runtime oczywiste tez sa mozliwe, ale sa bardzo rzadkie i mozesz napisac dla nich "workaround" dla prawie kazdego przypadku. No i bugi w c++ sa raczej naprawiane super wczesnie - poniewaz ten bug zapewne tez bedzie w danym OS

No, tak bo w takim Qt, gcc czy przeglądarce internetowej to nie ma setek niepoprawionych bugów.
Język w którym każdy kawałek kodu może nadpisać dowolny fragment swojej pamięci nazywasz bezpiecznym.... ROTFL.

Jak musz buga w C++, to faktycznie możesz się tylko modlić aby nie rozwalił sterty i nie zakończył się crashem. W Javie łapiesz wyjątek i jedziesz dalej.

Odpowiadając na oryginalne pytanie:

  1. GC raczej nie jest już problemem. CMS odśmieca współbieżnie i jak się jest ostrożnym można spokojnie zejść z do poziomu pojedynczych milisekund raz na jakiś długi czas. Jak komuś CMS nie daje rady, to można próbować z G1, ale moje doświadczenia są lepsze z CMS. Gry używają bardzo dużo pamięci na zasoby graficzne. Można je alokować poza stertą, nie obciążając GC.

  2. Nadal problemem jest optymalizowanie struktur danych aby były cache-friendly. Java nie ma value-types tak jak ma C#. To powoduje, że trudno zrobić wydajną reprezentację punktów (np. Point3D). Ale z tego co wiem, to pracują nad tym i w niedalekiej przyszłości ten brak zostanie naprawiony (raczej nie w Java 9, a później, ale zostało to już ogłoszone).

  3. Większość dobrych silników została napisana w C/C++, więc z przyczyn historycznych, zaawansowane gry pisze się w tym, co jest wymagane przez silnik.

  4. Przykład Minecrafta pokazuje, że gracze wcale nie są tak bardzo wrażliwi na okazjonalne lagi i przycięcia, jak to niektórzy sugerują. Jak gra jest dobra, to zgubienie jednej klatki raz na 5 minut nie jest jakimś wielkim problemem.

i java zjada mniej pamięci niż C++. Bo w C++ nie ma garbage collector

W pewnym sensie jest to prawda. Tzn. licząc tylko samą stertę, system z GC jest znacznie bardziej przewidywalny pamięciowo niż system z alokacją dynamiczną malloc/free. W przypadku ręcznej alokacji tak jak w C++, tak naprawdę nie masz żadnej gwarancji, że rozmiar sterty jest tylko nieznacznie większy od rozmiaru pamięci faktycznie zaalokowanej. Pogooglaj o problemie fragmentacji pamięci. Typowo fragmentacja nie jest dużym problemem, ale w skrajnym przypadku może się zdarzyć, że Twój program będzie zżerał w danej chwili 100x więcej pamięci niż faktycznie jest zaalokowane. Natomiast w przypadku GC - TY jako programista aplikacji możesz na sztywno wbić jaki chcesz mieć ten współczynnik (całkowity rozmiar sterty / używana pamięć) i w dobrze napisanej aplikacji 1.5x zapewnia zwykle bardzo dobrą wydajność i małą aktywność GC. Jak dasz za mało miejsca na GC, to najwyżej się w którymś momencie przytnie. W C++, gdybyś tak zrobił (hmm... da sie - wystarczy odpowiedni ulimit), dostajesz wyjątkiem, a raczej wywaleniem programu, no bo kto łapie wyjątki rzucane przez new?

Inna sprawa, że systemy z GC mają większą przepustowość (w sensie allocation/deallocation rate) niż systemy z ręczną alokacją. Swoją drogą systemy baz danych od dawna stosują coś w rodzaju GC, właśnie aby zwiększyć wydajność. Jak robisz DELETE w SQLu, to dane nie są usuwane natychmiast, tylko doppiero podczas GC (w Postgresie zwanego "vacuum" a w Cassandrze "compaction").

edytowany 8x, ostatnio: Krolik, 2014-08-21 21:42
Pokaż pozostałe 2 komentarze
Placement new nie jest uniwersalną strategią zarządzania pamięcią, nadaje się tylko w niektórych przypadkach. Javowe GC działa jak placement new, ale dla wszystkich obiektów (alokuje sekwencyjnie z ciągłego obszaru, a po jakimś czasie zwalnia cały obszar za jednym zamachem). Dlatego wcale nie jestem przekonany, czy tuning GC nie jest ogólnie łatwiejszy niż zabawy w placement new, pule obiektów i inne dziwne rzeczy w C++. Np. LMAX z premedytacją użył Javy, bo stwierdzili, że łatwiej jest zoptymalizować GC niż optymalizować C++ pozbywając się do tego bezpieczeństwa pamięci. - Krolik 2014-08-22 08:36
Ale jakie zabawy z placement new? To po prostu wcześniejsze zarezerwowanie sobie miejsca, nic więcej. Proste jak budowa cepa, a i tak co możesz masz na stosie - spartanPAGE 2014-08-22 09:50
No wcześniejsze zarezerwowanie miejsca, miejsce się kończy i wtedy co? Jak się okaże, że część obiektów nadal potrzebujesz, a część nie, to jesteś w punkcie wyjścia - piszesz albo ręczny alokator ala malloc/free i pamiętasz, gdzie są wolne miejsca (fragmentacja), albo robisz coś w rodzaju GC, gdzie przenosisz używane obiekty do nowego regionu, aktualizujesz do nich wszystkie referencje, a stary zwalniasz. I to już wcale nie jest proste. Innymi słowy mnóstwo kodu na coś, co GC w Javie robi za Ciebie bezpieczniej bez pisania ani jednej linijki. - Krolik 2014-08-22 10:54
Huh? Wybierasz sobie wielkość sterty i na tym kończy się zabawa. Nie wiem jaką magie chcesz tutaj przypisać, nie mniej jednak przypominam, że mówimy tutaj o grach - tyle stworzono, wszystkim pasowało; http://gameprogrammingpatterns.com/object-pool.html - spartanPAGE 2014-08-22 11:12
Teraz piszesz o puli obiektów, a nie placement new. Tylko że pulę obiektów można tak samo zrobić w Javie, C# a nawet w Pythonie. Więc znowu nie widzę tu za bardzo jakiejkolwiek przewagi. Pule obiektów jednak niekoniecznie są szybsze od GC, zwłaszcza dla małych obiektów, bo masz narzut na wyszukanie i wyciągnięcie wolnego obiektu z puli, a zakodowanie takiej puli bezpiecznie ze względu na wątki i do tego wydajnie jest już całkiem skomplikowane. - Krolik 2014-08-22 11:46

Pozostało 580 znaków

2014-08-22 09:03

Rejestracja: 9 lat temu

Ostatnio: 4 minuty temu

1

Dochodzi jeszcze jedna rzecz - wiedza i nauka. Jesli jest zespol gosci ktorzy od 10 lat wymataja robiac gry w C/C++ i maja w malym paluszku cala potrzebna im wiedze, to przejscie na nowa technologie zajmie sporo czasu (prototyp czy alfe zrobia szybko, ale potem na walce ze szczaegolami i drobiazgami mnostwo zejdzie).

Dlatego w czasach, kiedy o Javie nikt nie słyszał, a w biznesie rządziło C++, w gamedev twardo kodowali w C i asm (no i flamewary C++ vs C były na porządku dziennym, gdzie wobec C++ stosowano podobną krytykę co obecnie wobec .NET i Javy - że nie daje pełnej kontroli, że dużo robi "za plecami programisty", że daje dodatkowy narzut na abstrakcje itp.) - Krolik 2014-08-22 10:58
Zgadzam sie, stad teraz robi sie rozbicie technologii w gamedev, czesc osob (zwlaszcza projekty AAA) zostaje w okolicach C/C++. A czesc (szczegolnie male projekty czy indie) idzie w srodowiska typu Unity, bo tam tworzy sie szybko, a wydajnosc przewaznie jest wystarczajaca. Dochodzi tez wykorzystanie gotowych silnikow a one przewaznie sa robione w C++. - WhiteLightning 2014-08-22 11:21

Pozostało 580 znaków

CcCcC
2014-08-22 11:57
CcCcC
0

W Javie nie można napisać Javy!!! Nie można w niej napisać nic, co potrzebne było, by napisać Javę!!! Ani nic, co potrzebne było do napisania tego, co potrzebne było... etc. Potrzebujesz VM i potrzebuejsz coś, na czym VM będzie działać. Ani VM ani Javy, ani tego na czym to działa, nie możesz napisać w Javie. A żeby uruchomić VM... o, potrzeba całkiem sporawo.
Java jest najbardziej zasobożerna...
Java jest najbardziej rozwlekła...
Java jest najbardziej powolnym językiem...

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0