Newsgroup: it.comp.lang.delphi
Titolo: Memoria utilizzata

Salve
ho fatto un piccolo programmino che parte all'avvio del pc e lavora in
background. Questo prog non fa altro che monitorizzare la connessione
internet e calcolare semplicemente i tempi di connessione. In un Thread
separato, poi, quando sono connesso, memorizzo gli url visitati con una
frequenza di 5 sec.
Quindi il programma è semplice e fa utilizzo di tre sole form(con pochi
componenti) che per altro, creo e distruggo a runtime. Il punto è che con
mio enorme stupore, lanciando il Task Manager, mi sono accorto che tale
programmino utilizza la bellezza di 10000 KB di memoria, per intenderci il
doppio di Norton antivirus e poco meno di explorer. Come è possibile? Da
cosa dipende la quantità di memoria necessaria all'applicazione per operare?
Ci sono degli accorgimenti particolari in fase di sviluppo?
Ciao e grazie
Andrea Cocci


Mars University: «Knowledge brings Fear»

Eè possibile che lui abbia linkato troppe librerie ?
Secondo voi a linkare solo quelle verament eutilizzate si diminuisce lo
spazio ?
"Blowin' free" <andre...@TRIMinwind.it> ha scritto nel messaggio
news:jSB2c.55964$FJ6.1...@twister1.libero.it...

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (
http://www.grisoft.com
).
Version: 6.0.613 / Virus Database: 392 - Release Date: 04/03/2004

 lo spazio ?
E' un problema che è stato affrontato qui qualche tempo fa...suppongo tu
ti riferisca alle unit elencate nella clausola "uses", giusto?
Si è scoperto che l'uso di una unit non influisce direttamente sulle
dimensioni dell'eseguibile poichè se tale unit non contiene risorse
utilizzate in qualche modo dall'applicazione (ad esempio, classi che
vengono istanziate), il codice non viene compilato.
Tuttavia, se all'interno di questa unit è presente una sezione
"initialization" o "finalization", essa viene compilata per essere
eseguita al caricamento della unit stessa e quindi anche il codice
dipendente viene compilato, incrementando le dimensioni dell'eseguibile.
A questo caso si aggiunge anche l'inclusione di risorse: se la unit
possiede una direttiva $R, le risorse appartenenti al file specificato
vengono prelevate e incluse nell'eseguibile.
I valori indicati dall'Original Poster mi sembrano però un po' eccessivi
per essere ricondotti a questo tipo di problema...ma non si sa mai,
quindi hai fatto molto bene a riportare il caso. ;-)


 funzionamento?
Va subito al massimo, e rimane pressoché costante (dai 9500 agli 11000 KB)

)

 se le dimensioni raggiungono lo stesso livello.
Ho studiato un pň la unit del componente in questione. In effetti non č
molto complicata: si tratta di un semplice timer che utilizza funzioni di
wininet per il controllo della connessione.
Il componente aggrava la situazione di "soli" 2000 KB.
Un solo form vuoto richiede 1700 KB; se aggiungo CPRasMonitor salgo a 4000
KB.
Aggiungendo il datamodule con relativo TAdoConnection e TAdoQuery arrivo a
5200 KB.
MainMenů (8 voci) e ImageList con 8 icone associate al menů arrivo a 5600
KB.
Aggiungo al DataModule il TJetEngine per la compattazione a runtime del
database Access arrivo a 5500 KB.
Aggiungo icona traybar arrivo a 5600 KB.
Se poi utilizzo una funzione per archiviare gli url che utilizza la unit
ddeman, la unit registry, wininet, inifiles, dateutils, arrivo a 6000 KB.
Poi ho scoperto l'arcano! Quando apro il db la memoria passa a 8000 KB e non
viene rilasciata alla chiusura delle query. Mi spiego:
L'applicazione parte all'avvio del PC e si piazza sulla tray. Al create
setto la stringa di connessione del TAdoconnection al db ma non faccio
operazioni di accesso al db e la memoria utilizzata non aumenta.
Aumenta di colpo e arriva a 8000 KB allo show quando faccio una query per
caricare i 3 combo presenti e , nonostante io CHIUDA la query, č come se la
memoria utilizzata non venisse rilasciata, infatti nella dir del db access
si crea il rispettivo file ldb che non viene rimosso finchč non chiudo la
connessione con AdoConnection1.close.
Ora io mi chiedo: non basta chiudere le varie query e (non in questo caso) i
comp Table per rilasciare memoria?
Mi sembra un pň macchinoso ogni volta chiudere e aprire la connessione...
Come si deve operare?
Grazie
Andrea

