za. Jaka jest dzisiaj szybkość Javy w porównaniu z C ++?
Trudne do zmierzenia. Warto zauważyć, że znaczną część prędkości implementacji, czyli alokatora pamięci, stanowią bardzo różne algorytmy w Javie i C ++. Niedeterministyczny charakter kolektora bardzo utrudnia uzyskanie znaczących danych dotyczących wydajności w porównaniu z deterministycznym zarządzaniem pamięcią w C ++, ponieważ nigdy nie można być pewnym, w jakim stanie jest kolektor. Oznacza to, że bardzo trudno jest napisać test porównawczy to może znacząco je porównać. Niektóre wzorce alokacji pamięci działają znacznie szybciej z GC, niektóre z natywnym alokatorem.
Powiedziałbym jednak, że Java GC musi działać szybko w każdej sytuacji. Natywnego programu przydzielającego można jednak zamienić na bardziej odpowiedni. Niedawno zadałem pytanie na temat SO, dlaczego C # Dictionary
może wykonać w (0,45 ms na moim komputerze) w porównaniu do równoważnegostd::unordered_map
który wykonał (10ms na moim komputerze). Jednak po prostu zamieniając alokator i skrót na bardziej odpowiednie, skróciłem ten czas wykonania do 0,34 ms na moim komputerze - trzydziestej pierwotnego czasu działania. Nigdy nie możesz mieć nadziei na wykonanie takiej niestandardowej optymalizacji za pomocą Java. Doskonałym przykładem tego, gdzie może to naprawdę zmienić rzeczywistość, jest gwintowanie. Rodzime biblioteki wątków, takie jak TBB, zapewniają alokatory buforowania wątków, które są znacznie szybsze niż tradycyjne alokatory w przypadku wielu alokacji dla wielu wątków.
Teraz wiele osób będzie rozmawiać o ulepszeniach JIT i tym, jak JIT ma więcej informacji. Jasne, to prawda. Ale nadal nie jest nawet w niewielkim stopniu zbliżone do tego, co kompilator C ++ może wyciągnąć - ponieważ kompilator ma stosunkowo nieskończony czas i przestrzeń do uruchomienia, z punktu widzenia czasu wykonania końcowego programu. Każdy cykl i każdy bajt, który JIT spędza na zastanawianiu się, jak najlepiej zoptymalizować program, to cykl, którego program nie spędza na wykonywaniu i którego nie może wykorzystać do własnych potrzeb pamięci.
Ponadto zawsze będą momenty, w których kompilator i optymalizacja JIT nie będą w stanie udowodnić pewnych optymalizacji - szczególnie w przypadku takich rzeczy jak analiza ucieczki. W C ++, a następnie jako wartość jest na stosie i tak , kompilator nie trzeba go wykonać. Ponadto istnieją proste rzeczy, takie jak ciągła pamięć. Jeśli przydzielisz tablicę w C ++, to przydzielisz pojedynczą, ciągłą tablicę. Jeśli alokujesz tablicę w Javie, nie jest to wcale ciągłe, ponieważ tablica jest wypełniona tylko wskaźnikami, które mogą wskazywać w dowolnym miejscu. Jest to nie tylko narzut pamięci i czasu dla podwójnych pośrednich, ale także narzut pamięci podręcznej. Tego rodzaju semantyka języka Java po prostu wymusza, że musi być wolniejszy niż równoważny kod C ++.
Ostatecznie moje osobiste doświadczenie jest takie, że Java może być średnio o połowę szybsza niż C ++. Jednak realistycznie nie ma sposobu na wykonanie kopii zapasowej jakichkolwiek oświadczeń dotyczących wydajności bez niezwykle kompleksowego pakietu testów porównawczych, z powodu zasadniczo różnych algorytmów.
b. Czy byłoby możliwe stworzenie nowoczesnego tytułu AAA za pomocą Java?
Zakładam, że masz na myśli „grę”, a nie szansę. Po pierwsze, musisz napisać wszystko od zera, ponieważ prawie wszystkie istniejące biblioteki i infrastruktura docelowa C ++. Nie czyniąc go per se niemożliwym, z pewnością może przyczynić się solidnie do niewykonalności. Po drugie, nawet silniki C ++ z trudem mieszczą się w niewielkich ograniczeniach pamięciowych istniejących konsol - jeśli JVM istnieją nawet dla tych konsol - a gracze na PC oczekują nieco więcej pamięci. Tworzenie wydajnych gier AAA jest wystarczająco trudne w C ++, nie wiem, jak można to osiągnąć w Javie. Nikt nigdy nie napisał gry AAA ze znacznym czasem spędzonym w nieskompilowanym języku. Co więcej, byłby po prostu wyjątkowo podatny na błędy. Deterministyczne zniszczenie jest niezbędne, gdy mamy do czynienia np. Z zasobami GPU, aw Javie „
do. W jakich obszarach Java jest wolniejsza niż C ++, jeśli w ogóle? (tj. łamanie liczb, grafika lub po prostu dookoła)
Zdecydowanie wybrałbym wszystko dookoła. Wymuszona charakterystyka wszystkich obiektów Java oznacza, że Java ma znacznie więcej pośrednich i referencji niż C ++ - przykład, który podałem wcześniej z tablicami, ale dotyczy również na przykład wszystkich obiektów członkowskich. Tam, gdzie kompilator C ++ może wyszukiwać zmienną składową w stałym czasie, środowisko wykonawcze Java musi podążać za innym wskaźnikiem. Im więcej masz dostępu, tym wolniej będzie to robić i JIT nie może nic z tym zrobić.
Tam, gdzie C ++ może niemal natychmiast zwolnić i ponownie wykorzystać część pamięci, w Javie musisz poczekać na kolekcję, i mam nadzieję, że ta część nie wyszła z pamięci podręcznej, a z natury wymaganie większej ilości pamięci oznacza niższą wydajność pamięci podręcznej i stronicowania. Następnie spójrz na semantykę takich rzeczy jak boks i rozpakowanie. W Javie, jeśli chcesz odwoływać się do int, musisz dynamicznie przydzielić go. To nieodłączny marnotrawstwo w porównaniu do semantyki C ++.
Masz wtedy problem ogólny. W Javie można operować na obiektach ogólnych tylko poprzez dziedziczenie w czasie wykonywania. W C ++ szablony mają dosłownie zero kosztów ogólnych - coś, co Java nie może dopasować. Oznacza to, że cały ogólny kod w Javie jest z natury wolniejszy niż ogólny odpowiednik w C ++.
A potem dochodzisz do niezdefiniowanego zachowania. Wszyscy go nienawidzą, gdy ich program wykazuje UB i wszyscy żałują, że nie istniał. Jednak UB zasadniczo umożliwia optymalizacje, które nigdy nie mogą istnieć w Javie. Spójrz na ten post opisujący optymalizacje oparte na UB. Brak zdefiniowania zachowania oznacza, że implementacje mogą przeprowadzić więcej optymalizacji i zmniejszyć kod wymagany do sprawdzenia warunków, które byłyby niezdefiniowane w C ++, ale zdefiniowane w Javie.
Zasadniczo semantyka Java wskazuje, że jest to język wolniejszy niż C ++.
Czy Java jest teraz uważana za język skompilowany lub język interpretowany?
To naprawdę nie pasuje do żadnej z tych grup. Powiedziałbym, że zarządzanie jest naprawdę odrębną kategorią samą w sobie, chociaż powiedziałbym, że zdecydowanie bardziej przypomina język interpretowany niż język skompilowany. Co ważniejsze, są prawie dwa główne systemy zarządzane, JVM i CLR, a kiedy mówisz „zarządzany”, jest wystarczająco wyraźny.
Jakie są główne niedociągnięcia w Javie, które zostały usunięte od pierwszych dni?
Automatyczne boksowanie i rozpakowywanie jest jedyną rzeczą, o której wiem. Leki ogólne rozwiązują niektóre problemy, ale daleko od wielu.
Jakie są poważne niedociągnięcia w Javie, które wymagają jeszcze rozwiązania?
Ich leki generyczne są bardzo, bardzo słabe. Generyczne C # są znacznie silniejsze - choć oczywiście nie są też całkiem szablonami. Deterministyczne zniszczenie to kolejny poważny brak. Każda forma lambda / zamknięcie jest również poważnym problemem - możesz zapomnieć o funkcjonalnym API w Javie. I oczywiście zawsze występuje kwestia wydajności w tych obszarach, które ich potrzebują.