View Full Version : [JAVA] Quando le prestazioni contano
Salve a tutti, ho una questione da risolvere.
Sto partendo con un progetto piuttosto serio in cui si necessita di ALTE PRESTAZIONI e mi è stato detto che esiste la possibilità di compilare Java in modo che non generi bytecode ma codice nativo che viene eseguito senza interpreti intermedi. Volevo sapere innanzitutto se questa cosa è possibile (guardando in giro pare di si) e soprattutto se produce vantaggi PRATICI? Considerate che l'applicativo in questione potrebbe dover girare anche svariate ore (è un simulatore) quindi le prestazioni non servono al boot ma nell'esecuzione a regime. Lo scrivo chiaramente in modo che non nascano eventuali flame: IO VORREI USARE JAVA perchè lo conosco abbastanza bene e so che sarei più produttivo. Detto ciò, se la situazione dovesse essere inaccettabile dal punto di vista delle performances, dovrò desistere e andare all'alternativa (che può essere _esclusivamente_ C++ quindi non ci sono altre strade). Mi farebbe piacere sentire i pareri di gente che ha più esperienza di me perchè chiaramente se si parla di ordini di grandezza di differenza la scelta è obbligata ma se Java si può spingere a livelli comparabili, si potrebbe accettare un tradeoff...
Grazie in anticipo :)
Beh, java non usa più interpreti da secoli... e puoi compilare il tuo codice, ma non puoi compilare tutta la libreria e il runtime :D
Senza contare che la "lentezza" di Java risiede in altro, tipo nel garbage collector, nel thrashing allegro dell'heap che fa la libreria standard, nell'allocazione ancora più allegra di nuovi oggetti, nella mancanza di overloaded operators ed inline, etc.
Per cui, credo che compilare il codice non sia un grande aiuto alle prestazioni.
Ma comunque queste sono speculazioni, l'unico modo per essere sicuri è TESTARE :D
Scrivi qualcosa di rappresentativo del tuo carico di lavoro in C++, Java e Java compilato, e vedi come va!
cdimauro
06-05-2012, 18:21
Concordo. Esiste gcj per compilare java in codice nativo, ma dubito che possa fare meglio della VM 7 e annesso HotSpot.
Grazie per le risposte. Alla fine dei conti immaginavo che non poteva essere un compilatore a risolvermi i problemi..
Ma comunque queste sono speculazioni, l'unico modo per essere sicuri è TESTARE :D
Scrivi qualcosa di rappresentativo del tuo carico di lavoro in C++, Java e Java compilato, e vedi come va!
Questa potrebbe essere una buona idea, a patto che riesca a fare un prototipo molto semplificato in poco tempo... Il core di tutto il sw è un simulatore a eventi discreti. Fare delle prove anche solo per capire quali sono le differenze potrebbe portare via parecchio tempo (purtroppo sono poco familiare con C++).
Ti è possibile pensare di rendere il simulatore multithread per sfruttare davvero al 100% la cpu?
Profiling, profiling, profiling
Dopo che avrai capito dov'è realmente il collo di bottiglia nel tuo codice, si potrà pensare a come sistemarlo
La natura del mio problema si presta in modo naturale ad un approccio ad oggetti oltrechè alla parallelizzazione visto che ci sono N dispositivi da simulare simultaneamente (sono dei router ma non basati su IP). Il multithreading sarà d'obbligo. Mi sa che si potrebbero fare dei test incrociati come consigliato da alcuni di voi, poi dall'alto sceglieranno cosa è meglio!
Gcj è un binario morto. Lo sviluppo è fermo da anni a java 1.4 con ancora parti della libraria da implementare e quello che c'è è bugnato. Lascia perdere questi aggeggi se hai intenzione di usare java. La jvm è più che sufficiente per arrivare a sfiorare le prestazioni di un programma scritto in C.
banryu79
07-05-2012, 10:42
Gcj è un binario morto. Lo sviluppo è fermo da anni a java 1.4 con ancora parti della libraria da implementare e quello che c'è è bugnato. Lascia perdere questi aggeggi se hai intenzione di usare java. La jvm è più che sufficiente per arrivare a sfiorare le prestazioni di un programma scritto in C.
Quoto, considerato quanto detto dall'autore del thread:
...Considerate che l'applicativo in questione potrebbe dover girare anche svariate ore (è un simulatore) quindi le prestazioni non servono al boot ma nell'esecuzione a regime...
L'implementazione della JVM distribuita con il JDK Oracle di default, compila in codice nativo quei metodi che superano una certa soglia di chiamate a runtime, 1000 se non ricordo male (comunque è un parametro settabile).
Vero, mi pare anche che c'era un modo per "convincere" la JVM a compilare tutti i metodi al primo utilizzo... però non so qual'è. Magari non esiste :asd:
EDIT: un articolo molto interessante con dei veri tests: http://caprazzi.net/posts/jit-compiler-part-1/
Vero, mi pare anche che c'era un modo per "convincere" la JVM a compilare tutti i metodi al primo utilizzo... però non so qual'è. Magari non esiste :asd:
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#PerformanceTuning
Direi che con -XX:CompileThreshold=1 dovrebbe andare... mai fatto dei test in questo senso però.
Riuppo questo thread di qualche mese fa per chiedervi nuovi consigli...
Il mio software è praticamente finito, gira su Win7 64 bit + Java 7 (per sviluppare utilizzo Eclipse). Volevo chiedervi qualche tool per fare un pò di profiling in maniera semplice e veloce. Mi interessa sia analizzare le performances in termini di CPU che in termini di memoria e dovrei farlo in _poco_ tempo... :bsod:
Parti con visualvm. Se hai installato il jdk lo hai già bello e pronto sul disco.
Parti con visualvm. Se hai installato il jdk lo hai già bello e pronto sul disco.
Grazie del consiglio, c'è voluto poco per essere operativo.
Dai report prodotti da visualvm emerge che c'è un'allocazione massiccia di byte[] (svariate centinaia di MB), cosa che io non faccio mai esplicitamente nel mio codice, non ho alcun array di byte. Immagino che sia memoria allocata internamente da Java: è possibile risalire fino a CHI causa questa allocazione?
Grazie del consiglio, c'è voluto poco per essere operativo.
Dai report prodotti da visualvm emerge che c'è un'allocazione massiccia di byte[] (svariate centinaia di MB), cosa che io non faccio mai esplicitamente nel mio codice, non ho alcun array di byte. Immagino che sia memoria allocata internamente da Java: è possibile risalire fino a CHI causa questa allocazione?
byte[] e char[] sono in genere allocati da stringhe e stream in input/output internamente da java.
Rieccomi qui.
Diciamo che da un punto di vista dei tempi di esecuzione ho ottimizzato quel che c'era da ottimizzare... Il problema adesso è l'occupazione di memoria! Il mio programma parte con un buon ritmo, ad un certo punto raggiunge quota 2GB (visibile anche dal Task Manager) e lì comincia a rallentare vistosamente. Tra l'altro non capisco se rallenta perchè arriva ad un punto della simulazione molto oneroso oppure perchè il GC è troppo indaffarato a liberare memoria. Comunque sia, tramite il profiler scopro che buona parte della memoria è occupata da oggetti di tipo 'Event' (classe mia) e la cosa è anche normale visto che è un simulatore a eventi discreti ne vengono allocati molti. Viste queste grosse esigenze di allocazione potete consigliarmi qualche tecnica per risparmiare memoria e/o gestirla in maniera più efficente? Ho già minimizzato il numero di new cercando di riusare gli oggetti. Adesso mi balenava l'idea di fare uno store di oggetti di questo tipo così quando ne ho bisogno li chiedo sempre allo store che li allocherà fisicamente solo quando c'è realmente bisogno. Ovviamente si complica un pò tutto perchè quando sti oggetti non servono più devo tenerne traccia e rilasciarli nello store per renderli disponibili al successivo bisogno... :confused:
Avete idee?? :help:
banryu79
17-09-2012, 10:56
Rieccomi qui.
Diciamo che da un punto di vista dei tempi di esecuzione ho ottimizzato quel che c'era da ottimizzare... Il problema adesso è l'occupazione di memoria! Il mio programma parte con un buon ritmo, ad un certo punto raggiunge quota 2GB (visibile anche dal Task Manager) e lì comincia a rallentare vistosamente. Tra l'altro non capisco se rallenta perchè arriva ad un punto della simulazione molto oneroso oppure perchè il GC è troppo indaffarato a liberare memoria. Comunque sia, tramite il profiler scopro che buona parte della memoria è occupata da oggetti di tipo 'Event' (classe mia) e la cosa è anche normale visto che è un simulatore a eventi discreti ne vengono allocati molti. Viste queste grosse esigenze di allocazione potete consigliarmi qualche tecnica per risparmiare memoria e/o gestirla in maniera più efficente? Ho già minimizzato il numero di new cercando di riusare gli oggetti. Adesso mi balenava l'idea di fare uno store di oggetti di questo tipo così quando ne ho bisogno li chiedo sempre allo store che li allocherà fisicamente solo quando c'è realmente bisogno. Ovviamente si complica un pò tutto perchè quando sti oggetti non servono più devo tenerne traccia e rilasciarli nello store per renderli disponibili al successivo bisogno... :confused:
Avete idee?? :help:
E' difficile (per me) rispondere a questa domanda così, sui due piedi. Sarebbe neccessario conoscere l'applicazione e studiarne bene il comportamento a runtime con il profiler, specie analizzare le varie generazioni della memoria gestita dal GC.
Comunque, circa l'object pool, potresti leggere qualcosa in merito: in linea di massima in Java non è una buona stategia.
- http://stackoverflow.com/questions/3636125/cant-find-a-modern-implementation-of-object-pool-in-java#3657724
- http://stackoverflow.com/questions/680514/object-pooling
Prova a spulciare tra questi topic, potresti trovare validi suggerimenti per il tuo caso; male che vada potrai schiarirti un po' le idee:
+ http://stackoverflow.com/questions/tagged/java+memory-management?sort=votes&pagesize=15
E' difficile (per me) rispondere a questa domanda così, sui due piedi. Sarebbe neccessario conoscere l'applicazione e studiarne bene il comportamento a runtime con il profiler, specie analizzare le varie generazioni della memoria gestita dal GC.
Comunque, circa l'object pool, potresti leggere qualcosa in merito: in linea di massima in Java non è una buona stategia.
- http://stackoverflow.com/questions/3636125/cant-find-a-modern-implementation-of-object-pool-in-java#3657724
- http://stackoverflow.com/questions/680514/object-pooling
Prova a spulciare tra questi topic, potresti trovare validi suggerimenti per il tuo caso; male che vada potrai schiarirti un po' le idee:
+ http://stackoverflow.com/questions/tagged/java+memory-management?sort=votes&pagesize=15
Intanto grazie, sto facendo un giro fra i vari topic...
La maggior parte sembrano sconsigliare il pooling tanto dicono che gli oggetti, Java li crea a "basso costo"... Sarà ma se di oggetti ne servono migliaia e migliaia al secondo non mi pare trascurabile la questione della creazione/deallocazione (soprattutto deallocazione)...
Aggiungo che ulteriori analisi col profiler dimostrano che ad un certo punto tutto rallenta perchè la CPU è quasi totalmente utilizzata dal GC (ho utilizzato il tracer di visualvm), come immaginavo...
banryu79
17-09-2012, 12:22
Ah, un'altra cosa: probabilmente non è il tuo caso ma occhio ai memory leak fantasma causati dai profiler birboni (http://www.hwupgrade.it/forum/showthread.php?t=2229123); se puoi è meglio "profilare" l'applicazione da remoto.
vBulletin® v3.6.4, Copyright ©2000-2026, Jelsoft Enterprises Ltd.