Come si deve operare?
Mi sa che te lo devi tenere cosi'... e eventualmente chiudere la connessione.
Il problema e' molto piu' complesso perche' entrano in gioco i dataset che
utilizzi, se hanno o meno il cursore lato cliente, se hanno la proprieta'
active automatica, ecc... con Ado anche io ho questi problemi: finche non
chiudi la connessione rimane allocato il file di lock di access, sintomo che
si stanno spendendo risorse per gestire l'accesso. Curiosita': hai mai provate
a visualizzare quel file di lock? E' un banalissimo file ascii, con dentro
nome e dominio di chi ha aperto il db.
Ciao
P.S.
Se trovassi un'altra soluzione ti pregherei di renderla nota!!
^___^
-- 
Morde. 
(
mo...@despammed.com
)
M-List di icld: 
http://it.groups.yahoo.com/group/icld/

 Se trovassi un'altra soluzione ti pregherei di renderla nota!!
Ho notato però che non sempre chiudendo la connessione la memoria viene
rilasciata, infatti dall'help:
"TAdoConnection.Close
Call Close to disconnect from the remote source of database information.
Before the connection component is deactivated, all associated datasets are
closed. Calling Close is the same as setting the Connected property to
False.
In most cases, closing a connection frees system resources allocated to the
connection."
L'ultima riga è significativa (In most cases.., dunque non sempre), quindi
non avrebbe senso chiudere e aprire continuamente la connessione, se non in
particolari situazioni che non possono essere dedotte a priori dallo
sviluppatore...
Ricordavo tra i miei tips una funzione riguardo il refresh della memoria,
così l'ho provata e funziona una meraviglia: la memoria viene deallocata
completamente, addirittura la memoria usata risulta essere minore di quella
"base" richiesta all'avvio! La posto:
procedure RefreshMemoryUsage;
var
  MainHandle : THandle;
begin
  MainHandle := OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessID);
  SetProcessWorkingSetSize(MainHandle, $FFFFFFFF, $FFFFFFFF);
  CloseHandle(MainHandle);
end;
Ho pensato che si potrebbe chiamarla in punti strategici del programma o, se
si vuole farla completa, dopo la chiusura di ogni dataset.
Che ne pensate? Potrebbero esserci controindicazioni?
Ho guardato sull'help SetProcessWorkingSetSize e non mi pare ci siano cose
particolari di cui preoccuparsi. Che ne dite?
Ciao
Andrea Cocci

  * Interfering with Windows' ability to manage RAM.
In pratica (al di la' del fatto che tu allochi la massima ram e non la
diminuisci), agire sulla memoria disponibile per un processo, non risolve il
problema che il processo stesso alloca memoria e la libera quando vuole.
Questi comportamenti imho sono tipici dei garbage collectors: quando un
compilatore si preoccupa per te di gestire la memoria, allora ti devi
aspettare che essa, se impegnata, sara' rilasciata "al piu' presto possibile",
ma non saprai mai quando precisamente.
Forse ho detto delle cazzate, ma mi sembra che il problema in origine non
abbia soluzione: il wrapper di delphi per ADO gestisce la memoria come meglio
crede, e noi possiamo al limite trovare dei workaround per ottimizzarla (ma
non saprei per quali minimi vantaggi ne varrebbe la pena).
Cosa ne pensano gli altri ?
