View Full Version : [Java] Uso della memoria, prestazioni, vs c++
Volevo un po' di pareri riguardo alle prestazioni di Java soprattutto su come utilizza la memoria e in misura minore la cpu, in particolare in relazione ad uno stesso ipotetico programma scritto in c++, a parità di algoritmi e con una programmazione orientata in maniera massiccia all'ottimizzazione.
Per l'ambito, diciamo un programma per calcolo scientifico, assetato in maniera incredibile di ram, no calcoli in virgola mobile, no grafica, no I/O; il calcolo richiede molta potenza alla cpu, ma non ci sono vincoli di tempo (no real time, se finisce qualche min. prima o dopo nessun problema. Se finisce 2 giorni dopo sì :D )
Da una parte si sente sempre: "Java è pesante.", "Il programma X scritto in Java è lento", ecc. D'altra parte ho letto che:
Java è nato per sistemi embedded, dove l'hardware è limitato;
l'ottimizzazione del jvm è notevole e a volte può competere con la gestione della memoria lasciata al programmatore.
Lato cpu, Jit e ancora una volta la jvm si danno parecchio da fare. Sembra insomma che Java non sia ordini di grandezza più lento del c++. Ovviamente dipende da ciò che si vuole fare nel caso specifico. Leggendo un altro thread un grosso limite di Java è la casualità con cui interviene il garbage collector. Non si può usarlo quindi per programmi con stringenti vincoli di tempo. Ci sono altri problemi simili?
Inoltre vorrei sapere se:
in generale è sconsigliato usare Java per software dove anche l'ultimo bit è importante? Perché?
Un oggetto Java "spreca" della memoria oltre ai dati dichiarati dal programmatore? (Riguardo ciò, da una ricerca su internet fatta un po' di tempo fa, ho scoperto sorprendentemente che non si può sapere quanto occupa un oggetto se non con metodi poco ortodossi, tipo allocare 1000 oggetti e vedere quanto sale la ram occupata :D , o usando librerie esterne che non hanno garanzie di precisione).
Grazie!
IMVHO:
E' vero che da una parte il linguaggio Java non consente l'ottimizzazione del codice che un programmatore C/C++ molto esperto sarebbe in grado di estrarre implementando lo stesso algoritmo in quel linguaggio su di una piattaforma che conosce molto bene, ma considera che:
1) Di questi programmatori ce n'è proprio pochi: la maggior parte degli sviluppatori preferisce la comodità di un ambiente managed e non ha la capacità / il tempo / la voglia di tenere presente tutti i problemi aggiuntivi che sviluppare software unmanaged ti da', problemi che scegliendo Java (ma, per correttezza, anche C#, Ruby, Python, etc) non si hanno. E bada bene che non si possono eliminare dalla programmazione C/C++ queste caratteristiche, perchè proprio la sua capacità di "basso livello" da una parte aumenta le possibili ottimizzazioni, dall'altra impedisce l'uso di automatismi da piattaforma managed, appunto.
2) Bisogna fare un bilancio che tenga conto del tempo di sviluppo impiegato: siamo sicuri che il tempo speso per ottimizzare quattro loop annidati risparmiando dieci cicli di CPU non sarebbe stato meglio speso ottimizzando il funzionamento del'algoritmo ad alto livello? (Nota che in C/C++ puoi fare entrambe le cose, ma evidentemente mentre fai l'una non puoi fare l'altra...).
3) Il codice ultraottimizzato è meno leggibile e meno manutebile di quello più astratto, perchè il primo si allontana dall'intuizione umana più del secondo.
4) Esistono ottime librerie già esistenti a cui delegare i calcoli più complessi e che possono beneficiare in maniera significativa anche delle più piccole ottimizzazioni: queste sono scritte in C/C++ e probabilmente resteranno sempre così, perchè potranno essere riutilizzate a piacere da programmi scritti in altri linguaggi (i driver per i dispositivi sono scritti in C, ma ne beneficia tutto il S.O. e tutti gli applicativi che ci girano sopra, siano essi scritti in Java, .NET, Python, Ruby, ...).
5) L'hardware "costa poco": un incremento prestazionale del 5% si può ottenere aumentando i Mhz del processore con una spesa che magari è inferiore a quella del tempo di un team per ottimizzare in maniera estrema del codice.
Al di là di queste considerazioni "personali", posso dire di aver avuto l'impressione che in ambito di ricerca accademica capiti spesso che venga usato il linguaggio Java anche per simulazioni e calcoli dove le prestazioni sono importanti, senza particolari lamentele. ;)
tomminno
06-10-2008, 07:39
Il vantaggio dei linguaggi managed, risiede nella libreria che mettono immediatamente a disposizione dello sviluppatore, non tanto nella mancanza della gestione diretta della memoria (in quanto nei linguaggi managed devi gestirti a mano la "deallocazione" di oggetti che usano risorse non gestite es connessioni db, tcp, file...).
Prova ad aprire connessioni magari al database centrale dell'azienda e ad aspettare che sia il GC a chiuderle, il server comincia a segnalare che ci sono troppe connessioni nel giro di pochi minuti, fermando il lavoro di tutta l'azienda.
Il fatto che siano lenti (e lo sono anche parecchio in confronto al C++, al lavoro è una situazione che vedo praticamente tutti i giorni) non interessa quanto l'uniformità della piattaforma di sviluppo.
E l'hardware non costa affatto poco. Un computer assemblato a mano costa poco, prova a sentire quanto costa un server rack e magari visto che stiamo parlando di elevati volumi di traffico magari 2 con un bilanciatore e mettici pure un NAS dietro per tutti i dati. Ecco questo è il livello minimo di hardware, in più conta le licenze...
incipit1970
06-10-2008, 15:25
Java non mi sembra particolarmente lento. Ha senz'altro alcuni problemi di performance (il GC, il fatto che i programmi vengono impacchettati in archivi zip, richiedendo una fase di scompattamento prima dell'esecuzione, etc.), ma niente di terribile.
Tutti i programmi impongono un trade-off tra flessibilità e potenza: Java è stato pensato per essere meno complicato di C++, ed in cambio paga un prezzo in performance. Lo stesso si dica di qualsiasi altro programma che "semplifica" la programmazione (in media, maggiore è l'astrazione dal linguaggio macchina, maggiore è la penalità in termini di performance). Anche C++ è meno performante di C...
L'importante dunque è scegliere il linguaggio giusto per ogni compito: se devi ottimizzare al massimo, meglio se usi C++ o persino C (di rado in un programma di calcolo hai bisogno delle estensioni object oriented di C++, hanno un costo in performance pure quelle). Se invece qualche perdita di velocità è accettabile, pur di avere una programmazione più semplice e meno complicata, ben venga Java o C#, o Python...
E' vero che un server enterprise è costoso, ma costa di più mantenere un codice più complesso: il costo di assumere 4-5 programmatori per un anno supera di gran lunga il costo di un server di prima categoria. Inoltre, Java è ricco di codice evoluto open source che altrimenti bisognerebbe sviluppare in-house o acquisire in costose librerie... infatti, Java è molto comune in ambiti aziendali per questi motivi.
Volevo proprio capire quanto sia possibile avvantaggiarsi degli aspetti positivi di un linguaggio come Java da voi menzionati nel caso del tipo di software del mio primo thread.
Perché ancora non ho ben compreso quali sono le problematiche che portano a dire a tomminno: "Il fatto che siano lenti (e lo sono anche parecchio in confronto al C++" e nello stesso tempo a incipit1970:
"Java non mi sembra particolarmente lento. Ha senz'altro alcuni problemi di performance ..., ma niente di terribile."
Ho capito che il GC non si sa quando va in esecuzione (anche se lo si può chiamare forzatamente).
Ma per il resto, soprattutto sull'uso della memoria?
Grazie ancora.
variabilepippo
06-10-2008, 18:49
Prova ad aprire connessioni magari al database centrale dell'azienda e ad aspettare che sia il GC a chiuderle, il server comincia a segnalare che ci sono troppe connessioni nel giro di pochi minuti, fermando il lavoro di tutta l'azienda.
Ma la corretta gestione delle connessioni (aperture/chiusure/transazioni/...) ad un database è comunque compito del programmatore, non del GC, ovvero di una tecnica di gestione della memoria che al massimo può sollevare lo sviluppatore da problemi di allocazione/deallocazione della memoria, dangling pointers, memory leaks, etc. :rolleyes:
Il vantaggio dei linguaggi managed, risiede nella libreria che mettono immediatamente a disposizione dello sviluppatore, non tanto nella mancanza della gestione diretta della memoria (in quanto nei linguaggi managed devi gestirti a mano la "deallocazione" di oggetti che usano risorse non gestite es connessioni db, tcp, file...).
Sì, ma come osserva variabilepippo più sotto, questo vale anche nei linguaggi unmanaged: la differenza che volevo sottolineare io era che un linguaggio managed (o meglio, come correttamente osservi, la sua piattaforma sottostante) risolve automaticamente un problema in più di quello che fanno i linguaggi unmanaged.
Il fatto che siano lenti (e lo sono anche parecchio in confronto al C++, al lavoro è una situazione che vedo praticamente tutti i giorni) non interessa quanto l'uniformità della piattaforma di sviluppo.
Mmmm... qui parliamo di impressioni personali: il fatto è che è difficile fare paragoni oggettivi, perchè raramente usiamo linguaggi managed e unmanaged per fare la stessa cosa: gli ambiti di sviluppo si separano naturalmente all'atto della scelta dei linguaggi. A me per esempio non viene in mente un caso di sviluppo in ambito enterprise "convenzionale" (DB + Web app, per intenderci) in cui la velocità del compilato sia determinante, anche perchè solitamente i "colli di bottiglia" sono i database e/o le connessioni di rete, cose sulle quali il programma contenente la logica applicativa può avere pochissimo effetto.
E l'hardware non costa affatto poco. Un computer assemblato a mano costa poco, prova a sentire quanto costa un server rack e magari visto che stiamo parlando di elevati volumi di traffico magari 2 con un bilanciatore e mettici pure un NAS dietro per tutti i dati. Ecco questo è il livello minimo di hardware, in più conta le licenze...
Il mio era un discorso di tipo differenziale: avendo una disposizione due versioni dello stesso applicativo, di cui una scritta con un linguaggio managed ed una con un linguaggio unmanaged, la differenza di pura velocità di esecuzione (perchè di questa parliamo) giustificherebbe la differenza di prezzo?
Rinunceresti alla SAN con i canali in fibra? No, perchè non è per la velocità di esecuzione che l'hai presa verosimilmente.
Rinunceresti agli switch di rete ridondati? No, perchè non è per la velocità di esecuzione che ne hai ordinati due.
Forse, diciamo, potresti evitare di comprare uno dei quattro server che stanno dietro al tuo load balancer (al quale non puoi rinunciare, per i motivi di cui sopra): il risparmio si ridurrebbe perciò ad un paio di migliaia di euro.
Però in cambio dovresti rinunciare a tutti i benefici di una piattaforma managed...
Intendiamoci, io non sono un grande esperto di questo genere di questioni, riporto solo le mie impressioni personali, che derivano da un po' di esperienza e da un po' di sentito dire, però non mi sentirei di dire, a tutt'oggi, che sia meglio intraprendere uno sviluppo su di un sistema unmanaged piuttosto che uno managed, nella maggioranza dei casi.
Tornando poi al caso esposto da Johnn, forse farebbe premio la maggiore "riusabilità" del codice managed (specie se scritto secondo i criteri dell'OO, ma se si parla di Java, C#, Ruby, Python, ...) rispetto alle maggiori performance di quello funzionale, perchè ritengo (ma è solo una sensazione) che la perdita di performance, anche se ci fosse, sarebbe comunque una percentuale poco significativa dell'esecuzione del totale. E siccome non si tratta di compiti rt, ne deduco che, per esempio, aspettare 31 giorni per un risultato anzichè 30 non farebbe molta differenza.
Ma la corretta gestione delle connessioni (aperture/chiusure/transazioni/...) ad un database è comunque compito del programmatore, non del GC, ovvero di una tecnica di gestione della memoria che al massimo può sollevare lo sviluppatore da problemi di allocazione/deallocazione della memoria, dangling pointers, memory leaks, etc. :rolleyes:
:mano:
tomminno
07-10-2008, 07:43
Ma la corretta gestione delle connessioni (aperture/chiusure/transazioni/...) ad un database è comunque compito del programmatore, non del GC, ovvero di una tecnica di gestione della memoria che al massimo può sollevare lo sviluppatore da problemi di allocazione/deallocazione della memoria, dangling pointers, memory leaks, etc. :rolleyes:
Scusa che differenza c'è tra chiamare correttamente una delete e chiamare correttamente un metodo Dispose?
Poi puntualmente trovi metodi Dispose chiamati male, perchè tanto c'è il GC, nessuno ha mai imparato a gestire la memoria e quindi la deallocazione corretta delle risorse, nessuno si prende la briga di studiare lo using...
tomminno
07-10-2008, 07:55
Java non mi sembra particolarmente lento. Ha senz'altro alcuni problemi di performance (il GC, il fatto che i programmi vengono impacchettati in archivi zip, richiedendo una fase di scompattamento prima dell'esecuzione, etc.), ma niente di terribile.
Le interfacce grafiche in Java sembrano lentissime anche su dei Core2Duo ben carrozzati.
Sia all'avvio sia durante l'esecuzione, ho come esempio NetBeans che ci mette 40 secondi ad avviarsi e spesso si ferma a pensare quando devi aprire un menu o altro.
Ma la mia esperienza con Java è disastrosa su tutti i computer che ho potuto provare, contrariamente a quello che riportano altri.
Probabilmente quello che per me è inaccettabile come prestazioni per altri risulta adeguato.
Tutti i programmi impongono un trade-off tra flessibilità e potenza: Java è stato pensato per essere meno complicato di C++, ed in cambio paga un prezzo in performance. Lo stesso si dica di qualsiasi altro programma che "semplifica" la programmazione (in media, maggiore è l'astrazione dal linguaggio macchina, maggiore è la penalità in termini di performance). Anche C++ è meno performante di C...
La programmazione ti è semplificata dalla libreria standard del linguaggio in primis e poi dagli strumenti che ruotano attorno.
Ad esempio se devi fare un'applicazione enterprise, non c'è C# che tenga, Java ha strumenti molto migliori ed è quindi più produttivo.
Al contrario per lo sviluppo di un applicativo desktop, il vantaggio del linguaggio si fa sentire.
L'importante dunque è scegliere il linguaggio giusto per ogni compito: se devi ottimizzare al massimo, meglio se usi C++ o persino C (di rado in un programma di calcolo hai bisogno delle estensioni object oriented di C++, hanno un costo in performance pure quelle). Se invece qualche perdita di velocità è accettabile, pur di avere una programmazione più semplice e meno complicata, ben venga Java o C#, o Python...
Se parti da una libreria che è pari come funzionalità a quella integrata nei linguaggi managed non ho trovato particolari svantaggi nello sviluppo, ma anche in applicativi semplici come di log parser i vantaggi prestazionali sono mediamente 1:8, per lo meno per la mia esperienza.
Certo se l'ottica è di incrementare il numero di server ogni anno al posto del numero di sviluppatori, chi se ne frega.
tomminno
07-10-2008, 08:21
Sì, ma come osserva variabilepippo più sotto, questo vale anche nei linguaggi unmanaged: la differenza che volevo sottolineare io era che un linguaggio managed (o meglio, come correttamente osservi, la sua piattaforma sottostante) risolve automaticamente un problema in più di quello che fanno i linguaggi unmanaged.
Veramente anche nei linguaggi managed devi deallocarti correttamente le risorse unmanaged, da una parte gestisci manualmente la memoria, dall'altra gestisci manualmente tutte le altre risorse, non ci vedo una gran differenza.
Per la mia esperienza trovo sempre colleghi che non hanno mai studiato il C/C++ che non usano correttamente la deallocazione delle risorse anche in linguaggi managed e questo a volte causa più danni di un memory leak in un singolo applicativo, tipo saturazione delle connessioni al db.
Mmmm... qui parliamo di impressioni personali: il fatto è che è difficile fare paragoni oggettivi, perchè raramente usiamo linguaggi managed e unmanaged per fare la stessa cosa: gli ambiti di sviluppo si separano naturalmente all'atto della scelta dei linguaggi.
Ho avuto modo di fare esattamente gli stessi applicativi in più linguaggi e con un codice che è praticamente identico (tra l'altro assolutamente if-less), salvo le dovute differenze di linguaggio, la differenza prestazionale in questi casi era 1:8 e il bello è che essendo stato lo sviluppo C++ il porting di quello C# non mi ha portato via più di un paio d'ore, con il vantaggio che ora i parser riescono ad elaborare nelle 24 ore e a stare al passo con le tonnellate di log giornaliere.
A me per esempio non viene in mente un caso di sviluppo in ambito enterprise "convenzionale" (DB + Web app, per intenderci) in cui la velocità del compilato sia determinante, anche perchè solitamente i "colli di bottiglia" sono i database e/o le connessioni di rete, cose sulle quali il programma contenente la logica applicativa può avere pochissimo effetto.
Infatti il C++ ormai è in disuso nelle aziende, relegato solo ad ambienti embedded, encoding audio/video; perchè ci sono aziende come Microsoft e Sun che hanno creato ambienti di sviluppo migliori.
A nessuno interessa la velocità di esecuzione.
Il mio era un discorso di tipo differenziale: avendo una disposizione due versioni dello stesso applicativo, di cui una scritta con un linguaggio managed ed una con un linguaggio unmanaged, la differenza di pura velocità di esecuzione (perchè di questa parliamo) giustificherebbe la differenza di prezzo?
Sei sicuro che costerebbe di più?
Rinunceresti alla SAN con i canali in fibra? No, perchè non è per la velocità di esecuzione che l'hai presa verosimilmente.
Rinunceresti agli switch di rete ridondati? No, perchè non è per la velocità di esecuzione che ne hai ordinati due.
Forse, diciamo, potresti evitare di comprare uno dei quattro server che stanno dietro al tuo load balancer (al quale non puoi rinunciare, per i motivi di cui sopra): il risparmio si ridurrebbe perciò ad un paio di migliaia di euro.
Magari triplica la cifra che hai menzionato.
Comunque ormai i linguaggi managed sono lo standard aziendale, perchè sono stati creati strumenti intorno che li rendono intrinsecamente migliori.
Però in cambio dovresti rinunciare a tutti i benefici di una piattaforma managed...
Che sono l'ambiente di sviluppo e gli strumenti immediatamente disponibili allo sviluppatore.
Intendiamoci, io non sono un grande esperto di questo genere di questioni, riporto solo le mie impressioni personali, che derivano da un po' di esperienza e da un po' di sentito dire, però non mi sentirei di dire, a tutt'oggi, che sia meglio intraprendere uno sviluppo su di un sistema unmanaged piuttosto che uno managed, nella maggioranza dei casi.
Anche perchè non hai alternative, le aziende oggi lavorano in Java o .NET.
Solo che a volte rimani scottato come con .NET 1.1 il cui ambiente di sviluppo non è più supportato in Vista e gli applicativi sono non importabili nei nuovi ambienti.
Tornando poi al caso esposto da Johnn, forse farebbe premio la maggiore "riusabilità" del codice managed (specie se scritto secondo i criteri dell'OO, ma se si parla di Java, C#, Ruby, Python, ...) rispetto alle maggiori performance di quello funzionale, perchè ritengo (ma è solo una sensazione) che la perdita di performance, anche se ci fosse, sarebbe comunque una percentuale poco significativa dell'esecuzione del totale. E siccome non si tratta di compiti rt, ne deduco che, per esempio, aspettare 31 giorni per un risultato anzichè 30 non farebbe molta differenza.
:mano:
Credo che per funzionale tu intenda procedurale ovvero C (e non C++), altrimenti pensa che C# ha introdotto elementi di programmazione funzionale.
Prova ad aprire connessioni magari al database centrale dell'azienda e ad aspettare che sia il GC a chiuderle, il server comincia a segnalare che ci sono troppe connessioni nel giro di pochi minuti, fermando il lavoro di tutta l'azienda.
Il garbage collector serve per la gestione della memoria, non delle risorse. Usarlo anche per quest'ultimo e' di solito un errore indotto da cattive librerie di sistema o da un linguaggio mal progettato. Molti linguaggi di alto livello supportano un uso corretto delle risorse (Ruby, Python, CL etc.)
Scusa che differenza c'è tra chiamare correttamente una delete e chiamare correttamente un metodo Dispose?
Poi puntualmente trovi metodi Dispose chiamati male, perchè tanto c'è il GC, nessuno ha mai imparato a gestire la memoria e quindi la deallocazione corretta delle risorse, nessuno si prende la briga di studiare lo using...
Doversi occupare "solo" delle risorse e' comunque un vantaggio, perche' piu' localizzate e facili da gestire, in quanto e' piu' chiaro chi sia il "proprietario". In teoria dovrebbero essere necessari ben pochi Dispose.
Le interfacce grafiche in Java sembrano lentissime anche su dei Core2Duo ben carrozzati.
Sia all'avvio sia durante l'esecuzione, ho come esempio NetBeans che ci mette 40 secondi ad avviarsi e spesso si ferma a pensare quando devi aprire un menu o altro.
Ma la mia esperienza con Java è disastrosa su tutti i computer che ho potuto provare, contrariamente a quello che riportano altri.
Probabilmente quello che per me è inaccettabile come prestazioni per altri risulta adeguato.
Sono dell'opinione che piu' che che al linguaggio in se' la lentezza sia dovuta piu' a come e' architettata la libreria standard, con cataste di metodi ed oggetti. E' anche evidente che quando e' stata ideata le performance non erano tra i requisiti principali e la cosa si nota. Basta confrontare le classi di I/O di Java e C++ per notare la differenza. Questa tendenza tra l'altro mi sembra si sia diffusa anche agli utilizzatori, con i deleteri effetti del caso.
perchè proprio la sua capacità di "basso livello" da una parte aumenta le possibili ottimizzazioni, dall'altra impedisce l'uso di automatismi da piattaforma managed, appunto. chi l'ha detto, i garbage collectors esistono anche per C++.
queste sono scritte in C/C++ e probabilmente resteranno sempre così, perchè potranno essere riutilizzate a piacere da programmi scritti in altri linguaggi come mai adesso una libreria può essere utilizzata da programmi scritti in altri linguaggi solo se scritta in C o C++?
(i driver per i dispositivi sono scritti in C, ma ne beneficia tutto il S.O. e tutti gli applicativi che ci girano sopra, siano essi scritti in Java, .NET, Python, Ruby, ...). i drivers non sono librerie, spero sia chiaro...
Le interfacce grafiche in Java sembrano lentissime anche su dei Core2Duo ben carrozzati.
Sia all'avvio sia durante l'esecuzione, ho come esempio NetBeans che ci mette 40 secondi ad avviarsi e spesso si ferma a pensare quando devi aprire un menu o altro.
Ma la mia esperienza con Java è disastrosa su tutti i computer che ho potuto provare, contrariamente a quello che riportano altri.
Probabilmente quello che per me è inaccettabile come prestazioni per altri risulta adeguato.
Sono dell'opinione che piu' che che al linguaggio in se' la lentezza sia dovuta piu' a come e' architettata la libreria standard, con cataste di metodi ed oggetti. E' anche evidente che quando e' stata ideata le performance non erano tra i requisiti principali e la cosa si nota. Basta confrontare le classi di I/O di Java e C++ per notare la differenza. Questa tendenza tra l'altro mi sembra si sia diffusa anche agli utilizzatori, con i deleteri effetti del caso.
bla bla bla :blah:
ovviamente inutile dire che sono l'unico fortunello a cui i menu di NetBeans si aprono al click e che di certo non ho un Core2Duo ben carrozzato :rolleyes:
edit - sapete indicarmi uno di quei programmi per registrare un video di ciò che accade sullo schermo? vorrei prendere un video dell'apertura di un menu di uno di quei programmoni Java belli grassi e grossi, tipo Eclipse e NetBeans, così poi ve lo faccio vedere :asd:
tomminno
07-10-2008, 09:54
Il garbage collector serve per la gestione della memoria, non delle risorse. Usarlo anche per quest'ultimo e' di solito un errore indotto da cattive librerie di sistema o da un linguaggio mal progettato. Molti linguaggi di alto livello supportano un uso corretto delle risorse (Ruby, Python, CL etc.)
Il GC chiude le risorse quando esegue, ma te prova a fare delle sqlconnection e a non chiamare manualmente il dispose in maniera corretta, replica questa circostanza per migliaia di applicativi che girano intorno ad un db aziendale e vedrai l'uso corretto delle risorse che fine fa.
tomminno
07-10-2008, 09:56
Doversi occupare "solo" delle risorse e' comunque un vantaggio, perche' piu' localizzate e facili da gestire, in quanto e' piu' chiaro chi sia il "proprietario". In teoria dovrebbero essere necessari ben pochi Dispose.
In C# forse nessuno se è il caso di usare lo using. Però una volta che qualcuno ti passa un riferimento potresti fare il Dispose nel momento sbagliato esattamente come la delete
khelidan1980
07-10-2008, 10:08
bla bla bla :blah:
ovviamente inutile dire che sono l'unico fortunello a cui i menu di NetBeans si aprono al click e che di certo non ho un Core2Duo ben carrozzato :rolleyes:
edit - sapete indicarmi uno di quei programmi per registrare un video di ciò che accade sullo schermo? vorrei prendere un video dell'apertura di un menu di uno di quei programmoni Java belli grassi e grossi, tipo Eclipse e NetBeans, così poi ve lo faccio vedere :asd:
Non renderebbe l'idea,in quei video la reattività del sistema sembra di un ordine di grandezza inferiore! ;)
Le interfacce grafiche in Java sembrano lentissime anche su dei Core2Duo ben carrozzati.
Sia all'avvio sia durante l'esecuzione, ho come esempio NetBeans che ci mette 40 secondi ad avviarsi e spesso si ferma a pensare quando devi aprire un menu o altro.
Ma la mia esperienza con Java è disastrosa su tutti i computer che ho potuto provare, contrariamente a quello che riportano altri.
Probabilmente quello che per me è inaccettabile come prestazioni per altri risulta adeguato.
Sinceramente Eclipse non mi sembra poi così lento
tomminno
07-10-2008, 10:16
edit - sapete indicarmi uno di quei programmi per registrare un video di ciò che accade sullo schermo? vorrei prendere un video dell'apertura di un menu di uno di quei programmoni Java belli grassi e grossi, tipo Eclipse e NetBeans, così poi ve lo faccio vedere :asd:
Cerchi qualcosa tipo questo?
http://www.microsoft.com/windows/windowsmedia/howto/articles/screencap.aspx
variabilepippo
07-10-2008, 12:03
Poi puntualmente trovi metodi Dispose chiamati male, perchè tanto c'è il GC, nessuno ha mai imparato a gestire la memoria e quindi la deallocazione corretta delle risorse
Puoi lasciare appese le risorse sia in Assembly, sia con un qualsiasi linguaggio managed. La gestione delle risorse (il tuo esempio iniziale era riferito alle connessione ad un DB) è compito del programmatore, se uno non chiude una connessione per dimenticanza, per incompetenza, per scelta deliberata o altro è colpa sua, non del GC (che è pensato per fare altre cose, non per sostituire il programmatore nella gestione delle aperture/chiusure di una connessione)! :) Non a caso le classi per la gestione delle connessioni prevedono metodi Open e Close.
Il GC chiude le risorse quando esegue, ma te prova a fare delle sqlconnection e a non chiamare manualmente il dispose in maniera corretta, replica questa circostanza per migliaia di applicativi che girano intorno ad un db aziendale e vedrai l'uso corretto delle risorse che fine fa.
Quello che intendevo dire che una corretta gestione delle risorse prevede che le risorse non vengano liberate manualmente dal dispose, ma tramite altri meccanismi, o tramite un qualche oggetto responsabile (le risorse dovrebbero comunque avere sempre un proprietario) o, meglio, dallo scope.
Ad esempio in ruby puoi fare qualcosa del tipo
File.open("somefile.dat","w") {
# Use the file here
}
e quando si esce dal blocco per qualsiasi motivo (eccezioni comprese) il file viene chiuso. In questo modo ottieni quasi tutto gratis.
tomminno
07-10-2008, 12:43
Quello che intendevo dire che una corretta gestione delle risorse prevede che le risorse non vengano liberate manualmente dal dispose, ma tramite altri meccanismi, o tramite un qualche oggetto responsabile (le risorse dovrebbero comunque avere sempre un proprietario) o, meglio, dallo scope.
Ad esempio in ruby puoi fare qualcosa del tipo
File.open("somefile.dat","w") {
# Use the file here
}
e quando si esce dal blocco per qualsiasi motivo (eccezioni comprese) il file viene chiuso. In questo modo ottieni quasi tutto gratis.
Che è quello che ottieni per definizione dal C++, mentre in altri linguaggi hai bisogno di catene chilometriche di try finally per tutto quello che può andare storto, ovvero tutto. In C# per fortuna hanno messo lo using che evita tutto questo.
L'ultima spiaggia è il GC.
incipit1970
07-10-2008, 17:28
Che è quello che ottieni per definizione dal C++, mentre in altri linguaggi hai bisogno di catene chilometriche di try finally per tutto quello che può andare storto, ovvero tutto. In C# per fortuna hanno messo lo using che evita tutto questo.
L'ultima spiaggia è il GC.
Non esattamente: la distruzione automatica degli oggetti C++ avviene unicamente per le variabili con scope in stack. Sul heap è come Java, ma senza GC. Se fai una new e dimentichi il delete, hai esattamente lo stesso problema (senza il GC che ti corregge la fuga di memoria, però). Non per niente i programmi in C++ sono molto tendenti alle memory leaks, resource leaks e quant'altro (ci sono persino i debugger specializzati per scovare bug di quel tipo). Il GC è stato pensato appunto per correggere (in modo automatico e pertanto non ottimale) un comunissimo errore di programmazione (comune principalmente nei linguaggi unmanaged come C++). Potresti usare smart pointers, ma anche quelli hanno un costo in termini di performance.
Certo dirai che una programmazione ideale dovrebbe prendere in considerazione questi errori, e concordo. Non è certo un diffetto del linguaggio, ma del programmatore. Ma questo è un mondo imperfetto: molti programmatori commettono questi errori, quindi eliminare la causa del problema migliora, in modo economico, la qualità del programma e diminuisce i cicli di correzione errori.
Poi, per quanto riguarda la velocità delle interfacce UI in Java, hai ragione, ma non vedo il problema: Java infatti è usato bene soprattutto in ambito enterprise, dove non ha paragoni per la richezza delle librerie e di codice già pronto. Non ha molto uso nella creazione di applicazioni client (nemmeno gli applet hanno avuto grosso successo, figuriamoci un programma in AWT). Se devo fare un programma che gira su Windows, userei Visual C++, o qualcosa di simile (non andrei nemmeno su C# o VisualBasic).
Ho avuto un'esperienza con un grosso programma enterprise (un sito web) interamente scritto in C++ e CORBA, ed è una esperienza che non vorrei ripetere: non solo era lento come o più di un programma in Java o persino PHP, già solo compilare e rilasciare l'applicazione era estremamente complicato, così come il debugging. Per non parlare di problemi di concorrenzialità, locking del db, etc.
Di nuovo, ripeto: ogni linguaggio andrebbe usato nel ambito che più gli si addisce.
Non esattamente: la distruzione automatica degli oggetti C++ avviene unicamente per le variabili con scope in stack. Sul heap è come Java, ma senza GC. Se fai una new e dimentichi il delete, hai esattamente lo stesso problema (senza il GC che ti corregge la fuga di memoria, però). Non per niente i programmi in C++ sono molto tendenti alle memory leaks, resource leaks e quant'altro (ci sono persino i debugger specializzati per scovare bug di quel tipo). Il GC è stato pensato appunto per correggere (in modo automatico e pertanto non ottimale) un comunissimo errore di programmazione (comune principalmente nei linguaggi unmanaged come C++). Potresti usare smart pointers, ma anche quelli hanno un costo in termini di performance.
Penso che il discorso di tommino fosse ortogonale alla presenza o meno di un garbage collector. In C++ hai la possibilita' di allocare sullo stack e quindi ottenere automaticamente la deallocazione automatica all'uscita dallo scope. In linguaggi che non permettono di farlo devi fornire un mezzo alternativo (blocchi in Ruby, using in C# etc.), altrimenti gestire la cosa diventa molto complicato (come mi sembra di capire sia in Java).
Poi, per quanto riguarda la velocità delle interfacce UI in Java, hai ragione, ma non vedo il problema: Java infatti è usato bene soprattutto in ambito enterprise, dove non ha paragoni per la richezza delle librerie e di codice già pronto.
Non e' piu' un problema perche' le performance ne hanno assassinato l'uso sul lato desktop. Java e' "finito" in ambito enterprise dopo che ha fallito in altri (tra cui appunto quello desktop e client internet, dove in teoria le sue qualita' dovrebbero aver maggior risalto). Adesso la situazione e' migliorata, pero' il passato ha lasciato il segno.
Ho avuto un'esperienza con un grosso programma enterprise (un sito web) interamente scritto in C++ e CORBA, ed è una esperienza che non vorrei ripetere
E' un'esperienza che sto facendo pure io, e non consiglierei l'accoppiata C++ e CORBA neanche ad un condannato a morte :asd:
Veramente anche nei linguaggi managed devi deallocarti correttamente le risorse unmanaged, da una parte gestisci manualmente la memoria, dall'altra gestisci manualmente tutte le altre risorse, non ci vedo una gran differenza.
Per la mia esperienza trovo sempre colleghi che non hanno mai studiato il C/C++ che non usano correttamente la deallocazione delle risorse anche in linguaggi managed e questo a volte causa più danni di un memory leak in un singolo applicativo, tipo saturazione delle connessioni al db.
Sì, ma come hanno sottolineato altri, linguaggi managed e unmanaged condividono lo stesso insieme di problemi di "deallocazione" di risorse, solo che i linguaggi unmanaged ne aggiungono uno in più: quello della gestione della memoria (dello heap).
Forse però ti sto fraintendendo, e tu intendi dire che la mancanza di praticità col concetto di liberare le risorse alla chiusura di un applicativo derivata dall'utilizzo dei linguaggi managed a causa dell'utilizzo del gc che questi fanno porta a "cattive abitudini" quando si programma in questi linguaggi. Su questo non so cosa risponderti, non ho una risposta precisa: ancora, credo che riguardi più il tipo di insegnamento che si è ricevuto nella programmazione "in generale" che nella programmazione con linguaggi "managed" in particolare.
Ho avuto modo di fare esattamente gli stessi applicativi in più linguaggi e con un codice che è praticamente identico (tra l'altro assolutamente if-less), salvo le dovute differenze di linguaggio, la differenza prestazionale in questi casi era 1:8 e il bello è che essendo stato lo sviluppo C++ il porting di quello C# non mi ha portato via più di un paio d'ore, con il vantaggio che ora i parser riescono ad elaborare nelle 24 ore e a stare al passo con le tonnellate di log giornaliere.
Mi sembra di ricordare dei tuoi interventi sul forum in merito a questo problema: siccome però mi sembra molto strano, posso permettermi di pensare che tu abbia trovato un "caso particolare" in cui C++ funziona enormemente meglio di C#.
Infatti il C++ ormai è in disuso nelle aziende, relegato solo ad ambienti embedded, encoding audio/video; perchè ci sono aziende come Microsoft e Sun che hanno creato ambienti di sviluppo migliori.
A nessuno interessa la velocità di esecuzione.
Sei sicuro che costerebbe di più?
Magari triplica la cifra che hai menzionato.
Comunque ormai i linguaggi managed sono lo standard aziendale, perchè sono stati creati strumenti intorno che li rendono intrinsecamente migliori.
Che sono l'ambiente di sviluppo e gli strumenti immediatamente disponibili allo sviluppatore.
Anche perchè non hai alternative, le aziende oggi lavorano in Java o .NET.
Ne deduco che per te i linguaggi managed siano prevalenti per motivazioni storiche e non di merito: sono in sostanza capitati al momento giusto e nel posto giusto, e sono molto diffusi perchè tutti li usano e nessuno vuole gettarli via per far posto a qualcos'altro, visti i soldi investiti e la loro ubiquità. Poi ci sono ottime librerie, buoni ambienti di sviluppo eccetera.
Anche qui, non saprei cosa dirti: potrebbe anche essere vero (anche se qualcosa mi suggerisce che forse a nessuno interessava più gestire autonomamente certi problemi, e si è preferito delegarli per astrarre ulteriormente, e nel contesto tecnologico attuale il trade-off risulta sbilanciato verso i linguaggi managed). Però questo non è un buon motivo per programmare in un linguaggio come C++ anzichè in Java (o C#, o Ruby, o Python, ...).
Solo che a volte rimani scottato come con .NET 1.1 il cui ambiente di sviluppo non è più supportato in Vista e gli applicativi sono non importabili nei nuovi ambienti.
Non lo sapevo.
Credo che per funzionale tu intenda procedurale ovvero C (e non C++), altrimenti pensa che C# ha introdotto elementi di programmazione funzionale.
Lapsus. :D
chi l'ha detto, i garbage collectors esistono anche per C++.
Non lo sapevo, ma in ogni caso, siccome tommino lamentava il fatto che i gc infliggono pesanti danni prestazionali alle applicazioni che ne fanno uso, mentre C++ ne è immune proprio perchè non li usa, non avrebbe molto senso paragonare C++ + gc con Java, perchè in teoria dovrebbero avere le stesse performance.
Io credo che però la JVM abbia altri "assi" nella manica per abbassare le performance in altre operazioni, tipicamente i controlli sugli array et similia, e che non sia il gc la vera causa del degrado prestazionale (che peraltro, sempre IMVHO, va cercato col lanternino, al di fuori degli ambiti in cui è sempre stato usato il C/C++ finora e nessuno ha mai pensato di cambiarlo con qualcos'altro).
Per tornare IT, penso che le probabilità di Johnn di incontrare questi ambiti sia molto bassa, e quindi gli suggerei di procedere con i linguaggi managed. Ecco. :D
come mai adesso una libreria può essere utilizzata da programmi scritti in altri linguaggi solo se scritta in C o C++?
Intendevo dire: se proprio credi che la tua funzione / metodo / procedura fatta in Java / C # / ... sia troppo lenta perchè eseguita in JVM / CLR / ... , procurati o scriviti l'equivalente fatto in C / C++, testato, compilato, assemblato e "velocissimo", e invoca quello. In Java è complicato, in C# meno, eccetera.
i drivers non sono librerie, spero sia chiaro...
Sì: ma sono scritti in C / C++ / Assembly e mi serviva un "esempio-di-codice-scritto-in-questi-linguaggi-che-riusi-senza-farti-troppi-problemi-per-motivi-di-performance-anche-se-non-sai-nulla-di-programmazione-unmanaged" (cioè, il mondo è pieno di codice unmanaged, e lo usiamo quando ci serve, senza bisogno di scrivere tutto in codice unmanaged).
Ho avuto modo di fare esattamente gli stessi applicativi in più linguaggi e con un codice che è praticamente identico (tra l'altro assolutamente if-less), salvo le dovute differenze di linguaggio, la differenza prestazionale in questi casi era 1:8 e il bello è che essendo stato lo sviluppo C++ il porting di quello C# non mi ha portato via più di un paio d'ore, con il vantaggio che ora i parser riescono ad elaborare nelle 24 ore e a stare al passo con le tonnellate di log giornaliere.
Sono dell'opinione che piu' che che al linguaggio in se' la lentezza sia dovuta piu' a come e' architettata la libreria standard, con cataste di metodi ed oggetti. E' anche evidente che quando e' stata ideata le performance non erano tra i requisiti principali e la cosa si nota. Basta confrontare le classi di I/O di Java e C++ per notare la differenza. Questa tendenza tra l'altro mi sembra si sia diffusa anche agli utilizzatori, con i deleteri effetti del caso.
Ma perché l'I/O in Java (o C#) è più lento tanto da avere un rapporto di 1:8? E' l'uso errato di alcune classi di I/O non adatte allo scopo, errori di programmzione o carratteristiche intrinseche al linguaggio che non possono essere ovviate? Se è la libreria standard il problema, potrebbe essere modificata per migliorarla?
Potresti usare smart pointers, ma anche quelli hanno un costo in termini di performance.
Non lo sapevo, ma in ogni caso, siccome tommino lamentava il fatto che i gc infliggono pesanti danni prestazionali alle applicazioni che ne fanno uso, mentre C++ ne è immune proprio perchè non li usa, non avrebbe molto senso paragonare C++ + gc con Java, perchè in teoria dovrebbero avere le stesse performance.
Io credo che però la JVM abbia altri "assi" nella manica per abbassare le performance in altre operazioni, tipicamente i controlli sugli array et similia, e che non sia il gc la vera causa del degrado prestazionale (che peraltro, sempre IMVHO, va cercato col lanternino, al di fuori degli ambiti in cui è sempre stato usato il C/C++ finora e nessuno ha mai pensato di cambiarlo con qualcos'altro).
Proprio questo è un punto che mi incuriosisce parecchio. Esistono gc per c++, che però non sono stadard. Oppure si possono usare smart pointer. Ma in entrambi i casi si aggiunge overhead al velocissimo c++. Questo c++ + gc raggiunge o supera le "cattive" prestazioni del Java? Perché altrimenti o non si ha a che fare con problemi di deallocazione della memoria, o sono molto semplici essendo risolvibili con piccoli trucchi, oppure neanche si deve pensare al c++! In più, deallocazioni ad hoc affidate al programmatore, come possono essere, in generale più efficienti del garbage collector? Mi pare come il confronto tra C e assembler. L'assembler è sulla carta più efficiente, ma con i compilatori C odierni è quasi impossibile fare meglio.
Per tornare IT, penso che le probabilità di Johnn di incontrare questi ambiti sia molto bassa, e quindi gli suggerei di procedere con i linguaggi managed. Ecco. :D
Il fatto è che sto valutando il porting di un software definito, quindi vorrei capire bene se le "inefficienze" di un linguagio unmanaged vengano bilanciate dai vantaggi. Il mio obiettivo sarebbe rendere l'implementazione java paragonabile a quella c++ (già esistente). Non potrei accettare un rapporto 1:8, ad esempio. Nel mio caso non avrò a che fare con db, risorse esterne e I/O. Solo ram e cpu.
Comunque la discussione che sta venendo fuori mi piace anche se vengono coinvolti aspetti come interfacce grafiche, db, ecc. in modo da capire quali sono i limiti di un linguaggio rispetto ad un altro e fare delle scelte opportune in futuro. Su queste tematiche mi pare i sia molta confusione e molto "sentito dire".
Per la discussione eclipse è lento/ no il mio è una scheggia, ho scoperto di recente che contanto anche le opzioni della jvm con cui viene lanciato.
Intendevo dire: se proprio credi che la tua funzione / metodo / procedura fatta in Java / C # / ... sia troppo lenta perchè eseguita in JVM / CLR / ... , procurati o scriviti l'equivalente fatto in C / C++, testato, compilato, assemblato e "velocissimo", e invoca quello. In Java è complicato, in C# meno, eccetera.
Ma JNI è inefficiente/complicato? Solo a livello sintattico o c'è altro?
tomminno
09-10-2008, 08:12
Sì, ma come hanno sottolineato altri, linguaggi managed e unmanaged condividono lo stesso insieme di problemi di "deallocazione" di risorse, solo che i linguaggi unmanaged ne aggiungono uno in più: quello della gestione della memoria (dello heap).
La differenza è che in C++ devo gestire solo la memoria nei linguaggi managed non gestisco la memoria ma tutto il resto.
Ad esempio se devo scrivere su un file in C++ una volta che l'oggetto di tipo ofstream è uscito dallo scope ho la garanzia che il file è chiuso, se uso lo StreamWriter in C# devo assicurarmi di usare lo using o gestire complicatamente a mano le possibili eccezioni per garantire la corretta chiusura del file (e dire che lavoro in una azienda dove è scosigliato l'utilizzo dello using "perchè fa casini", ma io sostanzialmente me ne frego delle indicazioni senza senso che arrivano dall'alto).
Non mi verrebbe mai in mente di mettere in C++ di mettere l'ofstream su heap.
Stesso discorso per le connessioni al db.
Forse però ti sto fraintendendo, e tu intendi dire che la mancanza di praticità col concetto di liberare le risorse alla chiusura di un applicativo derivata dall'utilizzo dei linguaggi managed a causa dell'utilizzo del gc che questi fanno porta a "cattive abitudini" quando si programma in questi linguaggi. Su questo non so cosa risponderti, non ho una risposta precisa: ancora, credo che riguardi più il tipo di insegnamento che si è ricevuto nella programmazione "in generale" che nella programmazione con linguaggi "managed" in particolare.
In buona sostanza si. Dato che c'è il GC ci possiamo pure permettere il lusso di non rilasciare le risorse o per lo meno di non sapere nemmeno che esiste l'interfaccia IDisposable e a cosa serva.
Mi sembra di ricordare dei tuoi interventi sul forum in merito a questo problema: siccome però mi sembra molto strano, posso permettermi di pensare che tu abbia trovato un "caso particolare" in cui C++ funziona enormemente meglio di C#.
I casi particolari sarebbero parecchi a quanto ho potuto sperimentare. Comunque è bello notare che anche usando un oggetto comune tra gli applicativi come il LogParser della Microsoft e quindi con un programma che effettua quasi esclusivamente chiamate all'oggetto COM e scrive su un file esegua in metà tempo se scritto in C++ rispetto a quello C#.
Per non parlare incredibilmente dell'accesso a file remoti, dove la lentezza della rete dovrebbe mitigare se non annullare le differenze.
Ne deduco che per te i linguaggi managed siano prevalenti per motivazioni storiche e non di merito: sono in sostanza capitati al momento giusto e nel posto giusto, e sono molto diffusi perchè tutti li usano e nessuno vuole gettarli via per far posto a qualcos'altro, visti i soldi investiti e la loro ubiquità. Poi ci sono ottime librerie, buoni ambienti di sviluppo eccetera.
No, secondo me hanno stravinto perchè ci sono state aziende che hanno sponsorizzato e quindi investito su linguaggi diciamo "proprietari" e quindi hanno creato strumenti e librerie per lo sviluppo migliori.
Lo standard C++ evolve ogni 10 anni con revisioni ogni 5 anni come tutti gli standard, non ha nessuna azienda che lo "sponsorizza" è chiaro che è rimasto indietro come linguaggio rispetto a quello che possono permettersi linguaggi aggiornati ogni 2 anni.
Cosa impedirebbe per dire di fare una libreria C++ che raccoglie il 95% delle caratteristiche del .NET? (rimane fuori la reflection)
Sarebbe così tremendamente più produttivo .NET?
Io dico di no per esperienza personale, ho avuto modo di partecipare a qualche grosso progetto in C++ dove c'era già tutto il codice necessario a smazzarsi le operazioni più noiose (che è quello che alla fine fa il framework .NET).
Anche qui, non saprei cosa dirti: potrebbe anche essere vero (anche se qualcosa mi suggerisce che forse a nessuno interessava più gestire autonomamente certi problemi, e si è preferito delegarli per astrarre ulteriormente, e nel contesto tecnologico attuale il trade-off risulta sbilanciato verso i linguaggi managed). Però questo non è un buon motivo per programmare in un linguaggio come C++ anzichè in Java (o C#, o Ruby, o Python, ...).
Ripeto ormai commercialmente il C++ è relegato ad ambienti molto ristretti quindi non è più un quesito da porsi.
cdimauro
09-10-2008, 08:34
Non bastano le librerie: anche il linguaggio fa la sua parte. E mi permetto di aggiungere: ovviamente.
Altrimenti non staremmo qui tutti a smazzarci C#, Java, Python, Ruby, ecc...
tomminno
09-10-2008, 08:53
Non esattamente: la distruzione automatica degli oggetti C++ avviene unicamente per le variabili con scope in stack. Sul heap è come Java, ma senza GC. Se fai una new e dimentichi il delete, hai esattamente lo stesso problema (senza il GC che ti corregge la fuga di memoria, però).
Si ma assai probabilmente non avrei creato un oggetto nello heap.
Non per niente i programmi in C++ sono molto tendenti alle memory leaks, resource leaks e quant'altro (ci sono persino i debugger specializzati per scovare bug di quel tipo). Il GC è stato pensato appunto per correggere (in modo automatico e pertanto non ottimale) un comunissimo errore di programmazione (comune principalmente nei linguaggi unmanaged come C++). Potresti usare smart pointers, ma anche quelli hanno un costo in termini di performance.
Dalle mie escursioni con Reflector negli assembly .net credo che le prestazioni non siano degradate dal GC, ma dalle tonnellate di codice che stanno dietro ad ogni metodo esposto dal framework.
Certo dirai che una programmazione ideale dovrebbe prendere in considerazione questi errori, e concordo. Non è certo un diffetto del linguaggio, ma del programmatore. Ma questo è un mondo imperfetto: molti programmatori commettono questi errori, quindi eliminare la causa del problema migliora, in modo economico, la qualità del programma e diminuisce i cicli di correzione errori.
Poi, per quanto riguarda la velocità delle interfacce UI in Java, hai ragione, ma non vedo il problema: Java infatti è usato bene soprattutto in ambito enterprise, dove non ha paragoni per la richezza delle librerie e di codice già pronto. Non ha molto uso nella creazione di applicazioni client (nemmeno gli applet hanno avuto grosso successo, figuriamoci un programma in AWT). Se devo fare un programma che gira su Windows, userei Visual C++, o qualcosa di simile (non andrei nemmeno su C# o VisualBasic).
In ambito enteprise non hai nemmeno le interfacce grafiche, usi strumenti di ben altro livello per risolvere ben altri problemi (penso banalmente a ORM ed ESB), dove semplicemente l'ambiente .NET non arriva per limitazione, non a caso lo strumento Microsoft per l'ESB è in C++.
Tutto il resto è solo Java.
Di nuovo, ripeto: ogni linguaggio andrebbe usato nel ambito che più gli si addisce.
Infatti gli ambiti del C++ sono ridotti al lumicino.
tomminno
09-10-2008, 09:04
Non bastano le librerie: anche il linguaggio fa la sua parte. E mi permetto di aggiungere: ovviamente.
Altrimenti non staremmo qui tutti a smazzarci C#, Java, Python, Ruby, ecc...
Il linguaggio senza la libreria standard che lo supporta è solo un'insieme di regole sintattiche e semantiche.
Il vantaggio enorme dei linguaggi managed è che generalmente i task di base sono già tutti fatti.
Se devo connettermi via TCP ho già la classe pronta, non devo ripartire dai socket BSD, se devo inviare una email ho la classe apposita, non devo implementarmi il protocollo SMTP, se devo connettermi ad un db ho pure lì la classe wrappata in modo che sia semplice da usare, non devo scrivermi io un wrapper sopra l'ODBC.
Prova però a dover fare da proxy tra un POP3 e SMTP e magicamente la produttività del linguaggio decade perchè non ci sono gli strumenti pre-creati.
Prova a lavorare su un ORM in C# e la produttività decade rispetto a Java dove ci sono strumenti integrati che smazzano il lavoro sporco.
Prova a creare un'applicazione enterprise in C# che gestisca lo scambio di messaggi e usi C++ o Java (e quindi scegli Java anche perchè offre prodotti open source).
cdimauro
09-10-2008, 10:05
Fortunatamente i linguaggi "managed" hanno ottime librerie.
Anche per C++ esistono, sia chiaro, ma non sono standard. E quando Boost diventerà parte dello standard, rimarrà comunque un framework gigantesco da portarsi dietro...
Comunque a parità di funzionalità di libreria, il linguaggio fa la differenza, eccome.
incipit1970
10-10-2008, 11:40
Ma perché l'I/O in Java (o C#) è più lento tanto da avere un rapporto di 1:8? E' l'uso errato di alcune classi di I/O non adatte allo scopo, errori di programmzione o carratteristiche intrinseche al linguaggio che non possono essere ovviate? Se è la libreria standard il problema, potrebbe essere modificata per migliorarla?
Lo è stata: infatti hanno implementato il NIO, che aggira alcuni dei colli di bottiglia del java.io tradizionale ed è molto più veloce (pochissimo di meno del I/O di C++).
Proprio questo è un punto che mi incuriosisce parecchio. Esistono gc per c++, che però non sono stadard. Oppure si possono usare smart pointer. Ma in entrambi i casi si aggiunge overhead al velocissimo c++. Questo c++ + gc raggiunge o supera le "cattive" prestazioni del Java? Perché altrimenti o non si ha a che fare con problemi di deallocazione della memoria, o sono molto semplici essendo risolvibili con piccoli trucchi, oppure neanche si deve pensare al c++! In più, deallocazioni ad hoc affidate al programmatore, come possono essere, in generale più efficienti del garbage collector? Mi pare come il confronto tra C e assembler. L'assembler è sulla carta più efficiente, ma con i compilatori C odierni è quasi impossibile fare meglio.
Si, esistono GC per C++. Come tutte le cose di C++ hanno il vantaggio della flessibilità, il GC non funziona per tutti gli oggetti in heap ma funziona come un bag dove metti ciò che vuoi (ti rimane dunque sempre il heap per utilizzare la memoria "in modo standard"). A velocità, come tutte le librerie, dipende dall'implementazione fatta.
Le deallocazioni "manuali" sono più efficienti (in media, non bisogna mai generalizzare) perché non devi controllare tutti gli oggetti allocati in un determinato momento per capire quali sono da riciclare e quali sono ancora in uso (questo è in pratica ciò che fa il GC). Dico in media perché in casi patologici di utilizzo di memoria al limite può verificarsi il contrario (un heap managed potrebbe anche avere un algoritmo di allocazione della memoria più efficiente di quello del SO sottostante, quindi tante chiamate a malloc() potrebbero far degenerare le performance).
Il fatto è che sto valutando il porting di un software definito, quindi vorrei capire bene se le "inefficienze" di un linguagio unmanaged vengano bilanciate dai vantaggi.
Il bilanciamento dipende dall'applicazione specifica. Come detto, in ambito enterprise i linguaggi managed superano di gran lunga l'utilità dei linguaggi unmanaged. Ma è una casistica particolare.
Il mio obiettivo sarebbe rendere l'implementazione java paragonabile a quella c++ (già esistente). Non potrei accettare un rapporto 1:8, ad esempio. Nel mio caso non avrò a che fare con db, risorse esterne e I/O. Solo ram e cpu.
Per quanto riguarda la RAM, come detto l'unico collo di bottiglia è il GC (e questo solo quando deve recuperare memoria perché si sta esaurendo). Se gestisci bene la memoria, il GC può funzionare poco, ed il degrado di prestazioni è molto contenuto. Per quanto riguarda la CPU, dipende da ciò che usi, in media le istruzioni di calcolo non sono molto diverse in termini di prestazioni rispetto a quelle di un linguaggio unmanaged, la maggior parte si traduce in chiamate al linguaggio macchina quasi senza intermediazione.
Un vantaggio di Java è che puoi fare un prototipo in poco tempo e fare qualche prova per vedere quanta differenza c'è. Implementa lo stesso algoritmo in entrambi i linguaggi e verifica i tempi di esecuzione su campioni di dati rappresentativi di ciò che dovrai andare ad implementare in seguito.
Comunque la discussione che sta venendo fuori mi piace anche se vengono coinvolti aspetti come interfacce grafiche, db, ecc. in modo da capire quali sono i limiti di un linguaggio rispetto ad un altro e fare delle scelte opportune in futuro. Su queste tematiche mi pare i sia molta confusione e molto "sentito dire".
In realtà, spesso si discute sul linguaggio, ma poco sul programmatore, che invece è chi veramente fa o disfa un programma. Anche se C/C++ è una scheggia, se implementi un algoritmo sballato o poco performante non risolvi niente avendo un linguaggio più "veloce". Una libreria con algoritmi efficienti basata su un linguaggio "lento" spesso risolve meglio di un linguaggio veloce con un algoritmo inefficiente. Un esempio un po' cretino ma valido: se usi un quicksort su Java, sarà sempre più veloce di un bubble sort implementato in C++.
Il vantaggio di avere tante librerie è dovuto al fatto che, in media, chi ha implementato la libreria ha studiato il problema e trovato gli algoritmi più efficienti, in C++ spesso devi fare di testa tua o non hai tempo per analizzare le alternative.
Molti dicono che un linguaggio è lento, ma non si sono minimamente disturbati ad usare un profiler per vedere dove stava il collo di bottiglia: 80 volte su 100, è negli algoritmi implementati da noi e non nel linguaggio vero e proprio.
Detto questo, io non sono contrario a C++ ed anzi lo uso volentieri, ma principalmente per applicazioni desktop (trovo non solo Java, ma qualsiasi altro linguaggio managed, uno spreco di risorse in questo tipo di applicazioni). Qualche volta, quando voglio usare in una applicazione desktop delle comode librerie Java, chiamo le classi Java direttamente dall'applicazione C++ (una specie di JNI a rovescio, è perfettamente fattibile).
Comunque, anche C++ ha delle librerie spettacolari (in media, la qualità del codice è molto superiore a quella delle librerie Java, che spesso non funzionano neanche o sono delle versioni alpha). Un paio di esempi: lo stesso Boost ed SQL Lite. Ma ce ne sono tantissime altre.
Ma JNI è inefficiente/complicato? Solo a livello sintattico o c'è altro?
Inefficiente non è (stai chiamando un metodo scritto in C/C++, quindi la velocità di esecuzione è quella del normale C/C++). Complicato forse un po', ma soprattutto sul lato C++, non tanto sul lato Java. Ma almeno a me è bastato vedere un paio di esempi per riuscire ad usarlo senza problemi di sorta.
cdimauro
10-10-2008, 13:55
Le deallocazioni "manuali" sono più efficienti (in media, non bisogna mai generalizzare) perché non devi controllare tutti gli oggetti allocati in un determinato momento per capire quali sono da riciclare e quali sono ancora in uso (questo è in pratica ciò che fa il GC). Dico in media perché in casi patologici di utilizzo di memoria al limite può verificarsi il contrario (un heap managed potrebbe anche avere un algoritmo di allocazione della memoria più efficiente di quello del SO sottostante, quindi tante chiamate a malloc() potrebbero far degenerare le performance).
In genere i linguaggi non chiamano sempre malloc e free per ogni allocazione, ma fanno uso di pool di memoria, ed è questo che, quando serve, le richiama.
Comunque le deallocazioni "manuali" (o immediate) non sempre più efficienti. Spesso è meglio lasciar allocato lo spazio e liberarlo do un po', quando serve memoria, perché tendenzialmente diminiuisce la frammentazione della memoria (ed è poi più facile compattare i blocchi di memoria).
Per quanto riguarda la RAM, come detto l'unico collo di bottiglia è il GC (e questo solo quando deve recuperare memoria perché si sta esaurendo). Se gestisci bene la memoria, il GC può funzionare poco, ed il degrado di prestazioni è molto contenuto. Per quanto riguarda la CPU, dipende da ciò che usi, in media le istruzioni di calcolo non sono molto diverse in termini di prestazioni rispetto a quelle di un linguaggio unmanaged, la maggior parte si traduce in chiamate al linguaggio macchina quasi senza intermediazione.
Ci sono linguaggi e/o implementazioni che permettono di controllare il funzionamento del GC.
Un vantaggio di Java è che puoi fare un prototipo in poco tempo e fare qualche prova per vedere quanta differenza c'è. Implementa lo stesso algoritmo in entrambi i linguaggi e verifica i tempi di esecuzione su campioni di dati rappresentativi di ciò che dovrai andare ad implementare in seguito.
Infatti uno dei punti chiave dello sviluppo agile è di avere il prima possibile un prototipo per testare il comportamento dell'applicazione con dai reali.
Detto questo, io non sono contrario a C++ ed anzi lo uso volentieri, ma principalmente per applicazioni desktop (trovo non solo Java, ma qualsiasi altro linguaggio managed, uno spreco di risorse in questo tipo di applicazioni). Qualche volta, quando voglio usare in una applicazione desktop delle comode librerie Java, chiamo le classi Java direttamente dall'applicazione C++ (una specie di JNI a rovescio, è perfettamente fattibile).
Mah. Io la penso in maniera diametralmente opposta: è con applicazioni desktop che sarebbe preferibile l'uso di linguaggi managed, perché non sono importanti le prestazioni quanto il funzionamento del programma e la velocità con la quale lo si sviluppa.
Poi è anche vero che tutti i server che ho sviluppato finora li ho scritti in Python... :p
Comunque, anche C++ ha delle librerie spettacolari (in media, la qualità del codice è molto superiore a quella delle librerie Java, che spesso non funzionano neanche o sono delle versioni alpha). Un paio di esempi: lo stesso Boost ed SQL Lite. Ma ce ne sono tantissime altre.
Boost però è un pachiderma.
SQLite è carino (e ci sono binding per praticamente qualunque linguaggio), ma è fortemente fuori specifiche SQL e implementa veramente pochi costrutti. Insomma, per uno che è abituato a trigger, procedure, ecc. è quanto di meno desiderabile. Ma nel suo piccolo ha anche la sua utilità.
Vincenzo1968
10-10-2008, 15:17
...
Comunque, anche C++ ha delle librerie spettacolari (in media, la qualità del codice è molto superiore a quella delle librerie Java, che spesso non funzionano neanche o sono delle versioni alpha). Un paio di esempi: lo stesso Boost ed SQL Lite. Ma ce ne sono tantissime altre.
...
Ohé, non babbiamo: SQLite (http://www.sqlite.org) è scritto in C ;)
...
SQLite è carino (e ci sono binding per praticamente qualunque linguaggio), ma è fortemente fuori specifiche SQL e implementa veramente pochi costrutti. Insomma, per uno che è abituato a trigger, procedure, ecc. è quanto di meno desiderabile. Ma nel suo piccolo ha anche la sua utilità.
L'obiettivo dei progettisti non era, e non è, la sostituzione di SQL Server o Oracle:
http://www.sqlite.org/whentouse.html
SQLite is not designed to replace Oracle. It is designed to replace fopen().
;)
cdimauro
10-10-2008, 20:26
Non farà concorrenza a Oracle, ma implementa più di una semplice fopen, ecc.: http://www.sqlite.org/lang.html e http://www.sqlite.org/omitted.html
Sicuramente in futuro miglioreranno i trigger, e magari introdurranno le stored procedure: sono caratteristiche troppo utili per non inserirle.
Comunque se devo utilizzare un db embedded preferisco questo (http://www.firebirdsql.org/index.php?op=files&id=engine_211), che è MOOOLTO più completo (e passare poi da embedded a client/server è una bazzecola). ;)
Vincenzo1968
10-10-2008, 23:44
Non farà concorrenza a Oracle, ma implementa più di una semplice fopen, ecc.: http://www.sqlite.org/lang.html e http://www.sqlite.org/omitted.html
Sicuramente in futuro miglioreranno i trigger, e magari introdurranno le stored procedure: sono caratteristiche troppo utili per non inserirle.
Comunque se devo utilizzare un db embedded preferisco questo (http://www.firebirdsql.org/index.php?op=files&id=engine_211), che è MOOOLTO più completo (e passare poi da embedded a client/server è una bazzecola). ;)
Sono tutt'e due molto efficienti(utilizzano entrambi parser di tipo LALR(1) per il parsing SQL ;) ).
SQLite, se non si hanno troppe pretese(Multiutenza, triggers, etc), mi sembra la soluzione migliore. È più leggero e più facile da utilizzare.
cdimauro
11-10-2008, 06:13
Sono tutt'e due molto efficienti(utilizzano entrambi parser di tipo LALR(1) per il parsing SQL ;) ).
Di questo lo sai che me ne frego. :D
SQLite, se non si hanno troppe pretese(Multiutenza, triggers, etc), mi sembra la soluzione migliore. È più leggero e più facile da utilizzare.
Più facile da usare per la mia esperienza no. Sarà perché conosco bene FireBird, ma lavoro molto meglio e molto più velocemente con quest'ultimo (specialmente con trigger e stored procedure).
Più leggero SQLite lo è sicuramente: FireBird occupa 10 volte di più come spazio. Ma oggi chi se ne frega di passare da 400K a 4MB di memoria occupata? :p Io preferisco che FireBird usi 4MB, ma mi metta a disposizione quegli utilissimi strumenti che mi semplificano la vita. :cool:
Un oggetto Java "spreca" della memoria oltre ai dati dichiarati dal programmatore?
Grazie!
Ma riguardo ciò, cosa mi sapete dire?
cdimauro
11-10-2008, 18:03
Ma riguardo ciò, cosa mi sapete dire?
Dovremmo vedere la struttura interna (nell'implementazione di Java). A naso direi di sì (ci sarà qualche variabile privata interna).
Hai provato a stampae il sizeof della struttura e dei singoli elementi che la compongono (tanto per avere un'idea approssimativa)?
Perché in Java c'è sizeof? :stordita:
cdimauro
12-10-2008, 18:16
Vero: non c'è. :p
Visto che la dimensione dei tipi è fissata in Java, un calcolo lo si può fare, ma serve comunque conoscere l'implementazione base di Object (e la dimensione dei puntatori).
per quanto sia figo questo Python deve averti abituato molto male :Prrr:
in Java non ci sono puntatori, solo riferimenti. e prima che mi arrivi l'obiezione, secondo me il nome dell'eccezione NullPointerException è sbagliato, dovrebbe essere NullReferenceException, come in C#.
cdimauro
12-10-2008, 21:48
Alberto, forse sarà l'ora tarda ma ti vorrei ricordare che, riferimento o puntatori, qualunque oggetto in Java viene referenziato tramite l'uso di puntatori, che occupano 4 byte in sistemi a 32 bit, e 8 in sistemi a 64 bit.
Questo vuol dire che se dentro una classe referenzio l'istanza di un altro oggetto, oltre allo spazio occupato da quest'istanza ci sarà quello del suo riferimento o puntatore che dir si voglia. :O
Da qui:
http://www.jelovic.com/articles/why_java_is_slow.htm
In particolare il punto 3:
3. Increased Memory Use
Java programs use about double the memory of comparable C++ programs to store the data. There are three reasons for this:
1. Programs that utilize automatic garbage collection typically use about 50% more memory that programs that do manual memory management.
2. Many of the objects that would be allocated on stack in C++ will be allocated on the heap in Java.
3. Java objects will be larger, due to all objects having a virtual table plus support for synchronization primitives.
A larger memory footprint increases the probability that parts of the program will be swapped out to the disk. And swap file usage kills the speed like nothing else.
cdimauro
13-10-2008, 14:11
Non mi suona bene questa:
3. Java objects will be larger, due to all objects having a virtual table plus support for synchronization primitives.
La virtual table per ogni istanza di una classe dovrebbe essere la stessa per tutte le istanze di quella particolare classe. Come in C++ e nella maggior parte dei linguaggi che permettono di programmare a oggetti. Quindi non dovrebbe esserci nessuna differenza.
Non so nulla, invece, sulle primitive di sincronizzazione. Se n'era parlato qui qualche tempo fa, ma non ci sono informazioni precise in merito.
Anche io avevo fatto lo stesso ragionamento.
Da una piccola prova che ho fatto, per allocare un array di 2 milioni di oggetti contenenti 4 interi generati random la memoria occupata compresa la jvm è pari a circa 60 Mb.
Dai calcoli, in byte, dovrebbe essere:
4 (un int) * 4 (gli attributi di un oggetto) * 2000000 (tutti gli oggetti) = 32000000 = 32 Mb
Questo il codice che ho usato:
import java.lang.Thread;
import java.math.*;
public class prova{
public static void main(String args[]){
A[] array = new A[2000000];
int i=0;
while(i<2000000){
array[i] = new A((int)Math.random() * 100,
(int)Math.random() * 100,
(int)Math.random() * 100,
(int)Math.random() * 100);
i++;
}
try{
System.out.println("Sto aspettando...");
Thread.currentThread().sleep(10000);
}
catch(InterruptedException ie){
}
}
}
Per allocare 1 milione di oggetti invece vengono occupati 33 Mb.
Per allocarne 10, 3 Mb.
Ambiente di prova:
linux kernel v. 2.6.24.5 (Slackware)
e la versione di java:
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)
P.S. Ho dimenticato la classe A:
public class A{
private int a;
private int b;
private int c;
private int d;
public A(int a, int b, int c, int d){
this.a=a;
this.b=b;
this.c=c;
this.d=d;
}
}
cdimauro
13-10-2008, 20:25
Mi sembra che dovremmo esserci. 4 * 4 = 16 byte è la dimensione della struttura che hai definito, più 4 byte per il puntatore alla virtual table fanno 20 byte. 20 * 2.000.000 = 40 MB circa.
Mi sembra che dovremmo esserci. 4 * 4 = 16 byte è la dimensione della struttura che hai definito, più 4 byte per il puntatore alla virtual table fanno 20 byte. 20 * 2.000.000 = 40 MB circa. quale vtable? non c'è nessun metodo virtuale, il costruttore è implementato analogamente ad un metodo statico. :O
16 * 2.000.000 = 32 MB circa.
edit - però ora che ci penso ci sono i metodi di Object. Object ha 11 metodi dei quali nessuno final, quindi il conto diventa:
(16 + 4 * 11) * 2.000.000 = 60 * 2.000.000 = 120 MB
c'è qualcosa che non va :asd:
edit2 - dal momento però che, come hai detto tu stesso Cesare :read:, le vtables sono uniche per ogni classe, ri-escludiamo tutta la vtable e il conto torna a 32 MB.
cdimauro
13-10-2008, 21:04
Uomo di poca fede! :O :p
E no, i conti non tornano: ogni oggetto ha sempre un puntatore alla virtual table della sua classe. Quindi 16 + 4 = 20 che per 2.000.000 fa circa 40MB. :read: :cool:
Uomo di poca fede! :O :p
E no, i conti non tornano: ogni oggetto ha sempre un puntatore alla virtual table della sua classe. Quindi 16 + 4 = 20 che per 2.000.000 fa circa 40MB. :read: :cool:
[...] più 4 byte per il puntatore alla virtual table [...]
:ops2:
mi ritiro con disonore.
Ho fatto un'ulteriore prova: ho eliminato dalla classe A tutti gli attributi di tipo int. Quindi è diventata una classe senza attributi. Il resto l'ho lasciato invariato.
Spazio occupato 28 Mb (per 2 milioni di oggetti).
60 - 28 = 32
Quindi 28 Mb è lo spazio occupato dalla jvm e da tutto ciò che non sono attributi.
Ho fatto un'ulteriore prova: ho eliminato dalla classe A tutti gli attributi di tipo int. Quindi è diventata una classe senza attributi. Il resto l'ho lasciato invariato.
Spazio occupato 28 Mb (per 2 milioni di oggetti).
60 - 28 = 32
Quindi 28 Mb è lo spazio occupato dalla jvm e da tutto ciò che non sono attributi.
a questo punto sarebbe interessante vedere quanto occupa "tutto ciò che non sono attributi" sottraendo a 28 MB la memoria occupata da un programma Java che non istanzia nulla.
La jvm si prende 3-4 Mb (l'ho provato mettendo un while appena dentro al main del codice precedente allocando solo un intero; alle altre allocazioni, compreso l'array non ci arrivava).
Nel calcolo precedente, dei 2 milioni di oggetti vuoti, c'è però allocato un array di 2 milioni di riferimenti. Che dovrebbe fare 8 Mb.
28 - (8+4) = 16
Di cui 8 dovrebbero essere dei puntatori alla vtable.
Gli altri 8?
cdimauro
14-10-2008, 07:37
Azzardo l'ipotesi precedente:
3. Java objects will be larger, due to all objects having a virtual table plus support for synchronization primitives.
Può darsi che sia presente un puntatore a qualche struttura di sincronizzazione, magari inizialmente messo NULL (perché non usato).
4 * 2.000.000 = 8MB circa di spazio.
li abbiamo sgamati sti mutex, vedi come vengono a galla, eh! :D
e insomma, com'era quella storia che no, per carità, Java risparmiava risorse e li allocava solo quando assolutamente indispensabile... :asd:
il sucks rimane :rolleyes:
cdimauro
14-10-2008, 13:15
Però rimane na mia ipotesi, eh! Sarebbe interessante vedere la definizione della struttura di Object per venirne a capo.
banryu79
14-10-2008, 14:11
Però rimane na mia ipotesi, eh! Sarebbe interessante vedere la definizione della struttura di Object per venirne a capo.
/*
2 * Copyright 1994-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package java.lang;
27
28 /**
29 * Class <code>Object</code> is the root of the class hierarchy.
30 * Every class has <code>Object</code> as a superclass. All objects,
31 * including arrays, implement the methods of this class.
32 *
33 * @author unascribed
34 * @see java.lang.Class
35 * @since JDK1.0
36 */
37 public class Object {
38
39 private static native void registerNatives();
40 static {
41 registerNatives();
42 }
Bisogna vedere che cosa combina la chiamata registerNatives().
cdimauro
14-10-2008, 14:22
Può fare quello che vuole, ma da quel che vedo non risultano definite variabili d'istanza.
Quindi in teoria, a parte l'entry "nascosta" relativa al puntatore alla VMT, non dovrebbero esserci altri dati.
Sempre che, assieme al puntatore alla VMT, non vengano "nascosti" altri dati. :D
banryu79
14-10-2008, 14:28
Sì in effetti... cercando meglio ho trovato questo:
Object uses a class block initializer to register its native methods (such as clone(), getClass(), and hashCode()) with the JVM. The following Object code fragment takes care of that task:
private static native void registerNatives ();
static
{
registerNatives ();
}
Quindi non fa altro che registrare i metodi in Object con la JVM.
Qui c'è il link al sorgente di Object.java (http://www.docjar.com/html/api/java/lang/Object.java.html): solo metodi (nativi e non), nessun membro di classe.
Comunque anche il C++ ha i puntatori alla vtable per ogni oggetto creato, giusto?
Quegli 8 mega in più secondo voi sono per la sincronizzazione quindi?
Avete fatto delle prove anche voi o vi fidate dei miei dati? :D
Da un'altra prova fatta penso di aver dedotto che per un boolean alloca 1 byte. Il che renderebbe sconveniente allocare diversi booleani in un ottica di forte ottimizzazione dello spazio occupato. Il C++ sapete come si comporta in questo caso?
cdimauro
14-10-2008, 21:54
Sì in effetti... cercando meglio ho trovato questo:
Quindi non fa altro che registrare i metodi in Object con la JVM.
Qui c'è il link al sorgente di Object.java (http://www.docjar.com/html/api/java/lang/Object.java.html): solo metodi (nativi e non), nessun membro di classe.
Appunto. Quindi niente spazio in più per altro, ma... manca all'appello il puntatore alla VMT: non si vede da nessuna parte.
Comunque anche il C++ ha i puntatori alla vtable per ogni oggetto creato, giusto?
Solo per le classi che hanno definito almeno un metodo non statico.
Quegli 8 mega in più secondo voi sono per la sincronizzazione quindi?
E' soltanto una mia ipotesi, ma finché non trovo dati a conferma rimarrà tale. :p
Avete fatto delle prove anche voi o vi fidate dei miei dati? :D
No, mi fido. Per quale motivo dovresti mentire / barare? :confused:
Da un'altra prova fatta penso di aver dedotto che per un boolean alloca 1 byte.
Hum... Sicuro? Non so se tutti i modelli è così, ma mi sembra che sui telefonini con J2ME un boolean occupi 4 byte (32 bit), dalle prove che hanno fatto i miei colleghi della divisione mobile.
Il che renderebbe sconveniente allocare diversi booleani in un ottica di forte ottimizzazione dello spazio occupato.
Basta "impaccare" i bit in questi casi. ;)
Il C++ sapete come si comporta in questo caso?
Dovrebbe essere come Java.
No, mi fido. Per quale motivo dovresti mentire / barare? :confused:
No, certo :p , ma potrei sbagliare, nello scrivere codice, analizzare i dati, ecc.
Hum... Sicuro? Non so se tutti i modelli è così, ma mi sembra che sui telefonini con J2ME un boolean occupi 4 byte (32 bit), dalle prove che hanno fatto i miei colleghi della divisione mobile.
No. :D Domani rifarò la prova. Se avessimo ragione entrambi, potrebbe essere che in J2ME dei cellulari si sia scelta la strada della semplicità piuttosto che quella dell'ottimizzazione: tutto a 32 bit.
Il C++ sapete come si comporta in questo caso? lo standard non specifica una dimensione, ma molti compilatori implementano bool da un solo byte.
cdimauro
15-10-2008, 19:50
No, certo :p , ma potrei sbagliare, nello scrivere codice, analizzare i dati, ecc.
In tal caso sarebbe anche colpa mia per non aver verificato. :)
No. :D Domani rifarò la prova. Se avessimo ragione entrambi, potrebbe essere che in J2ME dei cellulari si sia scelta la strada della semplicità piuttosto che quella dell'ottimizzazione: tutto a 32 bit.
E' possibile, ma i byte occupano un solo byte. Infatti i miei colleghi per la J2ME non usano i boolean, ma i byte per risparmiare spazio e andare anche più veloci.
Mazzulatore
15-10-2008, 22:01
Leggendo un altro thread un grosso limite di Java è la casualità con cui interviene il garbage collector. Non si può usarlo quindi per programmi con stringenti vincoli di tempo. Ci sono altri problemi simili?
Non è un problema esclusivamente di java in quanto il GC è più presente in C e C++ di quanto si possa immaginare (nei programmi di tutti i giorni che non siano notepad) e di sicuro se vuoi mantenere efficienza nella memoria sarai costretto ad usarlo se il tuo programma è in qualche modo complesso. In java puoi scegliere la strategia del GC, ci sono sia le "StopTheWorld" che quelle più orientate al real time. In generale java non pone nessun vincolo di memoria o temporale o chicchessia che non sia strettissimissimo. Se l'elaborazione è molto lunga è probabile che le prestazioni siano anche meglio di c++, per via del profiling effettuato a runtime.
Se ti interessa sfruttare i multicore in java 7 ci saranno le primitive simil fork-join per la multiprogrammazione.
Hai già pensato se deve girare su più piattaforme? :)
Inoltre se non devi vendere il tuo programma puoi compilare in codice nativo con il compilatore Jet AOT e praticamente è come se avessi programmato in c++.
EDIT: non è facile ottenere una licenza gratuita, come dice qua (http://www.excelsior-usa.com/jetfree.html)
Hum... Sicuro? Non so se tutti i modelli è così, ma mi sembra che sui telefonini con J2ME un boolean occupi 4 byte (32 bit), dalle prove che hanno fatto i miei colleghi della divisione mobile.
Prova fatta:
se nella classe alloco un solo booleano lo spazio occupato per i soliti 2 milioni di oggetti è pari a 43 Mb.
Se tolgo l'unico attributo, sono occupati 27 Mb.
Quindi 43 - 27 = 16 Mb
Stessa prova fatta con un solo attributo di tipo intero (di valore 10 per tutti gli oggetti) restituisce gli stessi risultati in termini di occupazione di memoria, quindi un booleano occupa quanto un intero.
L'errore era scaturito dal fatto che dividendo 16 milioni per 2 milioni esce 8 e pensavo fossero bit. Invece sono byte.
Forse non sarò lucidissimo, ma perché sia un int che un boolean occupano 8 byte (ho un processore a 32 bit)? E' come se fosse allocato un tipo (puntatore?) fantasma in più. Ma allora perché usando 4 attributi di tipo int i conti tornano?
Il codice che ho usato:
public class A{
//private int a;
//private int b;
//private int c;
//private int d;
boolean b;
public A(/*int a, int b, int c, int d*/){
b = true;
//this.a=10;
//this.a=a;
//this.b=b;
//this.c=c;
//this.d=d;
}
}
import java.lang.Thread;
import java.math.*;
public class prova{
public static void main(String args[]){
A[] array = new A[2000000];
int i=0;
while(i<2000000){
array[i] = new A(/*(int)Math.random() * 1000,
(int)Math.random() * 1000,
(int)Math.random() * 1000,
(int)Math.random() * 1000*/);
i++;
}
try{
System.out.println("Sto aspettando...");
Thread.currentThread().sleep(10000);
}
catch(InterruptedException ie){
}
}
}
Non è un problema esclusivamente di java in quanto il GC è più presente in C e C++ di quanto si possa immaginare (nei programmi di tutti i giorni che non siano notepad) e di sicuro se vuoi mantenere efficienza nella memoria sarai costretto ad usarlo se il tuo programma è in qualche modo complesso. In java puoi scegliere la strategia del GC, ci sono sia le "StopTheWorld" che quelle più orientate al real time. In generale java non pone nessun vincolo di memoria o temporale o chicchessia che non sia strettissimissimo. Se l'elaborazione è molto lunga è probabile che le prestazioni siano anche meglio di c++, per via del profiling effettuato a runtime.
Se ti interessa sfruttare i multicore in java 7 ci saranno le primitive simil fork-join per la multiprogrammazione.
Hai già pensato se deve girare su più piattaforme? :)
Inoltre se non devi vendere il tuo programma puoi compilare in codice nativo con il compilatore Jet AOT e praticamente è come se avessi programmato in c++.
EDIT: non è facile ottenere una licenza gratuita, come dice qua (http://www.excelsior-usa.com/jetfree.html)
Il thread (EDIT: in realtà volevo dire post) che avevo letto era di un utente che scrive codice per videogiochi ed ha il vincolo che una scena deve essere renderizzata in un tot di tempo (forse era 10 ms). Se ci fosse un gc (ma si riferiva proprio a Java) che venisse lanciato "ogni tanto" non si rispetterebbe più il vincolo temporale. Perché non possa usare gc più orientati al real time, sinceramente, non ne ho idea. :D Magari se ritrovo il thread, posso invitare l'utente qui e ce lo facciamo spiegare.
Sì, mi interesserebbe sfruttare i multicore, ma che vantaggi si avrebbero rispetto all'uso dei normali thread, che dovrebbero già sfruttare più core?
EDIT:
Ovviamente l'utente è fek e il post è questo: http://www.hwupgrade.it/forum//showpost.php?p=20453765&postcount=330 ed anche se nel thread si parla ampiamente di Java, effettivamente parla di garbage collector in generale.
cdimauro
17-10-2008, 07:43
Prova fatta:
se nella classe alloco un solo booleano lo spazio occupato per i soliti 2 milioni di oggetti è pari a 43 Mb.
Se tolgo l'unico attributo, sono occupati 27 Mb.
Quindi 43 - 27 = 16 Mb
Stessa prova fatta con un solo attributo di tipo intero (di valore 10 per tutti gli oggetti) restituisce gli stessi risultati in termini di occupazione di memoria, quindi un booleano occupa quanto un intero.
L'errore era scaturito dal fatto che dividendo 16 milioni per 2 milioni esce 8 e pensavo fossero bit. Invece sono byte.
Forse non sarò lucidissimo, ma perché sia un int che un boolean occupano 8 byte (ho un processore a 32 bit)?
Interi e booleani occupano 32 bit, quindi 4 byte, non 8.
E' come se fosse allocato un tipo (puntatore?) fantasma in più.
Ma allora perché usando 4 attributi di tipo int i conti tornano?
Può darsi che la dimensione minima per l'allocazione della memoria sia di 8 byte. Quindi le strutture dati occupano sempre multipli di 8 byte. In gergo di chiama granularità, ed è una pratica molto diffusa.
Non pensare che sia cosa recente: se non ricordo male persino il Turbo Pascal 4.0 gestiva l'heap delle allocazioni con granularità di 8 byte, quando la memoria libera al massimo poteva essere (meno) di 640KB. :p
Il thread (EDIT: in realtà volevo dire post) che avevo letto era di un utente che scrive codice per videogiochi ed ha il vincolo che una scena deve essere renderizzata in un tot di tempo (forse era 10 ms). Se ci fosse un gc (ma si riferiva proprio a Java) che venisse lanciato "ogni tanto" non si rispetterebbe più il vincolo temporale. Perché non possa usare gc più orientati al real time, sinceramente, non ne ho idea. :D Magari se ritrovo il thread, posso invitare l'utente qui e ce lo facciamo spiegare.
Java non è particolarmente indicato per sviluppare videogiochi, infatti. Non offre un controllo preciso sull'intervento del GC.
Sì, mi interesserebbe sfruttare i multicore, ma che vantaggi si avrebbero rispetto all'uso dei normali thread, che dovrebbero già sfruttare più core?
Perché i thread non li sfruttano, visto che girano dentro UN ben preciso processo, che poi il s.o. dà in pasto a un core o a un altro a seconda delle sue politiche di scheduling.
Sfruttando il multiprocessing, invece, si possono tirar sù n processi a dividere loro il lavoro, in modo da cercare di sfruttare tutti i core a disposizione. Spesso è comodo associate a ogni processo un ben preciso core, in modo da (teoricamente; molto teoricamente) sfruttarli tutti.
Scusa la semplificazione, ma è per rendere l'idea.
EDIT:
Ovviamente l'utente è fek e il post è questo: http://www.hwupgrade.it/forum//showpost.php?p=20453765&postcount=330 ed anche se nel thread si parla ampiamente di Java, effettivamente parla di garbage collector in generale.
Sì, lo ricordo bene. :)
mad_hhatter
17-10-2008, 08:57
Perché i thread non li sfruttano, visto che girano dentro UN ben preciso processo
non dipende da come il s.o. gestisce i thread? _mi pare_, ad esempio, che windows esegua ogni thread in un processo separato.
cdimauro
17-10-2008, 13:28
Francamente è la prima volta che lo sento, ma mi posso sbagliare pure io. :)
mad_hhatter
17-10-2008, 15:24
Francamente è la prima volta che lo sento, ma mi posso sbagliare pure io. :)
qui:
http://msdn.microsoft.com/en-us/library/ms681917(VS.85).aspx
si legge che:
Microsoft Windows supports preemptive multitasking, which creates the effect of simultaneous execution of multiple threads from multiple processes. On a multiprocessor computer, the system can simultaneously execute as many threads as there are processors on the computer.
interessanti, poi, i seguenti:
http://www2.sys-con.com/itsg/virtualcd/Java/archives/0306/gal/index.html
e
http://java.sun.com/docs/hotspot/threads/threads.html
purtroppo ora non ho tempo di leggere tutto approfonditamente ne' di cercare meglio nella documentazione ufficiale SUN, mi spiace.
^TiGeRShArK^
17-10-2008, 16:28
no, in windows i thread girano all'interno dei processi.
Infatti ad esempio in firefox le varie tab sfruttano il multi-threading, ma se guardi nel task manager vedi un solo processo.
Invece google chrome ad esempio ha adottato una strategia diversa aprendo un nuovo processo per ogni tab, ma lo fa per motivi di sicurezza in modo che se crasha una tab non crasha tutto il browser ma solo quella pagina.
D'altronde in quello che hai riportato dalla microsoft c'è scritto che + thread da diversi processi possono girare contemporaneamente, il che implica anche che + thread di un unico processo possano girare nello stesso momento... :mbe:
EDIT: altrimenti ogni volta che apri un thread nei tuoi programmi dovresti vedere nel task manager il processo che viene duplicato, ma così non è :p
mad_hhatter
17-10-2008, 17:04
no, in windows i thread girano all'interno dei processi.
Infatti ad esempio in firefox le varie tab sfruttano il multi-threading, ma se guardi nel task manager vedi un solo processo.
Invece google chrome ad esempio ha adottato una strategia diversa aprendo un nuovo processo per ogni tab, ma lo fa per motivi di sicurezza in modo che se crasha una tab non crasha tutto il browser ma solo quella pagina.
D'altronde in quello che hai riportato dalla microsoft c'è scritto che + thread da diversi processi possono girare contemporaneamente, il che implica anche che + thread di un unico processo possano girare nello stesso momento... :mbe:
EDIT: altrimenti ogni volta che apri un thread nei tuoi programmi dovresti vedere nel task manager il processo che viene duplicato, ma così non è :p
in effetti il pezzo che ho riportato non risolve la questione.
però ho trovato questo (http://msdn.microsoft.com/en-us/library/ms684251(VS.85).aspx):
"The system uses a symmetric multiprocessing (SMP) model to schedule threads on multiple processors. With this model, any thread can be assigned to any processor"
da cui deriva la possibilità che 2 thread appartenenti allo stesso processo possono essere eseguiti contemporaneamente su 2 processori diversi.
ho letto in fretta, spero di non aver travisato il discorso...
non so se in windows un processo possa non essere visualizzato nel task manager...
comunque appena ho più tempo cerco meglio.
non dipende da come il s.o. gestisce i thread? _mi pare_, ad esempio, che windows esegua ogni thread in un processo separato.
Francamente è la prima volta che lo sento, ma mi posso sbagliare pure io. :)
... :mbe: stiamo messi male
Perché i thread non li sfruttano, visto che girano dentro UN ben preciso processo, che poi il s.o. dà in pasto a un core o a un altro a seconda delle sue politiche di scheduling. :muro: stiamo messi peggio :cry:
http://msdn.microsoft.com/en-us/library/ms686253(VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms686247(VS.85).aspx
cdimauro
17-10-2008, 21:23
qui:
http://msdn.microsoft.com/en-us/library/ms681917(VS.85).aspx
si legge che:
Il che mi sembra che non dimostri che sia possibile eseguire PIU' thread di UN processor su PIU' core. :)
interessanti, poi, i seguenti:
http://www2.sys-con.com/itsg/virtualcd/Java/archives/0306/gal/index.html
e
http://java.sun.com/docs/hotspot/threads/threads.html
purtroppo ora non ho tempo di leggere tutto approfonditamente ne' di cercare meglio nella documentazione ufficiale SUN, mi spiace.
Questo riguarda Java che però si appoggia al s.o.. ;)
no, in windows i thread girano all'interno dei processi.
Infatti ad esempio in firefox le varie tab sfruttano il multi-threading, ma se guardi nel task manager vedi un solo processo.
Invece google chrome ad esempio ha adottato una strategia diversa aprendo un nuovo processo per ogni tab, ma lo fa per motivi di sicurezza in modo che se crasha una tab non crasha tutto il browser ma solo quella pagina.
D'altronde in quello che hai riportato dalla microsoft c'è scritto che + thread da diversi processi possono girare contemporaneamente, il che implica anche che + thread di un unico processo possano girare nello stesso momento... :mbe:
EDIT: altrimenti ogni volta che apri un thread nei tuoi programmi dovresti vedere nel task manager il processo che viene duplicato, ma così non è :p
Esattamente.
in effetti il pezzo che ho riportato non risolve la questione.
però ho trovato questo (http://msdn.microsoft.com/en-us/library/ms684251(VS.85).aspx):
"The system uses a symmetric multiprocessing (SMP) model to schedule threads on multiple processors. With this model, any thread can be assigned to any processor"
da cui deriva la possibilità che 2 thread appartenenti allo stesso processo possono essere eseguiti contemporaneamente su 2 processori diversi.
ho letto in fretta, spero di non aver travisato il discorso...
Non mi sembra che da quell'affermazione (ma nemmeno leggendo tutta la pagina) si possa dedurre quanto hai scritto. ;)
non so se in windows un processo possa non essere visualizzato nel task manager...
comunque appena ho più tempo cerco meglio.
OK
... :mbe: stiamo messi male
Perché?
:muro: stiamo messi peggio :cry:
http://msdn.microsoft.com/en-us/library/ms686253(VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms686247(VS.85).aspx
Idem come sopra.
Per intenderci, la questione è quella che ha riportato mad_hutter sopra.
E' possibile far eseguire due thread dello STESSO processo nello STESSO MOMENTO su due core DIVERSI?
^TiGeRShArK^
17-10-2008, 23:21
E' possibile far eseguire due thread dello STESSO processo nello STESSO MOMENTO su due core DIVERSI?
In windows si.
Su linux non lo so con certezza ma immagino che funzioni allo stesso modo...
cdimauro
18-10-2008, 06:15
Allora non ha senso sbattersi per la strada del multiprocessing: è sufficiente sviluppare un programma multithreaded con la sicurezza di poter sfruttare tutti i core della CPU (ci pensa lo scheduler a smistare opportunamente i thread ai core).
Io non ho un sistema multicore sottomano, ma mi piacerebbe fare un programmino di prova e vedere se il task manager è al 100% su tutti i core con un'applicazione costituita da un solo processo e n thread. Se così fosse, mi risolverebbe non pochi problemi.
^TiGeRShArK^
18-10-2008, 10:08
Allora non ha senso sbattersi per la strada del multiprocessing: è sufficiente sviluppare un programma multithreaded con la sicurezza di poter sfruttare tutti i core della CPU (ci pensa lo scheduler a smistare opportunamente i thread ai core).
Io non ho un sistema multicore sottomano, ma mi piacerebbe fare un programmino di prova e vedere se il task manager è al 100% su tutti i core con un'applicazione costituita da un solo processo e n thread. Se così fosse, mi risolverebbe non pochi problemi.
basta vedere come su un n-core utiizzando un processo single-threaded puoi sfruttare il processore al 100 / n%, ma dividendolo in n thread lo puoi sfruttare al 100% pur mantenendo un singolo processo. :p
Ovviamente con python non funziona così dato che i thread che utilizza non sono thread di windows....
E' possibile far eseguire due thread dello STESSO processo nello STESSO MOMENTO su due core DIVERSI? si :fagiano:
Allora non ha senso sbattersi per la strada del multiprocessing: si che ha senso: non è sempre desiderabile che i diversi thread abbiano tutti lo stesso spazio di indirizzamento perché se crasha uno crashano tutti. vedi Internet Explorer 8, dove le tab girano in processi diversi ed il browser è in grado di ripristinarle senza crashare del tutto.
Io non ho un sistema multicore sottomano, ma mi piacerebbe fare un programmino di prova e vedere se il task manager è al 100% su tutti i core con un'applicazione costituita da un solo processo e n thread. Se così fosse, mi risolverebbe non pochi problemi. ora ci provo io, ho due core. usando le API che ho linkato prima dovrebbe essere semplice.
ora ci provo io, ho due core. usando le API che ho linkato prima dovrebbe essere semplice. fatto:
#include <windows.h>
static DWORD WINAPI ThreadProc(LPVOID lpParameter);
static void CpuSucker();
int main()
{
SetThreadIdealProcessor(GetCurrentThread(), 0);
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
if (hThread == NULL)
{
return 1;
}
SetThreadIdealProcessor(hThread, 1);
CloseHandle(hThread);
CpuSucker();
return 0;
}
void CpuSucker()
{
while (true);
}
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
CpuSucker();
return 0;
}
tutto regolare, entrambi i core a palla.
cdimauro
19-10-2008, 14:37
basta vedere come su un n-core utiizzando un processo single-threaded puoi sfruttare il processore al 100 / n%, ma dividendolo in n thread lo puoi sfruttare al 100% pur mantenendo un singolo processo. :p
Sì, lo so: è quello che m'interessava appurare... appunto. :D
Ovviamente con python non funziona così dato che i thread che utilizza non sono thread di windows....
No, sono proprio thread di Windows. Da thread_nt.h (file include dei sorgenti di Python 2.6):
long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
Py_uintptr_t rv;
callobj obj;
dprintf(("%ld: PyThread_start_new_thread called\n",
PyThread_get_thread_ident()));
if (!initialized)
PyThread_init_thread();
obj.id = -1; /* guilty until proved innocent */
obj.func = func;
obj.arg = arg;
obj.done = CreateSemaphore(NULL, 0, 1, NULL);
if (obj.done == NULL)
return -1;
rv = _beginthread(bootstrap,
Py_SAFE_DOWNCAST(_pythread_stacksize,
Py_ssize_t, int),
&obj);
if (rv == (Py_uintptr_t)-1) {
/* I've seen errno == EAGAIN here, which means "there are
* too many threads".
*/
dprintf(("%ld: PyThread_start_new_thread failed: %p errno %d\n",
PyThread_get_thread_ident(), (void*)rv, errno));
obj.id = -1;
}
else {
dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n",
PyThread_get_thread_ident(), (void*)rv));
/* wait for thread to initialize, so we can get its id */
WaitForSingleObject(obj.done, INFINITE);
assert(obj.id != -1);
}
CloseHandle((HANDLE)obj.done);
return obj.id;
}
_beginthread lo trovi qui (http://msdn.microsoft.com/en-us/library/kdzttdcb(VS.80).aspx) e usa l'API standard di Windows CreateThread. :)
si :fagiano:
OK
si che ha senso: non è sempre desiderabile che i diversi thread abbiano tutti lo stesso spazio di indirizzamento perché se crasha uno crashano tutti. vedi Internet Explorer 8, dove le tab girano in processi diversi ed il browser è in grado di ripristinarle senza crashare del tutto.
Sì, è chiaro ed è corretto, ma non era a questo che mi riferivo. Mi riferivo al fatto che per sfruttare tutti i core di una CPU non serve del codice di tipo multiprocessing, ma è sufficiente realizzarlo multithreaded.
ora ci provo io, ho due core. usando le API che ho linkato prima dovrebbe essere semplice.
OK
fatto:
#include <windows.h>
static DWORD WINAPI ThreadProc(LPVOID lpParameter);
static void CpuSucker();
int main()
{
SetThreadIdealProcessor(GetCurrentThread(), 0);
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
if (hThread == NULL)
{
return 1;
}
SetThreadIdealProcessor(hThread, 1);
CloseHandle(hThread);
CpuSucker();
return 0;
}
void CpuSucker()
{
while (true);
}
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
CpuSucker();
return 0;
}
tutto regolare, entrambi i core a palla.
Benissimo. Quindi anche Python sono a posto. In ufficio faccio una prova sul PC del mio collega e vediamo se il GIL rompe le scatole o permette di sfruttare pienamente tutti i core. :D
^TiGeRShArK^
19-10-2008, 15:22
No, sono proprio thread di Windows. Da thread_nt.h (file include dei sorgenti di Python 2.6):
ah già il problema era il GIL non il tipo dei thread :p
Benissimo. Quindi anche Python sono a posto. In ufficio faccio una prova sul PC del mio collega e vediamo se il GIL rompe le scatole o permette di sfruttare pienamente tutti i core. :D
fino alla versione 2.5 girava tutto su un unico core per processo, con la 2.6 non ho mai provato, ma non mi pare di aver letto cambiamenti in questo senso nelle release notes.. :boh:
cdimauro
19-10-2008, 15:41
Allora non ci sono speranze. :cry:
^TiGeRShArK^
19-10-2008, 16:03
Allora non ci sono speranze. :cry:
puoi sempre usare il nuovo package multiprocessing....
sempre meglio di niente....
cdimauro
19-10-2008, 17:10
Sì, lo so. Al momento non posso perché nelle macchine di produzione c'è Python 2.5, e fino a quando non saranno rilasciati per il 2.6 tutti i pacchetti che uso non posso adeguare i miei sorgenti e chiederne l'installazione.
Comunque è in programma. Non mi resta altra scelta se voglio sfruttare tutti i core con Python.
Allora non ci sono speranze. :cry: alla fine io Python non me lo sono più studiato, ma già mi pare d'aver capito che ti permetta di chiamare le API Win32; se poi ti permette anche di gestire puntatori a funzioni con un particolare prototipo e calling convention (non ricordo a cosa si espande WINAPI) allora forse puoi scrivere una tua mini-libreria che ci va di nativo ed implementa il multithreading per processori multicore. non so se sia possibile, comunque l'API per impostare il core preferenziale te l'ho detta :)
cdimauro
19-10-2008, 18:39
Sì, la conoscevo già. Le API di Windows, incluse quelle con le callback, si possono chiamare tranquillamente grazie al modulo standard ctypes, ma rimane il problema della GIT che blocca / limita la virtual machine.
L'unica è ricorrere al modulo multiprocessing appena introdotto con Python 2.6. Quello dello sfruttamento di tutti i core è un problema sentito, e visto che qualcuno l'ha risolto preferisco non reinventarmi la ruota. :p
Grazie comunque. :)
Sì, la conoscevo già. Le API di Windows, incluse quelle con le callback, si possono chiamare tranquillamente grazie al modulo standard ctypes, ma rimane il problema della GIT che blocca / limita la virtual machine. ma per curiosità, che succede se chiamando da Python tutte le API necessarie tenti di creare due thread e schedularli su core diversi?
cdimauro
19-10-2008, 20:02
Funzionerebbero lo stesso, ma si metterebbero "in fila" a causa del lock global della virtual machine (il GIL, appunto) che regola l'accesso allo stato e alle risorse della VM.
Funzionerebbero lo stesso, ma si metterebbero "in fila" a causa del lock global della virtual machine (il GIL, appunto) che regola l'accesso allo stato e alle risorse della VM. ma come fa la virtual machine ad avere il controllo su thread creati da te tramite chiamate native?
cdimauro
19-10-2008, 20:40
Perché non appena questi tenteranno di accedere alle risorse della VM, dovranno necessariamente aver acquisito il GIL, e questo ne "serializzerà" l'esecuzione.
Cosa tutt'altro che rara, visto l'uso "pervasivo" che in Python si fa dei dizionari, che sono oggetti modificabili e usati per memorizzare le variabili, tanto per fare l'esempio più noto.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.