Rozumiem, że C / C ++ tworzy natywny kod do uruchomienia na określonej architekturze maszyny. I odwrotnie, języki takie jak Java i C # działają na maszynie wirtualnej, która oddziela architekturę natywną. Logicznie wydaje się niemożliwe, aby Java lub C # dorównywała szybkością C ++ z powodu tego pośredniego kroku, jednak powiedziano mi, że najnowsze kompilatory („hot spot”) mogą osiągnąć tę prędkość lub nawet ją przekroczyć.
Być może jest to bardziej pytanie kompilatora niż pytanie o język, ale czy ktoś może wyjaśnić prostym językiem angielskim, w jaki sposób jeden z tych języków maszyn wirtualnych może działać lepiej niż język ojczysty?
Odpowiedzi:
Ogólnie rzecz biorąc, C # i Java mogą być tak samo szybkie lub szybsze, ponieważ kompilator JIT - kompilator, który kompiluje twój IL przy pierwszym uruchomieniu - może dokonywać optymalizacji, których nie może skompilowany program C ++, ponieważ może wysyłać zapytania do maszyny. Potrafi określić, czy maszyna to Intel czy AMD; Pentium 4, Core Solo lub Core Duo; lub jeśli obsługuje SSE4 itp.
Program w C ++ musi być wcześniej skompilowany, zwykle z mieszanymi optymalizacjami, aby działał przyzwoicie na wszystkich maszynach, ale nie jest zoptymalizowany tak bardzo, jak mógłby być dla pojedynczej konfiguracji (tj. Procesora, zestawu instrukcji, innego sprzętu).
Ponadto niektóre funkcje językowe pozwalają kompilatorowi w C # i Javie przyjmować założenia dotyczące kodu, które pozwalają mu na optymalizację pewnych części, które po prostu nie są bezpieczne dla kompilatora C / C ++. Gdy masz dostęp do wskaźników, istnieje wiele optymalizacji, które po prostu nie są bezpieczne.
Również Java i C # mogą wykonywać alokacje sterty bardziej wydajnie niż C ++, ponieważ warstwa abstrakcji między modułem odśmiecania pamięci a kodem pozwala na jednoczesne wykonywanie całej kompresji sterty (dość kosztowna operacja).
Teraz nie mogę mówić za Javą w następnym punkcie, ale wiem, że na przykład C # faktycznie usunie metody i wywołania metod, gdy wie, że treść metody jest pusta. I będzie używać tego rodzaju logiki w całym kodzie.
Jak widać, istnieje wiele powodów, dla których niektóre implementacje C # lub Java będą szybsze.
Teraz to wszystko powiedziawszy, w C ++ można wprowadzić określone optymalizacje, które zniweczą wszystko, co można zrobić z C #, szczególnie w dziedzinie grafiki i zawsze, gdy jesteś blisko sprzętu. Wskaźniki czynią tutaj cuda.
Więc w zależności od tego, co piszesz, wybrałbym jedną lub drugą. Ale jeśli piszesz coś, co nie jest zależne od sprzętu (sterownik, gra wideo itp.), Nie martwiłbym się o wydajność C # (znowu nie mogę mówić o Javie). Wystarczy.
Po stronie Java @Swati wskazuje dobry artykuł:
https://www.ibm.com/developerworks/library/j-jtp09275
źródło
JIT vs. kompilator statyczny
Jak już powiedziano w poprzednich postach, JIT może kompilować IL / kod bajtowy do kodu natywnego w czasie wykonywania. Wspomniano o koszcie, ale nie do końca:
JIT ma jeden poważny problem polega na tym, że nie może skompilować wszystkiego: kompilacja JIT wymaga czasu, więc JIT skompiluje tylko niektóre części kodu, podczas gdy statyczny kompilator utworzy pełny natywny plik binarny: w przypadku niektórych programów statyczny kompilator z łatwością przewyższy JIT.
Oczywiście C # (lub Java lub VB) jest zwykle szybsze w tworzeniu realnego i niezawodnego rozwiązania niż C ++ (choćby dlatego, że C ++ ma złożoną semantykę, a standardowa biblioteka C ++, choć interesująca i potężna, jest dość słaba w porównaniu z pełną zakres biblioteki standardowej z .NET lub Java), więc zwykle różnica między C ++ a .NET lub Java JIT nie będzie widoczna dla większości użytkowników, a dla tych plików binarnych, które są krytyczne, nadal można wywołać przetwarzanie w C ++ z C # lub Java (nawet jeśli tego rodzaju natywne wywołania mogą same w sobie być dość kosztowne) ...
Metaprogramowanie w C ++
Zauważ, że zazwyczaj porównujesz kod środowiska uruchomieniowego C ++ z jego odpowiednikiem w C # lub Javie. Ale C ++ ma jedną cechę, która może przewyższać Java / C # po wyjęciu z pudełka, to jest metaprogramowanie szablonów: Przetwarzanie kodu będzie wykonywane w czasie kompilacji (w ten sposób znacznie wydłużając czas kompilacji), co skutkuje zerowym (lub prawie zerowym) uruchomieniem.
Widzę jeszcze realny wpływ na to (bawiłem się tylko koncepcjami, ale wtedy różnica wynosiła sekundy wykonania dla JIT i zero dla C ++), ale warto o tym wspomnieć, obok metaprogramowania szablonu faktów nie jest trywialny......
Natywne użycie pamięci w języku C ++
C ++ ma inne wykorzystanie pamięci niż Java / C #, a zatem ma inne zalety / wady.
Bez względu na optymalizację JIT, nic nie pójdzie tak szybko, jak bezpośredni dostęp wskaźnika do pamięci (zignorujmy na chwilę pamięci podręczne procesora itp.). Tak więc, jeśli masz w pamięci ciągłe dane, dostęp do nich przez wskaźniki C ++ (tj. Wskaźniki C ... dajmy Cezarowi należność) będzie przebiegał szybciej niż w Javie / C #. A C ++ ma RAII, co sprawia, że wiele operacji jest o wiele łatwiejszych niż w C # czy nawet w Javie. C ++ nie musi
using
ograniczać istnienia swoich obiektów. A C ++ nie mafinally
klauzuli. To nie jest błąd.:-)
I pomimo prymitywnych struktur w C #, obiekty „na stosie” w C ++ nie będą kosztować nic przy alokacji i niszczeniu i nie będą potrzebować GC do pracy w niezależnym wątku do czyszczenia.
Jeśli chodzi o fragmentację pamięci, alokatory pamięci w 2008 r. Nie są starymi alokatorami pamięci z 1980 r., Które zwykle porównuje się z alokacją GC: C ++ nie można przenieść w pamięci, to prawda, ale potem, jak w systemie plików Linuksa: kto potrzebuje dysku twardego defragmentacja, gdy fragmentacja nie występuje? Użycie odpowiedniego alokatora do odpowiedniego zadania powinno być częścią zestawu narzędzi dla programistów C ++. Teraz pisanie alokatorów nie jest łatwe, a wtedy większość z nas ma lepsze rzeczy do zrobienia, a dla większości zastosowań RAII lub GC są więcej niż wystarczająco dobre.
Obecnie model pamięci staje się nieco bardziej skomplikowany wraz z rozwojem technologii wielordzeniowej i wielowątkowej. W tej dziedzinie myślę, że .NET ma przewagę, a Java, jak mi powiedziano, ma przewagę. Niektórym hakerom „na gołym metalu” łatwo jest pochwalić swój kod „blisko maszyny”. Ale teraz znacznie trudniej jest stworzyć lepszy zestaw ręcznie, niż pozwolić kompilatorowi wykonać swoje zadanie. W przypadku C ++ kompilator był zwykle lepszy od hakera od dekady. W przypadku języków C # i Java jest to jeszcze łatwiejsze.
Mimo to, nowy standard C ++ 0x narzuci prosty model pamięci kompilatorom C ++, który ustandaryzuje (a tym samym uprości) efektywny kod wieloprocesorowy / równoległy / wątkowy w C ++ i uczyni optymalizacje łatwiejszymi i bezpieczniejszymi dla kompilatorów. Ale wtedy zobaczymy za kilka lat, czy jej obietnice zostaną spełnione.
C ++ / CLI a C # / VB.NET
Uwaga: W tej sekcji mówię o C ++ / CLI, to znaczy C ++ hostowanym przez .NET, a nie natywnym C ++.
W zeszłym tygodniu odbyłem szkolenie z optymalizacji .NET i odkryłem, że statyczny kompilator i tak jest bardzo ważny. Równie ważne niż JIT.
Ten sam kod skompilowany w C ++ / CLI (lub jego przodku, Managed C ++) może być razy szybszy niż ten sam kod utworzony w C # (lub VB.NET, którego kompilator tworzy taki sam IL niż C #).
Ponieważ statyczny kompilator C ++ był o wiele lepszy do tworzenia już zoptymalizowanego kodu niż C #.
Na przykład wstawianie funkcji w .NET jest ograniczone do funkcji, których kod bajtowy jest mniejszy lub równy 32 bajtom. Tak więc, część kodu w C # utworzy 40-bajtowy akcesor, który nigdy nie zostanie wstawiony przez JIT. Ten sam kod w C ++ / CLI wygeneruje 20-bajtowy akcesor, który zostanie wstawiony przez JIT.
Innym przykładem są zmienne tymczasowe, które są po prostu kompilowane przez kompilator C ++, a wciąż są wspomniane w IL utworzonym przez kompilator C #. Optymalizacja kompilacji statycznej w C ++ spowoduje mniej kodu, a tym samym ponownie zezwoli na bardziej agresywną optymalizację JIT.
Spekulowano, że powodem tego jest fakt, że kompilator C ++ / CLI korzystał z ogromnych technik optymalizacji natywnych kompilatorów C ++.
Wniosek
Uwielbiam C ++.
Ale o ile to widzę, C # lub Java są w sumie lepszym rozwiązaniem. Nie dlatego, że są szybsze niż C ++, ale dlatego, że po dodaniu ich cech stają się bardziej produktywne, wymagają mniej szkoleń i mają pełniejsze standardowe biblioteki niż C ++. A tak jak w przypadku większości programów, różnice w szybkości (w ten czy inny sposób) będą znikome ...
Edycja (2011-06-06)
Moje doświadczenie w C # / .NET
Mam teraz 5 miesięcy prawie wyłącznego profesjonalnego kodowania w C # (co składa się na moje CV już pełne C ++ i Java oraz odrobinę C ++ / CLI).
Grałem z WinForms (Ahem ...) i WCF (super!) I WPF (fajnie !!!! zarówno przez XAML, jak i surowy C #. WPF jest tak łatwy, że wierzę, że Swing po prostu nie może go porównać) i C # 4.0.
Wniosek jest taki, że chociaż łatwiej / szybciej jest stworzyć kod działający w C # / Javie niż w C ++, o wiele trudniej jest stworzyć mocny, bezpieczny i niezawodny kod w C # (a jeszcze trudniej w Javie) niż w C ++. Powodów jest mnóstwo, ale można je podsumować następująco:
using
nie jest tak łatwe i wydajne, ponieważ pisanie poprawnych implementacji Dispose jest trudne )readonly
i Javafinal
nigdzie nie są tak użyteczne jak C ++const
( nie ma sposobu, aby ujawnić złożone dane tylko do odczytu (na przykład Drzewo węzłów) w C # bez ogromnej pracy, podczas gdy jest to wbudowana funkcja C ++. Niezmienne dane to ciekawe rozwiązanie , ale nie wszystko można uczynić niezmiennymi, więc to zdecydowanie za mało ).Tak więc C # pozostaje przyjemnym językiem, o ile chcesz czegoś, co działa, ale frustrującym językiem w momencie, gdy chcesz czegoś, co zawsze i bezpiecznie działa.
Java jest jeszcze bardziej frustrująca, ponieważ ma te same problemy co C #, a nawet więcej: z powodu braku odpowiednika
using
słowa kluczowego w C # mój bardzo utalentowany kolega spędził zbyt dużo czasu, upewniając się, że jego zasoby są poprawnie zwolnione, podczas gdy odpowiednik w C ++ było łatwe (przy użyciu destruktorów i inteligentnych wskaźników).Wydaje mi się, że wzrost produktywności C # / Java jest widoczny w przypadku większości kodu ... aż do dnia, w którym kod powinien być tak doskonały, jak to tylko możliwe. Tego dnia poznasz ból. (nie uwierzysz, o co prosi nasz serwer i aplikacje GUI ...).
Informacje o języku Java i C ++ po stronie serwera
Utrzymywałem kontakt z zespołami serwerów (pracowałem między nimi 2 lata, zanim wróciłem do zespołu GUI), po drugiej stronie budynku i dowiedziałem się czegoś ciekawego.
W ostatnich latach trend polegał na tym, że aplikacje serwerowe Java miały zastąpić stare aplikacje serwerowe C ++, ponieważ Java ma wiele struktur / narzędzi i jest łatwa w utrzymaniu, wdrażaniu itp.
... Dopóki problem niskiej latencji nie pojawił się w ostatnich miesiącach. Następnie aplikacje serwerowe Java, niezależnie od optymalizacji podjętej przez nasz wykwalifikowany zespół Java, po prostu i czysto przegrały wyścig ze starym, niezbyt zoptymalizowanym serwerem C ++.
Obecnie podjęto decyzję o pozostawieniu serwerów Java do wspólnego użytku, gdzie wydajność, choć nadal ważna, nie jest zainteresowana celem o niskim opóźnieniu, i agresywną optymalizację i tak już szybszych aplikacji serwerowych C ++ pod kątem potrzeb o niskim opóźnieniu i bardzo niskim opóźnieniu.
Wniosek
Nic nie jest tak proste, jak oczekiwano.
Java, a nawet C #, to fajne języki, z obszernymi standardowymi bibliotekami i frameworkami, w których można szybko kodować i uzyskać wyniki bardzo szybko.
Ale kiedy potrzebujesz surowej mocy, potężnych i systematycznych optymalizacji, silnej obsługi kompilatorów, potężnych funkcji językowych i absolutnego bezpieczeństwa, Java i C # utrudniają zdobycie ostatniego brakującego, ale krytycznego procenta jakości, którego potrzebujesz, aby pozostać nad konkurencją.
To tak, jakbyś potrzebował mniej czasu i mniej doświadczonych programistów w C # / Java niż w C ++, aby stworzyć kod średniej jakości, ale z drugiej strony, w momencie, gdy potrzebujesz kodu doskonałej do doskonałej jakości, nagle uzyskanie wyników było łatwiejsze i szybsze w C ++.
Oczywiście jest to moja własna percepcja, być może ograniczona do naszych konkretnych potrzeb.
Ale nadal dzieje się tak dzisiaj, zarówno w zespołach GUI, jak i zespołach po stronie serwera.
Oczywiście zaktualizuję ten post, jeśli wydarzy się coś nowego.
Edytuj (2011-06-22)
Źródła:
Edytuj (2011-09-20)
Źródła:
źródło
Ilekroć mówię o wydajności zarządzanej i niezarządzanej, lubię wskazywać na serię, w której Rico (i Raymond) porównali wersje C ++ i C # słownika chińskiego / angielskiego. Ta wyszukiwarka Google pozwoli ci przeczytać samemu, ale podoba mi się podsumowanie Rico.
Dla mnie najważniejsze jest to, że wersja niezarządzana wymagała 6 poprawek, aby pokonać wersję zarządzaną, która była prostym portem oryginalnego niezarządzanego kodu. Jeśli potrzebujesz wszystkiego do ostatniego kawałka wydajności (i masz czas i doświadczenie, aby to osiągnąć), będziesz musiał przejść bez zarządzania, ale dla mnie skorzystam z przewagi rzędu wielkości, jaką mam w pierwszych wersjach nad 33. % Zyskuję, jeśli spróbuję 6 razy.
źródło
Kompilacja pod kątem określonych optymalizacji procesora jest zwykle przeceniana. Po prostu weź program w C ++ i skompiluj go z optymalizacją dla Pentium PRO i uruchom na Pentium 4. Następnie dokonaj ponownej kompilacji z Optimize dla Pentium 4. Spędzałem długie popołudnia robiąc to z kilkoma programami. Ogólne wyniki? Zwykle wzrost wydajności o mniej niż 2-3%. Więc teoretyczne zalety JIT są prawie żadne. Większość różnic w wydajności można zaobserwować tylko podczas korzystania z funkcji przetwarzania danych skalarnych, co i tak będzie wymagało ręcznego dostrojenia, aby osiągnąć maksymalną wydajność. Tego rodzaju optymalizacje są powolne i kosztowne w wykonaniu, co sprawia, że czasami nie nadają się do JIT.
W świecie rzeczywistym i rzeczywistych aplikacjach C ++ jest nadal zwykle szybszy niż java, głównie ze względu na mniejszy rozmiar pamięci, co skutkuje lepszą wydajnością pamięci podręcznej.
Jednak aby wykorzystać wszystkie możliwości C ++, programista musi ciężko pracować. Możesz osiągnąć lepsze wyniki, ale musisz do tego użyć swojego mózgu. C ++ to język, który postanowił zaprezentować Ci więcej narzędzi, pobierając cenę, którą musisz się ich nauczyć, aby móc dobrze używać języka.
źródło
JIT (Just In Time Compiling) może być niesamowicie szybki, ponieważ optymalizuje pod kątem platformy docelowej.
Oznacza to, że może wykorzystać każdą sztuczkę kompilatora, którą obsługuje Twój procesor, niezależnie od tego, na jakim procesorze programista napisał kod.
Podstawowa koncepcja JIT .NET działa w następujący sposób (mocno uproszczona):
Wywołanie metody po raz pierwszy:
Wywołanie metody po raz drugi:
Jak widać, za drugim razem jest to praktycznie ten sam proces, co C ++, z wyjątkiem zalet optymalizacji w czasie rzeczywistym.
To powiedziawszy, nadal istnieją inne ogólne problemy, które spowalniają zarządzany język, ale JIT bardzo pomaga.
źródło
Podoba mi się odpowiedź Oriona Adriana , ale jest jeszcze jeden aspekt.
To samo pytanie zostało postawione dziesiątki lat temu w kwestii języka asemblera i języków „ludzkich”, takich jak FORTRAN. Część odpowiedzi jest podobna.
Tak, program w C ++ może być szybszy niż C # na dowolnym (nietrywialnym?) Algorytmie, ale program w C # często będzie równie szybki lub szybszy niż „naiwna” implementacja w C ++ i zoptymalizowana wersja w C ++ będzie trwało dłużej, a wersja C # może być lepsza od wersji z bardzo małym marginesem. Czy naprawdę warto?
Będziesz musiał odpowiadać na to pytanie indywidualnie.
To powiedziawszy, od dawna jestem fanem C ++ i myślę, że jest to niesamowicie wyrazisty i potężny język - czasami niedoceniany. Ale w przypadku wielu problemów „prawdziwego życia” (dla mnie osobiście oznacza to „takie, za których rozwiązanie dostaję wynagrodzenie”), C # wykona zadanie szybciej i bezpieczniej.
Największa kara, jaką płacisz? Wiele programów .NET i Java to świnie pamięci. Widziałem, jak aplikacje .NET i Java zajmują „setki” megabajtów pamięci, podczas gdy programy C ++ o podobnej złożoności ledwo zajmują „dziesiątki” MB.
źródło
Nie jestem pewien, jak często okaże się, że kod Java będzie działał szybciej niż C ++, nawet z Hotspotem, ale spróbuję wyjaśnić, jak to się może stać.
Pomyśl o skompilowanym kodzie Javy jako o zinterpretowanym języku maszynowym JVM. Kiedy procesor Hotspot zauważy, że pewne fragmenty skompilowanego kodu będą używane wielokrotnie, przeprowadza optymalizację kodu maszynowego. Ponieważ ręka-tuning Zgromadzenie jest prawie zawsze szybciej niż kod C ++ skompilowany, to OK, aby postać, która programowo dostrojony kod maszyna nie będzie zbyt złe.
Tak więc, w przypadku wysoce powtarzalnego kodu, mogłem zobaczyć, gdzie Hotspot JVM może uruchamiać Javę szybciej niż C ++ ... dopóki nie włączy się zbieranie śmieci. :)
źródło
Since hand-tuning Assembly is almost always faster than C++ compiled code
? Co masz na myśli przez „ręczne dostrajanie zestawu” i „skompilowany kod C ++”?Ogólnie algorytm programu będzie znacznie ważniejszy dla szybkości działania aplikacji niż język . Możesz zaimplementować słaby algorytm w dowolnym języku, w tym w C ++. Mając to na uwadze, generalnie będziesz w stanie napisać kod działający szybciej w języku, który pomoże Ci zaimplementować bardziej wydajny algorytm.
Języki wyższego poziomu radzą sobie w tym bardzo dobrze, zapewniając łatwiejszy dostęp do wielu wydajnych, gotowych struktur danych i zachęcając do praktyk, które pomogą Ci uniknąć nieefektywnego kodu. Oczywiście czasami mogą również ułatwić napisanie kilku naprawdę powolnego kodu, więc nadal musisz znać swoją platformę.
Ponadto C ++ dogania „nowe” (zwróć uwagę na cudzysłowy) funkcje, takie jak kontenery STL, automatyczne wskaźniki itp. - zobacz na przykład bibliotekę boost. Czasami może się okazać, że najszybszy sposób wykonania jakiegoś zadania wymaga techniki takiej jak arytmetyka wskaźników, która jest zabroniona w języku wyższego poziomu - chociaż zazwyczaj pozwalają one wywołać bibliotekę napisaną w języku, który może ją zaimplementować zgodnie z potrzebami .
Najważniejsze jest, aby znać język, którego używasz, powiązany z nim interfejs API, co potrafi i jakie są jego ograniczenia.
źródło
Ja też nie wiem ... moje programy w języku Java są zawsze powolne. :-) Tak naprawdę nigdy nie zauważyłem, że programy C # są szczególnie wolne.
źródło
Oto kolejny ciekawy test porównawczy, który możesz wypróbować na własnym komputerze.
Porównuje ASM, VC ++, C #, Silverlight, aplet Java, Javascript, Flash (AS3)
Demo prędkości wtyczki Roozz
Należy pamiętać, że szybkość javascript jest bardzo różna w zależności od przeglądarki, która go wykonuje. To samo dotyczy Flash i Silverlight, ponieważ te wtyczki działają w tym samym procesie co przeglądarka hostingowa. Ale wtyczka Roozz obsługuje standardowe pliki .exe, które działają we własnym procesie, więc przeglądarka hostująca nie ma wpływu na szybkość.
źródło
Należy zdefiniować „wydajność lepiej niż…”. Cóż, wiem, pytałeś o prędkość, ale to nie wszystko się liczy.
I tak dalej, jest stronniczy, tak;)
Dzięki C # i Javie płacisz cenę za to, co dostajesz (szybsze kodowanie, automatyczne zarządzanie pamięcią, duża biblioteka i tak dalej). Ale nie masz zbyt wiele miejsca na targowanie się o szczegóły: weź cały pakiet albo nic.
Nawet jeśli te języki mogą zoptymalizować jakiś kod, aby był wykonywany szybciej niż kod skompilowany, całe podejście jest (IMHO) nieefektywne. Wyobraź sobie, że codziennie jeździsz ciężarówką 5 mil do swojego miejsca pracy! Jest wygodny, dobrze się czujesz, jesteś bezpieczny (strefa ekstremalnego zgniotu), a po pewnym czasie nadepnięcia na gaz będzie nawet tak szybki jak zwykły samochód! Dlaczego nie wszyscy mamy ciężarówkę do jazdy do pracy? ;)
W C ++ dostajesz to, za co płacisz, nie więcej, nie mniej.
Cytując Bjarne Stroustrup: „C ++ to mój ulubiony język do zbierania śmieci, ponieważ generuje tak mało śmieci” tekst linku
źródło
times
na powłoce. Żeby sprawdzał cały program, a nie tylko jeden aspekt. Czy wyniki są podobne?Kod wykonywalny utworzony z kompilatora Javy lub C # nie jest interpretowany - jest kompilowany do kodu natywnego „just in time” (JIT). Tak więc przy pierwszym napotkaniu kodu w programie Java / C # podczas wykonywania występuje pewien narzut, ponieważ „kompilator środowiska uruchomieniowego” (znany również jako kompilator JIT) zamienia kod bajtowy (Java) lub kod IL (C #) na natywne instrukcje maszynowe. Jednak następnym razem, gdy ten kod zostanie napotkany, gdy aplikacja nadal działa, kod natywny jest wykonywany natychmiast. Wyjaśnia to, jak niektóre programy Java / C # wydają się początkowo wolne, ale im dłużej działają, działają lepiej. Dobrym przykładem jest witryna sieci Web ASP.Net. Podczas pierwszego dostępu do witryny sieci Web może to być nieco wolniejsze, ponieważ kod C # jest kompilowany do kodu natywnego przez kompilator JIT.
źródło
Kilka dobrych odpowiedzi na konkretne pytanie, które zadałeś. Chciałbym się cofnąć i spojrzeć na szerszą perspektywę.
Należy pamiętać, że na postrzeganie przez użytkownika szybkości pisania oprogramowania wpływa wiele innych czynników niż tylko to, jak dobrze kodegen optymalizuje. Oto kilka przykładów:
Ręczne zarządzanie pamięcią jest trudne do wykonania poprawnie (brak wycieków), a jeszcze trudniejsze do wykonania efektywnie (zwolnij pamięć wkrótce po zakończeniu). Ogólnie rzecz biorąc, użycie GC daje większe prawdopodobieństwo stworzenia programu, który dobrze zarządza pamięcią. Czy chcesz pracować bardzo ciężko i opóźniać dostarczanie oprogramowania, próbując prześcignąć GC?
Mój C # jest łatwiejszy do odczytania i zrozumienia niż mój C ++. Mam też więcej sposobów, aby przekonać się, że mój kod C # działa poprawnie. Oznacza to, że mogę zoptymalizować moje algorytmy przy mniejszym ryzyku wprowadzania błędów (a użytkownicy nie lubią oprogramowania, które ulega awarii, nawet jeśli robi to szybko!)
Mogę tworzyć swoje oprogramowanie szybciej w C # niż w C ++. To uwalnia czas na pracę nad wydajnością i nadal dostarcza oprogramowanie na czas.
Łatwiej jest napisać dobry interfejs użytkownika w języku C # niż w C ++, więc bardziej prawdopodobne jest, że będę w stanie przenieść pracę do tła, podczas gdy interfejs użytkownika pozostaje responsywny, lub zapewnić postęp lub interfejs dźwiękowy, gdy program musi na chwilę blokować. To nie przyspiesza niczego, ale sprawia, że użytkownicy są szczęśliwsi z czekania.
Wszystko, co powiedziałem o C #, prawdopodobnie odnosi się do Javy, po prostu nie mam doświadczenia, żeby to powiedzieć na pewno.
źródło
Jeśli jesteś programistą Java / C # uczącym się C ++, będziesz kusić, aby dalej myśleć w kategoriach Java / C # i tłumaczyć dosłownie składnię C ++. W takim przypadku uzyskasz tylko wspomniane wcześniej zalety kodu natywnego w porównaniu z interpretacją / JIT. Aby uzyskać największy wzrost wydajności w C ++ w porównaniu z Java / C #, musisz nauczyć się myśleć w C ++ i projektować kod specjalnie, aby wykorzystać mocne strony C ++.
Parafrazując Edsgera Dijkstrę : [twój pierwszy język] okalecza umysł nie do wyzdrowienia.
Parafrazując Jeffa Atwooda : możesz pisać [swój pierwszy język] w dowolnym nowym języku.
źródło
Jedną z najważniejszych optymalizacji JIT jest wstawianie metody. Java może nawet wbudować metody wirtualne, jeśli gwarantuje poprawność działania. Ten rodzaj optymalizacji zwykle nie może być przeprowadzony przez standardowe kompilatory statyczne, ponieważ wymaga analizy całego programu, co jest trudne ze względu na oddzielną kompilację (w przeciwieństwie do JIT ma dostępny cały program). Wbudowanie metod poprawia inne optymalizacje, zapewniając większe bloki kodu do optymalizacji.
Standardowa alokacja pamięci w Javie / C # jest również szybsza, a cofanie alokacji (GC) nie jest dużo wolniejsze, ale tylko mniej deterministyczne.
źródło
free
idelete
nie są deterministyczne, a GC można uczynić deterministycznymi, nie przydzielając.Jest mało prawdopodobne, aby języki maszyn wirtualnych przewyższały języki skompilowane, ale mogą zbliżyć się na tyle blisko, że nie ma to znaczenia, z (przynajmniej) następujących powodów (mówię tutaj o Javie, ponieważ nigdy nie robiłem C #).
1 / Środowisko wykonawcze Java jest zwykle w stanie wykryć fragmenty kodu, które są często uruchamiane i wykonać kompilację just-in-time (JIT) tych sekcji, aby w przyszłości działały z pełną szybkością kompilacji.
2 / Ogromne części bibliotek Java są kompilowane w taki sposób, że wywołanie funkcji biblioteki powoduje wykonanie skompilowanego kodu, a nie interpretacji. Możesz zobaczyć kod (w C), pobierając OpenJDK.
3 / O ile nie wykonujesz masowych obliczeń, przez większość czasu Twój program czeka na dane wejściowe od bardzo powolnego (względnie mówiącego) człowieka.
4 / Ponieważ wiele sprawdzania poprawności kodu bajtowego Javy jest wykonywanych w czasie ładowania klasy, normalne obciążenie związane z kontrolą w czasie wykonywania jest znacznie zmniejszone.
5 / W najgorszym przypadku kod wymagający dużej wydajności może zostać wyodrębniony do skompilowanego modułu i wywołany z Javy (patrz JNI), aby działał z pełną prędkością.
Podsumowując, kod bajtowy Java nigdy nie przewyższy natywnego języka maszynowego, ale istnieją sposoby na złagodzenie tego problemu. Dużą zaletą Javy (jak ja to widzę) jest OGROMNA standardowa biblioteka i wieloplatformowy charakter.
źródło
Orion Adrian , pozwól, że odwrócę twój post, aby zobaczyć, jak bezpodstawne są twoje uwagi, ponieważ wiele można powiedzieć o C ++. A powiedzenie, że kompilator Java / C # optymalizuje puste funkcje, naprawdę sprawia, że brzmisz tak, jak ty nie był moim ekspertem w optymalizacji, ponieważ a) dlaczego prawdziwy program miałby zawierać puste funkcje, z wyjątkiem naprawdę złego starszego kodu, b) tak naprawdę nie jest optymalizacja czarnych i krwawych krawędzi.
Poza tym wyrażeniem, bezczelnie narzekałeś na wskaźniki, ale czy obiekty w Javie i C # nie działają w zasadzie jak wskaźniki C ++? Czy nie mogą się pokrywać? Czy nie mogą być nieważne? C (i większość implementacji C ++) ma słowo kluczowe restrykcyjne, oba mają typy wartości, C ++ ma odniesienie do wartości z gwarancją niezerową. Co oferują Java i C #?
>>>>>>>>>>
Ogólnie rzecz biorąc, C i C ++ mogą być równie szybkie lub szybsze, ponieważ kompilator AOT - kompilator, który kompiluje kod przed wdrożeniem, raz na zawsze, na serwerze kompilacji z wieloma rdzeniami o dużej ilości pamięci - może wprowadzać optymalizacje, które program skompilowany w C # nie może, ponieważ ma na to mnóstwo czasu. Kompilator może określić, czy maszyna to Intel czy AMD; Pentium 4, Core Solo lub Core Duo; lub jeśli obsługuje SSE4 itp., a Twój kompilator nie obsługuje wysyłania w czasie wykonywania, możesz rozwiązać ten problem samodzielnie, wdrażając kilka wyspecjalizowanych plików binarnych.
Program AC # jest zwykle kompilowany po uruchomieniu go, aby działał przyzwoicie na wszystkich maszynach, ale nie jest zoptymalizowany tak bardzo, jak mógłby być dla pojedynczej konfiguracji (tj. Procesora, zestawu instrukcji, innego sprzętu) i musi spędzać trochę czasu pierwszy. Funkcje takie jak rozszczepianie pętli, inwersja pętli, automatyczna wektoryzacja, optymalizacja całego programu, rozszerzanie szablonów, IPO i wiele innych, są bardzo trudne do rozwiązania w całości i całkowicie w sposób, który nie denerwuje użytkownika końcowego.
Ponadto niektóre funkcje językowe pozwalają kompilatorowi w C ++ lub C na przyjmowanie założeń dotyczących kodu, co pozwala mu na optymalizację pewnych części, które nie są bezpieczne dla kompilatora Java / C #. Kiedy nie masz dostępu do pełnego identyfikatora typu leków generycznych lub gwarantowanego przepływu programu, istnieje wiele optymalizacji, które po prostu nie są bezpieczne.
Również C ++ i C wykonują wiele alokacji stosu naraz z tylko jedną inkrementacją rejestru, co z pewnością jest bardziej wydajne niż alokacje Javas i C #, jeśli chodzi o warstwę abstrakcji między modułem odśmiecania pamięci a kodem.
Teraz nie mogę mówić o Javie w tym następnym punkcie, ale wiem, że na przykład kompilatory C ++ faktycznie usuwają metody i wywołania metod, gdy wie, że treść metody jest pusta, wyeliminuje typowe podwyrażenia, może spróbować ponownie aby znaleźć optymalne wykorzystanie rejestru, nie wymusza sprawdzania granic, autowektoryzuje pętle i wewnętrzne pętle oraz odwraca wewnętrzne do zewnętrznych, usuwa warunkowe z pętli, dzieli i przerywa pętle. Rozszerzy std :: vector na natywne tablice zerowe, tak jak zrobiłbyś to w C. Dokonuje optymalizacji między procedurami. Konstruuje wartości zwracane bezpośrednio w witrynie wywołującej. Będzie zwijać i propagować wyrażenia. Zmieni kolejność danych w sposób przyjazny dla pamięci podręcznej. Będzie robić wątki skokowe. Pozwala na pisanie znaczników promieni czasu kompilacji bez narzutu czasu wykonania. Spowoduje to bardzo kosztowne optymalizacje oparte na wykresach. Zredukuje siłę, jeśli zastąpi niektóre kody składniowo całkowicie nierównym, ale semantycznie równoważnym kodem (stary "xor foo, foo" jest po prostu najprostszą, choć przestarzałą optymalizacją tego rodzaju). Jeśli o to poprosisz, możesz pominąć standardy zmiennoprzecinkowe IEEE i włączyć jeszcze więcej optymalizacji, takich jak zmiana kolejności operandów zmiennoprzecinkowych. Po wymasowaniu i zmasakrowaniu kodu może powtórzyć cały proces, ponieważ często pewne optymalizacje stanowią podstawę do jeszcze niektórych optymalizacji. Może też po prostu spróbować ponownie z potasowanymi parametrami i zobaczyć, jak inny wariant osiąga wyniki w swoim wewnętrznym rankingu. I będzie używać tego rodzaju logiki w całym kodzie. gdyby zastępował pewne kody składniowo całkowicie nierównym, ale semantycznie równoważnym kodem (stary „xor foo, foo” jest po prostu najprostszą, choć przestarzałą optymalizacją tego rodzaju). Jeśli o to poprosisz, możesz pominąć standardy zmiennoprzecinkowe IEEE i włączyć jeszcze więcej optymalizacji, takich jak zmiana kolejności operandów zmiennoprzecinkowych. Po wymasowaniu i zmasakrowaniu kodu może powtórzyć cały proces, ponieważ często pewne optymalizacje stanowią podstawę do jeszcze niektórych optymalizacji. Może też po prostu spróbować ponownie z potasowanymi parametrami i zobaczyć, jak inny wariant osiąga wyniki w swoim wewnętrznym rankingu. I będzie używać tego rodzaju logiki w całym kodzie. gdyby zastępował pewne kody składniowo całkowicie nierównym, ale semantycznie równoważnym kodem (stary „xor foo, foo” jest po prostu najprostszą, choć przestarzałą optymalizacją tego rodzaju). Jeśli o to poprosisz, możesz pominąć standardy zmiennoprzecinkowe IEEE i włączyć jeszcze więcej optymalizacji, takich jak zmiana kolejności operandów zmiennoprzecinkowych. Po wymasowaniu i zmasakrowaniu kodu może powtórzyć cały proces, ponieważ często pewne optymalizacje stanowią podstawę do jeszcze niektórych optymalizacji. Może też po prostu spróbować ponownie z potasowanymi parametrami i zobaczyć, jak inny wariant osiąga wyniki w swoim wewnętrznym rankingu. I będzie używać tego rodzaju logiki w całym kodzie. Jeśli o to poprosisz, możesz pominąć standardy zmiennoprzecinkowe IEEE i włączyć jeszcze więcej optymalizacji, takich jak zmiana kolejności operandów zmiennoprzecinkowych. Po wymasowaniu i zmasakrowaniu kodu może powtórzyć cały proces, ponieważ często pewne optymalizacje stanowią podstawę do jeszcze niektórych optymalizacji. Może też po prostu spróbować ponownie z potasowanymi parametrami i zobaczyć, jak inny wariant osiąga wyniki w swoim wewnętrznym rankingu. I będzie używać tego rodzaju logiki w całym kodzie. Jeśli o to poprosisz, możesz pominąć standardy zmiennoprzecinkowe IEEE i włączyć jeszcze więcej optymalizacji, takich jak zmiana kolejności operandów zmiennoprzecinkowych. Po wymasowaniu i zmasakrowaniu kodu może powtórzyć cały proces, ponieważ często pewne optymalizacje stanowią podstawę do jeszcze niektórych optymalizacji. Może też po prostu spróbować ponownie z potasowanymi parametrami i zobaczyć, jak inny wariant osiąga wyniki w swoim wewnętrznym rankingu. I będzie używać tego rodzaju logiki w całym kodzie. Może też po prostu spróbować ponownie z potasowanymi parametrami i zobaczyć, jak inny wariant osiąga wyniki w swoim wewnętrznym rankingu. I będzie używać tego rodzaju logiki w całym kodzie. Może też po prostu spróbować ponownie z potasowanymi parametrami i zobaczyć, jak inny wariant osiąga wyniki w swoim wewnętrznym rankingu. I będzie używać tego rodzaju logiki w całym kodzie.
Jak widać, istnieje wiele powodów, dla których niektóre implementacje C ++ lub C będą szybsze.
To wszystko powiedziawszy, wiele optymalizacji można wprowadzić w C ++, które zniweczą wszystko, co można zrobić w C #, szczególnie w dziedzinie obliczania liczb, w czasie rzeczywistym i prawie metalowym, ale nie tylko tam. Nie musisz nawet dotykać ani jednego wskaźnika, aby przejść długą drogę.
Więc w zależności od tego, co piszesz, wybrałbym jedną lub drugą. Ale jeśli piszesz coś, co nie jest zależne od sprzętu (sterownik, gra wideo itp.), Nie martwiłbym się o wydajność C # (znowu nie mogę mówić o Javie). Wystarczy.
<<<<<<<<<<
Ogólnie niektóre uogólnione argumenty mogą brzmieć fajnie w określonych postach, ale generalnie nie brzmią na pewno wiarygodnie.
W każdym razie, aby zawrzeć pokój: AOT jest świetny, podobnie jak JIT . Jedyną poprawną odpowiedzią może być: To zależy. A prawdziwi inteligentni ludzie wiedzą, że i tak możesz wykorzystać to, co najlepsze z obu światów.
źródło
Może się to zdarzyć tylko wtedy, gdy interpreter języka Java tworzy kod maszynowy, który jest faktycznie lepiej zoptymalizowany niż kod maszynowy generowany przez kompilator dla pisanego przez Ciebie kodu C ++, do tego stopnia, że kod C ++ jest wolniejszy niż język Java i koszt interpretacji.
Jednak szanse, że tak się stanie, są dość niskie - chyba że Java ma bardzo dobrze napisaną bibliotekę, a ty masz własną źle napisaną bibliotekę C ++.
źródło
W rzeczywistości C # tak naprawdę nie działa na maszynie wirtualnej, tak jak robi to Java. IL jest kompilowany do języka asemblera, który jest całkowicie rodzimym kodem i działa z taką samą prędkością jak kod natywny. Możesz przeprowadzić wstępne JIT aplikacji .NET, która całkowicie usuwa koszt JIT, a następnie uruchamiasz całkowicie natywny kod.
Spowolnienie z .NET nadejdzie nie dlatego, że kod .NET jest wolniejszy, ale dlatego, że robi znacznie więcej za kulisami, aby robić takie rzeczy, jak zbieranie śmieci, sprawdzanie referencji, przechowywanie kompletnych ramek stosu itp. Może to być dość potężne i pomocne, gdy tworzenie aplikacji, ale wiąże się to również z kosztami. Zauważ, że możesz zrobić to wszystko w programie C ++ (większość podstawowych funkcji .NET to w rzeczywistości kod .NET, który możesz wyświetlić w programie ROTOR). Jeśli jednak ręcznie napisałeś tę samą funkcjonalność, prawdopodobnie skończyłbyś z dużo wolniejszym programem, ponieważ środowisko wykonawcze .NET zostało zoptymalizowane i precyzyjnie dostrojone.
To powiedziawszy, jedną z mocnych stron zarządzanego kodu jest to, że można go w pełni zweryfikować, tj. możesz sprawdzić, czy kod nigdy nie uzyska dostępu do pamięci innego procesu ani nie zrobi żadnych rzeczy przed wykonaniem go. Firma Microsoft dysponuje prototypem badawczym w pełni zarządzanego systemu operacyjnego, który nieoczekiwanie wykazał, że w 100% zarządzane środowisko może działać znacznie szybciej niż jakikolwiek nowoczesny system operacyjny, wykorzystując tę weryfikację do wyłączania funkcji zabezpieczeń, które nie są już potrzebne zarządzanym programom (w niektórych przypadkach mówimy około 10x). Radio SE ma świetny odcinek opowiadający o tym projekcie.
źródło
W niektórych przypadkach kod zarządzany może być w rzeczywistości szybszy niż kod natywny. Na przykład algorytmy usuwania pamięci typu „mark-and-sweep” pozwalają środowiskom takim jak JRE lub CLR na zwolnienie dużej liczby krótkotrwałych (zwykle) obiektów w jednym przebiegu, podczas gdy większość obiektów sterty C / C ++ jest zwalnianych jeden na czas.
Z Wikipedii :
To powiedziawszy, napisałem dużo C # i dużo C ++ i przeprowadziłem wiele testów porównawczych. Z mojego doświadczenia wynika, C ++ jest o wiele szybciej niż C #, na dwa sposoby: (1) jeśli wziąć jakiś kod, który został napisany w języku C #, port go do C ++ natywny kod ma tendencję do być szybciej. O ile szybciej? Cóż, jest bardzo różny, ale nie jest niczym niezwykłym, że widzi się 100% poprawę prędkości. (2) W niektórych przypadkach wyrzucanie elementów bezużytecznych może znacznie spowolnić zarządzaną aplikację. NET CLR wykonuje okropną robotę z dużymi stosami (powiedzmy> 2 GB) i może spędzać dużo czasu w GC - nawet w aplikacjach, które mają niewiele - lub nawet nie mają - obiektów o pośrednim okresie życia.
Oczywiście, w większości przypadków, z którymi się spotkałem, języki zarządzane są wystarczająco szybkie, z długiej perspektywy, a konserwacja i kompromis w zakresie kodowania dla dodatkowej wydajności C ++ po prostu nie jest dobry.
źródło
Oto interesujący test porównawczy http://zi.fi/shootout/
źródło
W rzeczywistości maszyna JVM HotSpot firmy Sun używa wykonywania „w trybie mieszanym”. Interpretuje kod bajtowy metody, dopóki nie ustali (zwykle za pomocą pewnego rodzaju licznika), że określony blok kodu (metoda, pętla, blok try-catch itp.) Będzie często wykonywany, a następnie JIT go kompiluje. Czas wymagany do skompilowania metody JIT często trwa dłużej niż w przypadku interpretacji metody, jeśli jest to metoda rzadko uruchamiana. Wydajność jest zwykle wyższa w „trybie mieszanym”, ponieważ JVM nie marnuje czasu na kod JIT, który jest rzadko, jeśli w ogóle, uruchamiany. C # i .NET tego nie robią. .NET JIT wszystko, co często marnuje czas.
źródło
Przeczytaj o Dynamo HP Labs , interpreterze PA-8000, który działa na PA-8000 i często uruchamia programy szybciej niż natywnie. Wtedy wcale nie będzie to zaskakujące!
Nie myśl o tym jako o „kroku pośrednim” - uruchomienie programu obejmuje już wiele innych kroków w dowolnym języku.
Często sprowadza się do:
programy mają gorące punkty, więc nawet jeśli wolniej wykonujesz 95% całego kodu, który musisz uruchomić, nadal możesz być konkurencyjny pod względem wydajności, jeśli jesteś szybszy na gorących 5%
HLL wie więcej o twoich zamiarach niż LLL, jak C / C ++, dzięki czemu może generować bardziej zoptymalizowany kod (OCaml ma jeszcze więcej, aw praktyce często jest nawet szybszy)
kompilator JIT ma wiele informacji, których nie ma kompilator statyczny (na przykład rzeczywiste dane, które masz tym razem)
kompilator JIT może wykonywać optymalizacje w czasie wykonywania, których nie mogą robić tradycyjne konsolidatory (takie jak zmiana kolejności gałęzi, aby typowy przypadek był płaski lub wbudowane wywołania bibliotek)
Podsumowując, C / C ++ są dość kiepskimi językami pod względem wydajności: jest stosunkowo mało informacji o typach danych, nie ma informacji o danych i nie ma dynamicznego środowiska uruchomieniowego, które pozwala na wiele na drodze optymalizacji w czasie wykonywania.
źródło
Możesz uzyskać krótkie serie, gdy Java lub CLR są szybsze niż C ++, ale ogólnie wydajność jest gorsza przez cały okres użytkowania aplikacji: zobacz www.codeproject.com/KB/dotnet/RuntimePerformance.aspx, aby uzyskać niektóre wyniki.
źródło
Oto odpowiedź od Cliff Click: http://www.azulsystems.com/blog/cliff/2009-09-06-java-vs-c-performanceagain
źródło
To jest nielogiczne. Korzystanie z reprezentacji pośredniej nie powoduje z natury degradacji wydajności. Na przykład llvm-gcc kompiluje C i C ++ przez LLVM IR (który jest wirtualną maszyną z nieskończonym rejestrem) do kodu natywnego i osiąga doskonałą wydajność (często przewyższając GCC).
Oto kilka przykładów:
Maszyny wirtualne z kompilacją JIT ułatwiają generowanie kodu w czasie wykonywania (np.
System.Reflection.Emit
Na .NET), dzięki czemu można skompilować wygenerowany kod w locie w językach takich jak C # i F #, ale muszą uciec się do pisania stosunkowo wolnego interpretera w C lub C ++. Na przykład, aby zaimplementować wyrażenia regularne.Części maszyny wirtualnej (np. Bariera zapisu i alokator) są często napisane w asemblerze ręcznie kodowanym, ponieważ C i C ++ nie generują wystarczająco szybkiego kodu. Jeśli program kładzie nacisk na te części systemu, to prawdopodobnie może przewyższać wszystko, co można napisać w C lub C ++.
Dynamiczne łączenie kodu natywnego wymaga zgodności z ABI, co może utrudniać wydajność i eliminuje optymalizację całego programu, podczas gdy łączenie jest zwykle odraczane na maszynach wirtualnych i może korzystać z optymalizacji całego programu (takich jak zreifikowane typy generyczne .NET).
Chciałbym również odnieść się do niektórych problemów z wysoko ocenianą odpowiedzią Paercebala powyżej (ponieważ ktoś ciągle usuwa moje komentarze do jego odpowiedzi), która przedstawia spolaryzowany pogląd przeciwny do zamierzonego:
Stąd metaprogramowanie szablonów działa tylko wtedy, gdy program jest dostępny w czasie kompilacji, co często nie ma miejsca, np. Niemożliwe jest napisanie konkurencyjnej biblioteki wyrażeń regularnych w waniliowym C ++, ponieważ nie jest w stanie generować kodu w czasie wykonywania (ważny aspekt metaprogramowanie).
W języku C # dotyczy to tylko typów odwołań i nie dotyczy typów wartości.
Ludzie zaobserwowali, że Java pokonuje C ++ w teście SOR z testu porównawczego SciMark2 właśnie dlatego, że wskaźniki utrudniają optymalizacje związane z aliasowaniem.
Warto również zauważyć, że .NET specjalizuje się w typach typów ogólnych w bibliotekach połączonych dynamicznie po połączeniu, podczas gdy C ++ nie może, ponieważ szablony muszą zostać rozwiązane przed połączeniem. I oczywiście dużą przewagą typów generycznych nad szablonami są zrozumiałe komunikaty o błędach.
źródło
Oprócz tego, co powiedzieli inni, z mojego zrozumienia .NET i Java są lepsze w alokacji pamięci. Na przykład mogą kompaktować pamięć, gdy jest ona pofragmentowana, podczas gdy C ++ nie może (natywnie, ale może, jeśli używasz sprytnego garbage collectora).
źródło
W przypadku wszystkiego, co wymaga dużej szybkości, JVM po prostu wywołuje implementację C ++, więc bardziej chodzi o to, jak dobre są ich biblioteki, niż o to, jak dobra jest JVM dla większości rzeczy związanych z systemem operacyjnym. Zbieranie śmieci skraca pamięć o połowę, ale użycie niektórych bardziej wyszukanych funkcji STL i Boost przyniesie ten sam efekt, ale z wielokrotnie większym potencjałem błędów.
Jeśli używasz tylko bibliotek C ++ i wielu jego funkcji wysokiego poziomu w dużym projekcie z wieloma klasami, prawdopodobnie skończysz wolniej niż przy użyciu JVM. Z wyjątkiem znacznie bardziej podatnych na błędy.
Jednak zaletą C ++ jest to, że pozwala na optymalizację, w przeciwnym razie utkniesz z tym, co robi kompilator / jvm. Jeśli stworzysz własne kontenery, napiszesz własne zarządzanie pamięcią, które jest wyrównane, użyj SIMD i upuść do asemblacji tu i tam, możesz przyspieszyć co najmniej 2x-4x razy w porównaniu z tym, co większość kompilatorów C ++ zrobi samodzielnie. W przypadku niektórych operacji 16x-32x. To przy użyciu tych samych algorytmów, jeśli zastosujesz lepsze algorytmy i zrównoleglenie, wzrosty mogą być dramatyczne, czasem tysiące razy szybsze niż powszechnie stosowane metody.
źródło
Patrzę na to z kilku różnych punktów.
źródło
Bardzo krótka odpowiedź: biorąc pod uwagę ustalony budżet, osiągniesz lepszą wydajność aplikacji java niż aplikacja C ++ (względy zwrotu z inwestycji) Ponadto platforma Java ma bardziej przyzwoite profile, które pomogą Ci szybciej zlokalizować hotspoty
źródło