Newsgroup: it.comp.lang.c++
Titolo: Garbage Collection

Ciao,
Riprendo un tema che e' comparso in mezzo ad un altro thread per
aggiungere qualche elemento alla discussione.
Ci sono ottime probabilita' che la prossima versione dello standard
includa una forma di garbage collection. Questo non vuol dire che di
punto in bianco tutti gli oggetti dovranno per forza di cose essere
allocati dinamicamente. Semplicemente quando si allochera'
dinamicamente si avra' l'opzione di far controllare la gestione della
memoria dal garbage collector.
Personalmente la giudico una cosa positiva. Nei miei programmi noto
un'ampia classe di oggetti per la quale il momento effettivo della
distruzione mi interessa poco e in genere questi oggetti hanno
distruttori triviali o contenenti solo deallocazioni. Il passare
dall'uso di smart pointer a quello della garbage collection puo'
semplificare, per quanto di poco, la vita.
Un ulteriore argomento a favore, particolarmente caro ad Andrei
Alexandrescu, e' l'osservazione che la garbage collection impedisce
l'involontaria interpretazione di un'area di memoria come avente un
tipo diverso da quello che effettivamente ha. Un esempio:
double * p = new double;
delete p;
int * q = new int;
assumendo per semplicita' che il mio gestore della memoria riutilizzi
immediatamente la memoria deallocata l'esempio qui sopra consente di
interpretare l'int puntato da q come se fosse un double, tramite p.
Per quanto ovviamente questo si applichi solo alla memoria gestita dal
garbage collector, la GC collabora a ridurre il rischio di una classe
di errori perniciosa e prona ad aprire problemi di sicurezza.
Quello che e' certo pero' e' che la garbage collection non consente,
come alcuni pensano, di programmare ignorando bellamente i problemi
relativi alla gestione della memoria. Semplifica le cose, ma alcuni
problemi sono solo spostati.
Dal punto di vista delle prestazioni il discorso e' complesso, e
dipende moltissimo dalle caratteristische del garbage collector e da
quelle dell'applicazione. Idealmente lo spazio per un miglioramento
sul piano statistico c'e', perche' la GC accorpa le operazioni di
gestione della memoria, che sono in genere dispendiose. Per contro
puo' avere un effetto nefasto soprattutto sulle applicazioni
interattive.
Per ulteriori dettagli rimando al solito documento di Alisdair
Meredith dove trovate elencati i documenti che compongono la proposta
presentata al comitato di standardizzazione:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2336.html
Ciao,
Nicola

 Meredith[...]
Grazie del link ;-)

 interattive.
Gia', *molto* complesso. Qui per ora soprassiedo :-)
  bye
	av.

 Il vantaggio principale è che obbliga il programmatore [..]
Secondo me i due vantaggi principali sono il posticipare operazioni 
potenzialmente costose come la deallocazione di un instanza, e mettere 
ad una pezza a varie problematiche di memory leak.
Per il resto sono quasi un pythonista. Il programmatore può fare tutti 
i danni che vuole. Inutile educarlo attraverso il linguaggio.
Discorso che salta fuori appena si parla se è "giusto" avere scope di 
visibilita "private" o addirittura "protected" nella dichiarazione 
delle classi. Dico quasi perché mi piace mettere i dati di un classe 
sempre non accessibili.
Il discorso dell'educazione salta fuori anche con il cast, che ti 
permette di fare praticamente tutto.
-- 
partecipa anche tu:  
http://www.beppegrillo.it/vaffanculoday/
il capitalismo: 
http://www.rat-man.com/site/IT/IT/rat_cartoon.ashx?mn=5

 potenzialmente costose come la deallocazione di un instanza
Piu' che il posticipo, secondo me, il vantaggio vero e' che avviene in 
un thread separato, magari a priorita' piu' bassa.
  bye
	av.

 (Forse intendiamo la stessa cosa :-)
