Performanță Java - Java performance
În dezvoltarea de software , limbajul de programare Java a fost considerat istoric mai lent decât cel mai rapid treia generație tastate limbi , cum ar fi C și C ++ . Motivul principal este un design de limbaj diferit, în care după compilare, programele Java rulează pe o mașină virtuală Java (JVM) mai degrabă decât direct pe procesorul computerului ca cod nativ , la fel ca programele C și C ++. Performanța a fost o problemă de îngrijorare, deoarece multe software-uri de afaceri au fost scrise în Java după ce limbajul a devenit rapid popular la sfârșitul anilor 1990 și începutul anilor 2000.
De la sfârșitul anilor 1990, viteza de execuție a programelor Java s-a îmbunătățit semnificativ prin introducerea compilării just-in-time (JIT) (în 1997 pentru Java 1.1 ), adăugarea caracteristicilor de limbaj care susțin o analiză mai bună a codului și optimizări în JVM (astfel ca HotSpot devenind implicit pentru JVM-ul lui Sun în 2000). Executarea hardware a codului secundar Java, cum ar fi cea oferită de Jazelle ARM , a fost, de asemenea, explorată pentru a oferi îmbunătățiri semnificative ale performanței.
Performanța unui bytecode Java compilat program Java depinde de modul optim sarcinile date sunt gestionate de către gazdă mașina virtuală Java (JVM), și cât de bine JVM exploatează caracteristicile hardware - ul computerului și sistem de operare (OS) în acest sens. Astfel, orice test de performanță sau comparație Java trebuie să raporteze întotdeauna versiunea, furnizorul, sistemul de operare și arhitectura hardware a JVM-ului folosit. Într-un mod similar, performanța programului echivalent compilat nativ va depinde de calitatea codului său de mașină generat, astfel încât testul sau comparația trebuie să raporteze și numele, versiunea și furnizorul compilatorului folosit și directivele sale de optimizare a compilatorului activat .
Metode de optimizare a mașinilor virtuale
Multe optimizări au îmbunătățit performanța JVM în timp. Cu toate acestea, deși Java a fost adesea prima mașină virtuală care le-a implementat cu succes, ele au fost deseori folosite și pe alte platforme similare.
Compilarea la timp
JVM-urile timpurii au interpretat întotdeauna codurile secundare Java . Acest lucru a avut o penalizare mare de performanță între un factor 10 și 20 pentru Java versus C în aplicațiile medii. Pentru a combate acest lucru, un compilator JIT (just-in-time) a fost introdus în Java 1.1. Datorită costului ridicat de compilare, un sistem adăugat numit HotSpot a fost introdus în Java 1.2 și a devenit implicit în Java 1.3. Folosind acest cadru, mașina virtuală Java analizează continuu performanța programului pentru punctele fierbinți care sunt executate frecvent sau în mod repetat. Acestea sunt apoi vizate pentru optimizare , ducând la executarea de înaltă performanță, cu un minim de cheltuieli generale pentru un cod mai puțin performant. Unele etaloane indică o creștere de 10 ori a vitezei prin acest mijloc. Cu toate acestea, din cauza constrângerilor de timp, compilatorul nu poate optimiza pe deplin programul și, prin urmare, programul rezultat este mai lent decât alternativele de cod nativ.
Optimizare adaptivă
Optimizarea adaptivă este o metodă în informatică care realizează recompilarea dinamică a părților unui program pe baza profilului de execuție curent. Cu o implementare simplă, un optimizator adaptiv poate face pur și simplu un compromis între instrucțiunile de compilare și interpretare just-in-time. La un alt nivel, optimizarea adaptivă poate exploata condițiile de date locale pentru a optimiza sucursalele și pentru a utiliza extinderea în linie.
O mașină virtuală Java, cum ar fi HotSpot, poate deoptimiza codul anterior JITed. Acest lucru permite efectuarea de optimizări agresive (și potențial nesigure), putând totuși să dezoptimizați ulterior codul și să reveniți la o cale sigură.
Colectarea gunoiului
Mașinile virtuale Java (JVM) 1.0 și 1.1 foloseau un colector de marcare , care ar putea fragmenta grămada după o colectare a gunoiului. Începând cu Java 1.2, JVM-urile s-au schimbat într-un colecționar generațional , care are un comportament de defragmentare mult mai bun. JVM-urile moderne folosesc o varietate de metode care au îmbunătățit și mai mult performanța de colectare a gunoiului .
Alte metode de optimizare
Hopa comprimată
Hărțile comprimate permit Java 5.0+ să adreseze până la 32 GB de heap cu referințe pe 32 de biți. Java nu acceptă accesul la octeți individuali, ci doar obiecte care sunt aliniate în mod implicit pe 8 octeți. Din acest motiv, cei mai mici 3 biți ai unei referințe heap vor fi întotdeauna 0. Prin scăderea rezoluției referințelor pe 32 de biți la blocuri de 8 octeți, spațiul adresabil poate fi mărit la 32 GB. Acest lucru reduce semnificativ utilizarea memoriei în comparație cu utilizarea referințelor pe 64 de biți, deoarece Java folosește referințe mult mai mult decât unele limbi cum ar fi C ++. Java 8 acceptă alinieri mai mari, cum ar fi alinierea pe 16 octeți pentru a suporta până la 64 GB cu referințe pe 32 de biți.
Împărțirea verificării bytecode
Înainte de a executa o clasă , Sun JVM își verifică codurile secundare Java (consultați verificatorul de coduri bytecode ). Această verificare este efectuată leneș: codurile oculare ale claselor sunt încărcate și verificate numai atunci când clasa specifică este încărcată și pregătită pentru utilizare și nu la începutul programului. Cu toate acestea, întrucât bibliotecile de clase Java sunt și clase Java obișnuite, ele trebuie încărcate și atunci când sunt utilizate, ceea ce înseamnă că timpul de pornire al unui program Java este adesea mai lung decât pentru programele C ++ , de exemplu.
O metodă numită verificare în timp divizat , introdusă pentru prima dată în platforma Java, Micro Edition (J2ME), este utilizată în JVM de la versiunea Java 6 . Împarte verificarea codului secundar Java în două faze:
- Timp de proiectare - atunci când compilați o clasă de la sursă la bytecode
- Runtime - la încărcarea unei clase.
În practică, această metodă funcționează prin captarea cunoștințelor pe care compilatorul Java le are despre fluxul de clase și adnotarea bytecodurilor metodei compilate cu un sinopsis al informațiilor despre fluxul de clase. Acest lucru nu face ca verificarea în timp de rulare să fie mult mai puțin complexă, dar permite unele comenzi rapide.
Analiza evadării și îngrășarea blocării
Java este capabil să gestioneze multithreading la nivel de limbă. Multithreading-ul este o metodă care permite programelor să efectueze mai multe procese simultan, producând astfel programe mai rapide pe sisteme de calculatoare cu procesoare multiple sau nuclee. De asemenea, o aplicație cu mai multe fire poate rămâne receptivă la intrare, chiar și în timp ce îndeplinește sarcini de lungă durată.
Cu toate acestea, programele care utilizează multithreading trebuie să aibă grijă în plus de obiectele partajate între fire, blocând accesul la metodele sau blocurile partajate atunci când sunt utilizate de unul dintre fire. Blocarea unui bloc sau a unui obiect este o operațiune care necesită mult timp, datorită naturii sistemului de operare subiacent - operațiunea la nivel implicată (a se vedea controlul concurenței și granularitatea blocării ).
Deoarece biblioteca Java nu știe ce metode vor fi utilizate de mai multe fire, biblioteca standard blochează întotdeauna blocurile atunci când este necesar într-un mediu cu mai multe fire.
Înainte de Java 6, mașina virtuală a blocat întotdeauna obiecte și blocuri la cererea programului, chiar dacă nu exista riscul ca un obiect să fie modificat de două fire diferite simultan. De exemplu, în acest caz, un local a vector fost blocat înainte de fiecare dintre operațiile de adăugare pentru a se asigura că nu va fi modificat de alte fire (vectorul este sincronizat), dar pentru că este strict local la metoda, este inutil:
public String getNames() {
Vector<String> v = new Vector<>();
v.add("Me");
v.add("You");
v.add("Her");
return v.toString();
}
Începând cu Java 6, blocurile de cod și obiectele sunt blocate numai atunci când este necesar, astfel încât în cazul de mai sus, mașina virtuală nu ar bloca deloc obiectul Vector.
De la versiunea 6u23, Java include suport pentru analiza evadării.
Înregistrați îmbunătățiri de alocare
Înainte de Java 6 , alocarea registrelor era foarte primitivă în mașina virtuală client (nu trăiau între blocuri ), ceea ce reprezenta o problemă în design-urile CPU care aveau mai puține registre de procesoare disponibile, ca în x86s . Dacă nu mai există registre disponibile pentru o operațiune, compilatorul trebuie să copieze din registru în memorie (sau memorie pentru înregistrare), ceea ce necesită timp (registrele sunt semnificativ mai rapide de accesat). Cu toate acestea, mașina virtuală a serverului a folosit un alocator de culori și nu a avut această problemă.
O optimizare a alocării registrului a fost introdusă în Sun's JDK 6; a fost apoi posibil să se utilizeze aceleași registre între blocuri (atunci când este cazul), reducând accesul la memorie. Acest lucru a condus la un câștig de performanță raportat de aproximativ 60% în unele repere.
Partajarea datelor de clasă
Partajarea datelor de clasă (numită CDS de Sun) este un mecanism care reduce timpul de pornire pentru aplicațiile Java și, de asemenea, reduce amprenta de memorie . Când JRE este instalat, programul de instalare încarcă un set de clase din fișierul JAR al sistemului (fișierul JAR care conține toată biblioteca de clase Java, denumită rt.jar) într-o reprezentare internă privată și aruncă această reprezentare într-un fișier, numit „arhivă partajată”. În timpul invocațiilor JVM ulterioare, această arhivă partajată este mapată în memorie , economisind costul încărcării acelor clase și permițând ca o mare parte din metadatele JVM pentru aceste clase să fie partajate între mai multe procese JVM.
Îmbunătățirea corespunzătoare a timpului de pornire este mai evidentă pentru programele mici.
Istoricul îmbunătățirilor de performanță
În afară de îmbunătățirile enumerate aici, fiecare versiune de Java a introdus multe îmbunătățiri de performanță în interfața de programare a aplicațiilor (API) JVM și Java .
JDK 1.1.6: Prima compilare just-in-time ( compilatorul JIT Symantec )
J2SE 1.2: Utilizarea unui colecționar generațional .
J2SE 1.3: Compilare just-in-time de HotSpot .
J2SE 1.4: Vedeți aici , pentru o prezentare generală Sun a îmbunătățirilor de performanță între versiunile 1.3 și 1.4.
Java SE 5.0: Partajarea datelor de clasă
Java SE 6:
- Împărțirea verificării bytecode
- Analiza evadării și îngrășarea blocării
- Înregistrați îmbunătățiri de alocare
Alte îmbunătățiri:
- Îmbunătățirea vitezei conductei Java OpenGL Java 2D
- Performanța Java 2D s-a îmbunătățit semnificativ și în Java 6
Consultați și „Prezentare generală Sun a îmbunătățirilor de performanță între Java 5 și Java 6”.
Actualizare 10 Java SE 6
- Java Quick Starter reduce timpul de pornire a aplicației preîncărcând o parte din datele JRE la pornirea sistemului de operare pe memoria cache a discului .
- Părțile platformei necesare pentru a executa o aplicație accesată de pe web când JRE nu este instalat sunt acum descărcate mai întâi. JRE complet este de 12 MB, o aplicație tipică Swing trebuie să descarce doar 4 MB pentru a începe. Celelalte părți sunt apoi descărcate în fundal.
- Performanța grafică pe Windows s-a îmbunătățit utilizând în mod implicit Direct3D și folosind umbrele pe unitatea de procesare grafică (GPU) pentru a accelera operațiunile complexe Java 2D .
Java 7
Au fost lansate mai multe îmbunătățiri de performanță pentru Java 7: viitoare îmbunătățiri de performanță sunt planificate pentru o actualizare a Java 6 sau Java 7:
- Oferiți suport JVM pentru limbaje de programare dinamice , în urma lucrărilor de prototipare efectuate în prezent pe mașina Da Vinci (mașină virtuală în mai multe limbi),
- Îmbunătățiți biblioteca de concurență existentă gestionând calcule paralele pe procesoare multi-core ,
- Permiteți JVM să utilizeze atât compilatoarele JIT client, cât și serverul în aceeași sesiune cu o metodă numită compilare pe niveluri:
- Clientul va fi folosit la pornire (pentru că este bun la pornire și pentru aplicații mici),
- Serverul ar folosi pe termen lung de funcționare a aplicației (deoarece surclasează client compilator pentru acest lucru).
- Înlocuiți colectorul de gunoi concurent existent cu pauză mică (numit și colector de marcare simultană (CMS)) cu un nou colector numit Garbage First (G1) pentru a asigura pauze consistente în timp.
Comparație cu alte limbi
Compararea obiectivă a performanței unui program Java și a unui program echivalent scris într-un alt limbaj, cum ar fi C ++, are nevoie de un punct de referință construit cu atenție și gândire, care să compare programele care îndeplinesc sarcini identice. Platforma țintă a compilatorului de bytecode Java este platforma Java , iar bytecode-ul este fie interpretat, fie compilat în codul mașinii de către JVM. Alte compilatoare vizează aproape întotdeauna o anumită platformă hardware și software, producând codul mașinii care va rămâne practic neschimbat în timpul execuției. Scenarii foarte diferite și greu de comparat apar din aceste două abordări diferite: compilații și recompilări statice vs. dinamice , disponibilitatea informațiilor precise despre mediul de execuție și altele.
Java este adesea compilat exact la timp în timpul rulării de către mașina virtuală Java , dar poate fi compilat și înainte de timp , la fel ca și C ++. Atunci când sunt compilate exact la timp, micro-benchmark-urile jocului The Computer Language Benchmarks Game indică următoarele despre performanța sa:
- mai lent decât limbile compilate, cum ar fi C sau C ++ ,
- similar cu alte limbi compilate exact la timp, cum ar fi C # ,
- mult mai rapid decât limbile fără un compilator eficient de cod nativ ( JIT sau AOT ), cum ar fi Perl , Ruby , PHP și Python .
Viteza programului
Benchmark-urile măsoară adesea performanța pentru programele mici cu intensitate numerică. În unele programe rare din viața reală, Java depășește C. Un exemplu este etalonul lui Jake2 (o clonă a Quake II scrisă în Java prin traducerea codului GPL C original ). Versiunea Java 5.0 funcționează mai bine în unele configurații hardware decât omologul său C. Deși nu este specificat modul în care au fost măsurate datele (de exemplu, dacă a fost utilizat executabilul Quake II original compilat în 1997, ceea ce poate fi considerat rău, deoarece compilatoarele C actuale pot realiza optimizări mai bune pentru Quake), notează cum același cod sursă Java poate avea un impuls uriaș de viteză doar prin actualizarea VM, lucru imposibil de realizat cu o abordare 100% statică.
Pentru alte programe, omologul C ++ poate și, de obicei, funcționează semnificativ mai repede decât echivalentul Java. Un benchmark realizat de Google în 2011 a arătat un factor 10 între C ++ și Java. La cealaltă extremă, un reper academic realizat în 2012 cu un algoritm de modelare 3D a arătat că Java 6 JVM este de la 1,09 la 1,91 ori mai lent decât C ++ în Windows.
Este posibil ca unele optimizări posibile în Java și limbaje similare să nu fie posibile în anumite circumstanțe în C ++:
- Utilizarea indicatorului în stil C poate împiedica optimizarea în limbile care acceptă pointeri,
- Utilizarea metodelor de analiză de evadare este limitată în C ++ , de exemplu, deoarece un compilator C ++ nu știe întotdeauna dacă un obiect va fi modificat într-un bloc dat de cod din cauza pointerilor ,
- Java poate accesa metode de instanță derivate mai repede decât C ++ poate accesa metode virtuale derivate datorită căutării suplimentare a tabelului virtual al C ++. Cu toate acestea, metodele non-virtuale din C ++ nu suferă de blocaje de performanță ale tabelelor v și astfel prezintă performanțe similare cu Java.
JVM este, de asemenea, capabil să efectueze optimizări specifice procesorului sau extindere în linie . Și, abilitatea de a dezoptimiza codul deja compilat sau înclinat îi permite uneori să realizeze optimizări mai agresive decât cele realizate de limbaje tipizate static atunci când sunt implicate funcții de bibliotecă externe.
Rezultatele pentru microbenchmarks între Java și C ++ depind în mare măsură de operațiunile care sunt comparate. De exemplu, atunci când se compară cu Java 5.0:
- Operațiunile aritmetice pe 32 și 64 de biți, I / O de fișiere și gestionarea excepțiilor , au o performanță similară cu programele C ++ comparabile
- Performanța operațiunilor matricelor este mai bună în C.
- Performanța funcțiilor trigonometrice este mult mai bună în C.
- Note
Performanță multi-core
Scalabilitatea și performanța aplicațiilor Java pe sistemele multi-core sunt limitate de rata de alocare a obiectelor. Acest efect este uneori numit „perete de alocare”. Cu toate acestea, în practică, algoritmii moderni de colectare a gunoiului folosesc mai multe nuclee pentru a efectua colectarea gunoiului, ceea ce într-o oarecare măsură ameliorează această problemă. Unii colectoare de gunoi sunt raportate să susțină rate de alocare de peste un gigabyte pe secundă și există sisteme bazate pe Java care nu au probleme de scalare la câteva sute de nuclee CPU și grămezi de dimensiuni de câteva sute de GB.
Gestionarea automată a memoriei în Java permite utilizarea eficientă a structurilor de date blocabile și imuabile care sunt extrem de dure sau uneori imposibile de implementat fără un fel de colectare a gunoiului. Java oferă o serie de astfel de structuri la nivel înalt în biblioteca sa standard din pachetul java.util.concurrent, în timp ce multe limbaje utilizate în mod istoric pentru sisteme de înaltă performanță, cum ar fi C sau C ++, încă le lipsesc.
Timp de pornire
Timpul de pornire Java este adesea mult mai lent decât multe limbi, inclusiv C , C ++ , Perl sau Python , deoarece multe clase (și mai întâi toate clasele din bibliotecile de clase ale platformei ) trebuie încărcate înainte de a fi utilizate.
Comparativ cu timpii de execuție populari similari, pentru programele mici care rulează pe o mașină Windows, timpul de pornire pare a fi similar cu cel al lui Mono și puțin mai lent decât .NET .
Se pare că o mare parte din timpul de pornire se datorează operațiilor legate de intrare-ieșire (IO), mai degrabă decât inițializării JVM sau încărcării clasei ( fișierul de date de clasă rt.jar singur este de 40 MB și JVM trebuie să caute multe date în acest fișier mare) . Unele teste au arătat că, deși noua metodă de verificare a codului byt-split a îmbunătățit încărcarea clasei cu aproximativ 40%, a realizat doar aproximativ 5% îmbunătățirea pornirii pentru programele mari.
Deși o mică îmbunătățire, este mai vizibilă în programele mici care efectuează o operație simplă și apoi ies, deoarece încărcarea datelor de pe platforma Java poate reprezenta de multe ori sarcina operațiunii programului real.
Începând cu Java SE 6 Update 10, Sun JRE vine cu un Starter rapid care preîncarcă datele clasei la pornirea sistemului de operare pentru a obține date din memoria cache a discului, mai degrabă decât de pe disc.
Excelsior JET abordează problema din cealaltă parte. Optimizatorul său de pornire reduce cantitatea de date care trebuie citite de pe disc la pornirea aplicației și face citirile mai secvențiale.
În noiembrie 2004, Nailgun , un „client, protocol și server pentru rularea programelor Java de pe linia de comandă fără a suporta cheltuielile de pornire JVM” a fost lansat public. introducând pentru prima dată o opțiune pentru scripturi de a utiliza o JVM ca daemon , pentru rularea uneia sau mai multor aplicații Java fără niciun cost de pornire JVM. Demonul Nailgun este nesigur: „toate programele sunt rulate cu aceleași permisiuni ca serverul”. Acolo unde este necesară securitatea multi-utilizator , Nailgun este inadecvat fără măsuri speciale de precauție. Script - uri în cazul în care per aplicație JVM de pornire domină utilizarea resurselor, a se vedea un-doi ordin de mărime îmbunătățiri de performanță runtime.
Utilizarea memoriei
Utilizarea memoriei Java este mult mai mare decât cea a memoriei C ++, deoarece:
- Există o cheltuială de 8 octeți pentru fiecare obiect și 12 octeți pentru fiecare matrice în Java. Dacă dimensiunea unui obiect nu este un multiplu de 8 octeți, este rotunjită la următorul multiplu de 8. Aceasta înseamnă că un obiect care deține un câmp de octeți ocupă 16 octeți și are nevoie de o referință de 4 octeți. C ++ alocă, de asemenea, un pointer (de obicei 4 sau 8 octeți) pentru fiecare obiect a cărui clasă declară direct sau indirect funcții virtuale .
- Lipsa aritmeticii adreselor face ca crearea de containere eficiente din punct de vedere al memoriei, cum ar fi structuri strâns distanțate și liste legate XOR , să fie în prezent imposibilă ( proiectul OpenJDK Valhalla își propune să atenueze aceste probleme, deși nu are ca scop introducerea aritmeticii indicatorului; mediu colectat gunoi).
- Spre deosebire de noul malloc, performanța medie a cheltuielilor generale de colectare a gunoiului se apropie asimptotic de zero (mai precis, un ciclu de procesor) pe măsură ce mărimea heap-ului crește.
- Părți din biblioteca de clase Java trebuie să se încarce înainte de executarea programului (cel puțin clasele utilizate în cadrul unui program). Acest lucru duce la o suprasolicitare semnificativă a memoriei pentru aplicații mici.
- Atât recompilările binare Java cât și cele native vor fi de obicei în memorie.
- Mașina virtuală folosește memorie substanțială.
- În Java, un obiect compozit (clasa A care folosește instanțele B și C) este creat folosind referințe la instanțele alocate ale B și C. În C ++ memoria și performanța costurilor acestor tipuri de referințe pot fi evitate atunci când instanța B și / sau C există în A.
În majoritatea cazurilor, o aplicație C ++ va consuma mai puțină memorie decât o aplicație Java echivalentă datorită cheltuielilor mari ale mașinii virtuale Java, încărcării clasei și redimensionării automate a memoriei. Pentru programele în care memoria este un factor critic pentru alegerea între limbi și medii de rulare, este necesară o analiză cost / beneficiu.
Funcții trigonometrice
Performanța funcțiilor trigonometrice este slabă în comparație cu C, deoarece Java are specificații stricte pentru rezultatele operațiilor matematice, care ar putea să nu corespundă implementării hardware de bază. Pe subsetul cu virgulă mobilă x87 , Java, deoarece 1.4 face reducerea argumentelor pentru sin și cos în software, provocând o lovitură mare de performanță pentru valori din afara intervalului. JDK (11 și peste) are un progres semnificativ în viteza de evaluare a funcțiilor trigonometrice în comparație cu JDK 8.
Interfață nativă Java
Java Native Interface invocă o aeriene de mare, ceea ce face costisitor să traverseze granița dintre codul rulează pe JVM și codul nativ. Java Native Access (JNA) oferă programelor Java acces ușor la biblioteci partajate native ( bibliotecă cu legături dinamice (DLL) pe Windows) numai prin cod Java, fără JNI sau cod nativ. Această funcționalitate este comparabilă cu tipurile de platformă Windows / Invocare și Python . Accesul este dinamic la rulare fără generarea de cod. Dar are un cost, iar JNA este de obicei mai lent decât JNI.
Interfața cu utilizatorul
Swing a fost perceput ca fiind mai lent decât seturile de instrumente pentru widget-uri native , deoarece delegă redarea widgeturilor către API-ul Java 2D pur . Cu toate acestea, punctele de referință care compară performanțele Swing față de Standard Widget Toolkit , care delegă redarea bibliotecilor native GUI ale sistemului de operare, nu prezintă niciun câștigător clar, iar rezultatele depind în mare măsură de context și medii. În plus, noul cadru JavaFX , destinat să înlocuiască Swing, abordează multe dintre problemele inerente ale Swing.
Utilizat pentru calcul de înaltă performanță
Unii oameni consideră că performanța Java pentru calculul de înaltă performanță (HPC) este similară cu Fortran pe parametrii de referință intensivi în calcul, dar că JVM-urile au încă probleme de scalabilitate pentru realizarea unei comunicări intensive pe o rețea de calcul de rețea.
Cu toate acestea, aplicațiile de calcul de înaltă performanță scrise în Java au câștigat concursuri de referință. În 2008 și 2009, un cluster bazat pe Apache Hadoop (un proiect de calcul open-source de înaltă performanță scris în Java) a reușit să sorteze cel mai rapid un terabyte și un petabyte de numere întregi. Configurarea hardware a sistemelor concurente nu a fost însă fixată.
În concursurile de programare
Programele în Java încep mai lent decât cele din alte limbaje compilate. Astfel, unele sisteme de judecători online, în special cele găzduite de universitățile chinezești, utilizează limite de timp mai lungi pentru ca programele Java să fie corecte față de concurenții care folosesc Java.
Vezi si
- Runtime de limbaj comun
- Analiza performanței
- Procesor Java , un procesor încorporat care rulează Java bytecode în mod nativ (cum ar fi JStik )
- Comparație între Java și C ++
- Java ConcurrentMap