Infatti la mia premessa e' che in un'applicazione di norma esistono
numerosi oggetti per i quali il distruttore si limita a deallocare
membri puntatori.
Dove la distruzione deterministica serve si alloca sullo stack. Senza
contare che nulla vieterebbe di mantenere comunque il delete con
l'effetto di chiamare il distruttore, ma di non deallocare la memoria.
Ciao,
Nicola

 la localita' degli effetti dell'errore.
Non sapevo.
E' una caratteristica del (probabile) futuro C++ o in generale di tutti 
i GC?
  bye & Thanks
	av.

 includa una forma di garbage collection.
 > ...
Ho dato un'occhiata a 
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2310.pdf
 e la 
prima impressione (ma non ho lo "spessore" per poter giudicare il lavoro 
di questa gente e neppure l'ho letto tutto) è che non possa uscirne 
nulla di buono.
Mi pare di aver capito che vogliono fare un GC di tipo trasparente: in 
pratica occorre tener traccia di tutte le zone di memoria non più 
raggiungibili dal programma attraverso puntatori, ma anche puntatori 
"sporchi" per colpa della type-unsafety del C++, senza introdurre il 
concetto di un puntatore speciale type-safe e con regole più stringenti 
per gli oggetti allocati dal GC.
Questo comporterebbe alcuni vantaggi (ad esempio la possibilità di 
aggiungere la GC a un prog bacato e aggiustarlo magicamente) ma IMHO 
comporta un numero abnorme di svantaggi rispetto ad una GC con puntatore 
speciale (alla c++/cli).
Non vorrei che ne uscisse una cosa mostruosa malfunzionante o molto 
complicata da implementare che farebbe la fine di export...
Credo sarebbe molto meglio prendere spunto da c++/cli che (anche se a 
qualcuno MS sta antipatica) funziona ormai da tempo e anche piuttosto 
bene e soprattutto mette ben in evidenza la roba sotto GC e la roba no.
GM

 
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2336.html
Attualmente purtroppo non ho tempo di leggerlo, ma provero' a farlo quando
ho un po' piu' di tempo
 
Ciao,
Marco

 thread separato, magari a priorita' piu' bassa.
Il fatto che venga effettuato da un thread a bassa priorità può essere 
un bene o un male. Dipende. Se il thread principale va al 100% di CPU, 
teoricamente il thread della GC potrebbe non essere mai schedulato.


 
questo discorso di un thread al 100% l'ho già sentito anche sull'altro 
ng (win32) e probabilmente eri proprio tu a farlo.
Ma secondo me un thread al 100% è un errore a prescindere. In un sistema 
ben realizzato e ben dimensionato è un'eventualità che non dovrebbe mai 
verificarsi in modo persistente. Ok se ho il 100% per qualche frazione 
di secondo o al limite qualche secondo, altrimenti c'è qualcosa che tocca.


In generale dei garbage collector. Una porzione di memoria non viene
riutilizzata finche' ci sono puntatori attivi che la indirizzano.
Ciao,
Nicola

 bene e soprattutto mette ben in evidenza la roba sotto GC e la roba no.
Ma questo e' necessario perche' MS ha voluto spiaccicare sul C++ un
type system, quello di .NET, che col C++ centra poco e ne e' venuto
fuori l'accrocchio, pardon l'ibrido, che e' C++/CLI. Per fortuna Hans
Boehm si e' ben guardato da prendere questa strada.
Ciao,
Nicola

 Ma secondo me un thread al 100% è un errore a prescindere
Questa è una fesseria, se permetti. Se io faccio un motore di ricerca, 
e quindi devo scaricare e indicizzare praticamente il mondo, ogni 
momento in cui tutte le CPU NON sono al 100% è un errore.
Io faccio cose in cui le CPU DEVONO essere al 100% sempre, con tutto 
ciò che ne consegue. Chiaramente faccio in gioco delle tre carte: la 
CPU è sempre al 100%, ma non tutti i thread sono perennemente al 100%, 
ma qui si entra nei dettagli implementativi. Certo è che per me il 
fatto che un thread possa non essere mai richiamato è qualcosa che ho 
sempre in mente. Cos' come guardo sempre al costo dei vari 
oggetti/procedure per sincronizzare la comunicazione tra thread/task.
Di solito, con personale disgusto, sacrifico i log, se ho bisogno di 
tempo CPU. Però l'idea che la GC possa non essere (teoricamente) 
richiamata mi fa ribrezzo. Non credo sia il caso di dotnet della 
microsoft, tra l'altro, ma non la conosco molto bene.


 di secondo o al limite qualche secondo, altrimenti c'è qualcosa che tocca.
Vedi sopra.
Ciao,
Marco.

 
Appunto. E questo crea dei discreti casini ad esempio nei sistemi J2EE che 
trattano milioni di dati facendo girare vari "EJB" all'interno di un 
Application Server.
Ciao,
Marco

 ha scritto:

Non ne dubito. D'altronde chi non sa programmare non e' che diventa
programmatore provetto solo perche' c'e' la GC (o l'application
server).
Ciao,
Nicola

 
Anche perchè vedi che qui neghi subito. Io non ho parlato di CPU al 100% 
ma di UN thrad al 100%. E' diverso.

 che puo' disturbare le elaborazioni di tale thread. 
In un sistema di questo tipo è inutile parlare di thread: praticamente 
non hai un sistema operativo. E' ovvio che in questo caso il "main loop" 
sia sotto il mio controllo e si succhi tutta la CPU.
Io parlavo di SO con scheduler non RT e resto dell'idea che UN thrad al 
100% sia una cagata. (non la CPU al 100% ma UN singolo therad)

 server).
...ma far girare diversi EJB con un Application Server non significa
non saper programmare.
Eppure i problemi ci sono lo stesso...

 di UN thrad al 100%. E' diverso.
Filosofia. Devo processare un oggetto. Lo fa il thread 1. I dati gli 
vengono dati in pasto dal thread 2 e finiscono al thread 3. Non c'è 
niente di male se il thread 1 occupi il 99,99 % del tempo.
Ora, se ti leghi alla definizione di 100% ovviamente hai ragione tu. Se 
siamo elastici, ci può tranquillamente essere un programma in cui un 
thread sia sempre *praticamente* al 100% del consumo CPU. Poi su un 
sistema multiprocessore in concetto di CPU diventa più sfumato, ma a 
quel punto i thread potrebbero essere pari al numero di CPU.
Prova a pensare a un servizio sergreto che vuole decriptare le 
comunicazioni GSM in irak. Il problema non è il flusso di dati grezzo, 
ma la fase di crack. Il programmatore al servizio del servizio segreto 
è bene che usi la GC in questo caso? Non è nemmeno un esempio tanto 
casuale, anche se non ho minimamente idea di cosa usino i nostri 
servizi segreti per i loro tools.


 sotto il mio controllo e si succhi tutta la CPU.
Sbagli. Il programma sotto windows si direbbe che è fatto con i fiber, 
ma questo non toglie che possa girare sopra un sistema operativo 
multitask e multithread. Quindi le problematiche di cosa fa la GC in 
casi estremi come questi rimane comunque valida.
Se vuoi togliamo i thread, e parliamo di interupt hardware che 
scatenano routine. Cose del genere le ho programmate nel mio oscuro 
periodo di automazione industriale. Cambia poco, in un sistema simile 
c'è comunque un sistema operativo che fa le sue cose. Se ci mettiamo un 
GC che implicazioni ci sono nella gestione della memoria? Boh.
Magari parte la GC per un *altro* processo e mi pianta il mio. Boh, 
tutto può essere. Dipende come è fatto il sistema.


 
C'è un tale che si chiama Herb Sutter che non la pensa proprio così:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1956.pdf
Tra l'altro tratto da questo link:
"..A technology like C++/CLI is essential to C++’s continued success on 
Windows in particular. CLI librar-ies are the basis for many of the new 
technologies on the Windows platform, including..."
Questa frase e il fatto che MS habbia assoldato Sutter dovrebbe 
rispondere a chi dubitava dell'impegno di MS sul fronte C++. Solo che lo 
fanno "alla loro maniera" ma questo è un'altro discorso...


A me sembra che il problema stia nel fatto che tecnologie come GC e
application server vengono spacciate come soluzioni magiche a problemi
quali gestione della memoria e multithreading/sincronizzazione.
In realta' i problemi non li eliminano tutti ed in cambio causano una
minor attenzione agli stessi e di conseguenza di fatto ostacolano la
diffusione di conoscenze specifiche.
Sbaglio?
Ciao,
Nicola

 teoricamente il thread della GC potrebbe non essere mai schedulato.
Certo. Dipende dal tipo di applicazioni.
Se pensiamo ad un programma con GUI, tipicamente ci sono diversi tempi 
morti di cui il GC potrebbe avvantaggiarsi, ma in altri campi puo' 
succedere come dici tu. Tuttavia, per quanto io non ami il GC in 
generale, e' proprio in questi che non lo userei neanche morto.
  bye
	av.

 rispondere a chi dubitava dell'impegno di MS sul fronte C++.
O forse, molto più semplicemente, fa capire che Sutter sponsorizza il
suo datore di lavoro, al di là di meriti tecnici :-)

 100% sia una cagata. (non la CPU al 100% ma UN singolo therad)
Come succedeva con il compilatore del VB6 che quando compilava lui andava al 
100% e non riuscivi piu' a usare il PC finche' non aveva finito.
Eppure anche se era una cagata lo abbiamo usato e continuano ad usarlo una 
marea di persone anche su Vista !
-- 
Gugu
OIBABOI! (Tutti insiem OiBaBoi)

Andrea Laforgia ha scritto:

Volevo dire che il fatto che MS abbia assunto uno della fama di Sutter 
mi fa supporre che MS creda in un qualche modo nel futuro di c++ in win
D'altra parte credo che a tutt'oggi la maggior parte del sw ms sia 
sviluppato in c++ ...

 fanno "alla loro maniera" ma questo è un'altro discorso...
Rispetto Herb Sutter che e' una persona in gamba, pero' e' un
dipendente Microsoft e proprio perche' e' una persona leale lo e'
innanzi tutto, e giustamente, col suo datore di lavoro.
Personalmente considero C++/CLI un altro linguaggio rispetto al C++,
appena piu' simile al C++ vero e proprio di quanto non lo siano per
esempio C o Java.
Ciao,
Nicola

 non lo userei neanche morto.
Certo. Però in altri casi può essere comodo. I miei programmi 
giocattolo per i test li faccio in dotnet, per dire. Il tempo di 
sviluppo è importante, e la GC mi aiuta a velocizzarmi. Per questo se 
c'è una GC ed è uno standard è meglio. Poi se serve si usa, altrimenti 
no. Mai usato in vita mia std::set; non mi serviva, non l'ho mai usato 
(per fare un esempio cretino).
Su altri progetti andrei in un terreno che non conosco, in cui non vedo 
nessun vantaggio ad usare una GC. Sia per la indeterminatezza della 
chiamata agli allocatori, sia per la mia non conoscienza del "peso" di 
una GC sotto stress.
Però riconosco la mia ignoranza in materia di GC. Rimango scettico, ma 
sono aperto a cambiare idea.


 Certo.
Ho scritto esattamente le stesso cose hai detto tu. E' stata una 
giornata particolarmente pesante, scusami. Potevo anche risparmiarmi il 
post inutile e scrivere semplicemente: la penso anchio così.


 fuori l'accrocchio
Qui non ti seguo più. Cosa centrano i tipi con i puntatori ai tipi? Mi
è sembrato che nel post ha cui rispondi fosse auspicato che un
puntatore a un oggetto gestito dalla GC di sistema fosse un tipo di
puntatore *diverso* da quello in cui la deallocazione deve essere
gestita in modo esplicito dal programmatore.
Mi viene in mente questo pseudo codice simil microsoft.
int _gc* p = new int;
int * d = p <-- cacca
ma senza una differenziazione qui cosa succederebbe?
void Papero()
{
  int * p = new int;
}
e un errore o parte la GC? E sopratutto se non fosse un errore questo
codice devo ciucciarmi sempre la GC? Come noterai NON ho letto i link
da te postati, aspetto che tu mi dia la soluzione già pronta senza
nessuna fatica per me :-)

 
:-)
  bye
	av.

 un thread separato, magari a priorita' piu' bassa.
Questo č un dettaglio implementativo. Posso avere garbage collection
senza alcun thread separato, per dire.
-- 
blog:  
http://www.akropolix.net/rik0/blogs
 | Uccidete i filosofi,
site:  
http://www.akropolix.net/rik0/
      | tenetevi riso e
forum: 
http://www.akropolix.net/forum/
     | bacchette per voi.

 senza alcun thread separato, per dire.
Se è lo stesso thread ha la stessa priorità, e già su questo c'è da 
discutere. Tra l'altro se è lo stesso thread per forza di cosa la parte 
di codice del tuo programma che "lavora" è completamente ferma se parte 
la GC. Cosa che sui sistemi multiprocessore può essere una scelta 
"stupida".


 "stupida".
Non è detto che se la GC sta in un thread separato, sia in grado di 
girare su un processore differente da quello utilizzato dal programma.
Saluti  Manlio Perillo

 girare su un processore differente da quello utilizzato dal programma.
Qui mi son perso...
perche' non dovrebbe essere "in grado di girare su un processore
differente"?
Su sistemi SMP a memoria condivisa, molti sistemi operativi
gia'suddividono un processo monothread su piu' processori (ovviamente
_non_ eseguendo il processo contemporaneamente su piu' processori).
Quindi, anche se il thread GC a cui stai pensando non dovesse essere
thread safe, lo vedo comunque slegato dal concetto di processore.
Peraltro, scrivere un GC non thread-safe su un sistema
(potenzialmente)multiprocessore (come i pc odierni) mi suona un po'
fantasioso.
Se invece parliamo di sistemi non SMP, la cosa puo' avere senso
 
-- 
I'm trying a new usenet client for Mac, Nemo OS X.
You can download it at 
http://www.malcom-mac.com/nemo

  "stupida".
Su sistemi multiprocessore e' quantomeno una scelta curiosa, ma
sono dopotutto dettagli implementativi...
--
Marco


  Se invece parliamo di sistemi non SMP, la cosa puo' avere senso
dicevo:
.. la cosa puo' aver senso, ma non la vedo una situazione
moltodiffusa, e comunque una non espicitamente supportata dal
linguaggio.
--
Marco


 "stupida".
Se fai garbage collection con reference counting, per esempio, non hai
alcun thread separato e non esiste il concetto di 'parte il garbage
collector'.
Poi per inciso fino a poco tempo fa i thread erano nella maggior parte
dei computer più un modello concettuale che altro: se sei
monocore/monoprocessore per definizione in un dato istante o stai
eseguendo un task o ne stai eseguendo un altro. Uso il termine 'task' in
senso lato, nel senso che a questo livello poco importa se sei
multiprocessore o multithread, come non importa se hai green thread o
altro.


 collector'.
Stavo per risponderti al messaggio precedente che, appunto, se non e' un 
thread separato allora tanto vale usare degli smartpointer, ma forse e' 
quello che stai dicendo anche tu qui.
(Poi io questa non la chiamerei GC, ma forse sbaglio).
  bye
	av.

 alcun thread separato
Allora il thread/funzione lo gestiste il sistema operativo, oppure tu 
richiami esplicitamente il GC. Non vedo altre possibilità. Su un S.O. 
monotask tipo dos vedo difficile sviluppare un linguaggio con GC. O 
almeno, accademico, ma non realisitico.


 almeno, accademico, ma non realisitico.
*non* esiste il thread. e in effetti *non* esiste 'funzione' (non
necessariamente, per lo meno). E non è neppure necessariamente questione
di sistema operativo. Dipende in buona sostanza se il linguaggio gira in
una macchina virtuale oppure no.
Se gira in una macchina virtuale potrebbero essere generati per gli
assegnamenti istruzioni apposta dal compilatore oppure potrebbe essere
parte della funzione di assegnamento della macchina virtuale. Su un
linguaggio compilato nativo chiaramente solo la prima opzione è
fattibile.
Ed è roba tutt'altro che accademica: linguaggi con garbage collection a
reference counting sono parecchio diffusi. L'implementazione in C di
Python per esempio usa prescisamente questa tecnica (reference counting
'implicito' dentro la macchina viruale).
Ma ti faccio un esempio. Ti presento un linguaggio fittizio simil-java
con gc a ref counting.
Foo aFoo = new Foo();
Foo anotherFoo = new Foo();
aFoo = anotherFoo;
r1 è lo stack pointer, uso una asm simil-ppc, fingendo che le istruzioni
possano caricare una parola di memoria in una singola istruzione, rx
sono i vari registri.
Con la semantica senza ref counting l'assegnamento diventerebbe qualcosa
come:
lwz     r0, -4(r1)    ;; prendi l'indirizzo contenuto in anotherFoo
stw     r0, -8(r1)    ;; mettilo dentro aFoo
A questo punto in qualche momento partirà il gc e segherà l'oggetto
originariamente riferito da aFoo.
Se hai ref counting generi
lwz     r3, -8(r1)    ;; prendi l'indirizzo l'oggetto in aFoo
lwz     r4, 0(r3)     ;; prendi il numero di riferimenti, supposto nella
                      ;; prima parola dell'oggetto
addis   r4, r4, -1    ;; decrementalo
stw     r4, 4(r3)     ;; salvalo
cmpwi   cr7, r4, 0    ;; controlla che non sia zero
beq     foo_destr     ;; se è 0, salta al distruttore
lwz     r3, -4(r1)    ;; prendi l'indirizzo contenuto in anotherFoo
stw     r3, -8(r1)    ;; mettilo dentro aFoo
stw     r4, 0(r3)     ;; prendi i riferimenti 
addis   r4, r4, 1     ;; incrementalo
stw     r4, 0(r3)     ;; salvalo
Chiaramente il costo è abbastanza evidente (fai anche conto che qui io
lo ho scritto in asm pseudofunzionante ppc, per cui non ho istruzioni
che modificano direttamente la memoria, se no il tutto sarebbe
visivamente più 'corto').


 
magari dico una mega ca****ta non conoscendo il funzionamento dei gc ne
dei compilatori; ma....
_parte_ del lavoro del gc non potrebbe essere fatto a compile-time???
Ciao
-- 
Andrea Corradi | Debian User | 
www.debian.org
Fingerprint: A41E F6B0 DBDB F04C 4940 E411 30F3 CD62 57B1 8458
gpg --keyserver 
keyserver.linux.it
 --recv-key 57B18458
Please avoid sending me Word or PowerPoint attachments.
http://www.gnu.org/philosophy/no-word-attachments.html

 _parte_ del lavoro del gc non potrebbe essere fatto a compile-time???
Rispondo io: allora in linea puramente teorica, si. Quando la tecnologia
degli analizzatori di interi e puntatori *sound* e conservativi
progredirà sufficientemente (al momento sono argomento di ricerca, anche
se c'è una notevole base comune con tecniche comunemente impiegate dagli
ottimizzatori dei compilatori, pur con molto meno rigore).
Allora in determinati casi potrebbe essere possibile calcolare
staticamente quali sono i riferimenti ad un dato oggetto, quindi sapere
quando non se lo fila più nessuno e ficcare in quel punto i distruttori.
Ovviamente appena sei multithreading il tutto diventa talmente
complicato da farmi sentire ragionevolmente sicuro nel dirti 'non per un
bel po'', probabilmente mai in modo soddisfacente.
Ad ogni modo discutendo empiricamente con il mio co-relatore, la frase
che lui ha usato per un analizzatore che riuscisse a fare quanto sopra
era, se lo fai rischi di vincere un Turing Award. Risolvere il problema
nella sua completa generalità sarebbe *di fatto* la vittoria totale dei
garbage collector sulla gestione statica, poichè avrebbe i vantaggi di
entrambi (con chiaramente qualche possibile inefficienza dovuta al fatto
che un metodo sound e completo non è possibile causa il problema della
terminazione, ma se le inefficienze fossero statisticamente piccole...).
