Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

TResourceStream.SaveToFile() jede memoriju...?

[es] :: Pascal / Delphi / Kylix :: TResourceStream.SaveToFile() jede memoriju...?

[ Pregleda: 2022 | Odgovora: 5 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

((BugA))
Igor Djordjevic
Bor, Srbija

Član broj: 29241
Poruke: 196
*.dynamic.isp.telekom.rs.

ICQ: 66516695
Sajt: www.MalamutKlub.com


+17 Profil

icon TResourceStream.SaveToFile() jede memoriju...?24.02.2011. u 19:44 - pre 159 meseci
Primetio sam da mi aplikacija u memoriji racunara (Windows Task Manager -> Mem Usage) nenormalno naraste, pa bi mi dobro dosla mala pomoc :/

U okviru svog .exe fajla imam resurse koje u toku rada aplikacije citam i snimam kao fajlove na hard disk. Problem je u tome sto svaki procitani i snimljeni resurs i dalje zauzima prostor u memoriji, dokle god je program aktivan. Evo kako izgleda procedura:

Code:
procedure TfrmMain.ResExtract(sName, sFile: string);
var
  RS: TResourceStream;
begin
    RS := TResourceStream.Create(HInstance, sName, RT_RCDATA);
    try
      RS.SaveToFile(sFile);
    finally
      RS.Free;
    end;
end;

Sta se desava? Po pokretanju aplikacija u memoriji zauzima (recimo) 5 MB. Kada pozovem datu proceduru za Resurs1 (5 MB), aplikacija u memoriji zauzima 10 MB - u redu, procitan je resurs od 5 MB, snimljen na disk, ali zasto memorija nije oslobodjena? Jos gore, sada kada pozovem datu proceduru za Resurs2 (5 MB), aplikacija u memoriji zauzima 15 MB...? Ovo mi nije jasno. Zasto prethodno zauzeta memorija nije oslobodjena, ili barem prepisana novim pozivom procedure? Ako procitam i na disk snimim 10 razlicitih resursa, moja ce aplikacija u memoriji zauzimati 55 MB :(

Ovaj rast se nastavlja za svaki novi resurs koji se iz aplikacije procita i snimi na disk - svaki ostaje u memoriji aplikacije, iako mi to apsolutno nije potrebno (snimio sam ga na disk, sta ce mi u memoriji, ucitacu ga ako mi bude trebao). Valja napomenuti da pozivom procedure za neki od resursa koji su vec snimljeni ne dolazi do povecanja zauzete memorije (npr. visestrukim pozivom procedure sa parametrom Resurs1 povecava se memorija samo prvi put).

E sad, kad iskomentarisem liniju RS.SaveToFile(sFile); onda nema povecanja memorije (naravno, ni fajl nije snimljen), pa pretpostavljam da je neki problem u SaveToFile() proceduri - ili ne radi kako treba, ili je ja ne koristim kako valja. Ubih se trazeci po netu, ali nisam nasao nista konkretno vezano za problem koji imam.

Pitanje - kako da procitam resurs, snimim ga na disk, i oslobodim memoriju?

Ukoliko je bitno, koristim Delphi 2009.
Hvala unapred.
 
Odgovor na temu

Daniel Mauric
Software Architect
Novi Sad

Član broj: 3279
Poruke: 31
*.adsl-a-6.sezampro.rs.



+17 Profil

icon Re: TResourceStream.SaveToFile() jede memoriju...?25.02.2011. u 23:51 - pre 159 meseci
Nema nikakve greske, tvoj kod je ispravan (bar ovo sto vidimo) i sve funkcionise kako treba, samo ne onako kako si zamislio, procitaj ovo:

http://stackoverflow.com/questions/2569661/why-does-my-delphi-programs-memory-continue-to-grow

Ajd da napisem jos koju na brzinu.
Ukratko, Task manager nije preterano merodavan, zatim, memory manager zbog optimizacije ima diskreciono pravo da radi sa memorijom sta misli da je najbolje. Drugim recima memoriju koju si zauzeo i kasnije oslobodio MM moze da ne vrati windows-u odmah. I na kraju i sam Windows zonglira sa memorijom i po potrebi swap-uje na disk. Kad se sve sabere dobar deo toga nije pod tvojom direktnom kontrolom i u normalnim situacijama ne treba da te brine. Tvoja briga je samo da oslobodis sve sto si zauzeo. Za proveru toga poteras FastMM u full debug mode-u i dobijes sve leak-ove sa call stack-om.

[Ovu poruku je menjao Daniel Mauric dana 26.02.2011. u 01:05 GMT+1]
 
Odgovor na temu

((BugA))
Igor Djordjevic
Bor, Srbija

Član broj: 29241
Poruke: 196
*.dynamic.isp.telekom.rs.

ICQ: 66516695
Sajt: www.MalamutKlub.com


+17 Profil

icon Re: TResourceStream.SaveToFile() jede memoriju...?26.02.2011. u 02:20 - pre 159 meseci
Hvala puno! :) I odgovor i link su mi pomogli da shvatim sta se zapravo desava, i mislim da sam naucio nesto novo i vrlo korisno.

Ono sto je super stvar jeste da kod moje aplikacije pali ova fora sa minimizacijom koju je dthorpe pomenuo :D Po pokretanju aplikacija zauzima oko 5~6 MB, a raspakivanjem resursa moze da naraste do 50~60 MB (bez smanjivanja, ali i ne raste vise). Medjutim, kad tako naraslu aplikaciju minimizujem, ona se smanji na ~800kB! Po ponovnom podizanju prozora iz taskbara, aplikacija zauzima oko 2,5 MB ;) (cak manje nego po pokretanju). Posle toga ide sve kao i pre, raspakivanje resursa dovodi do povecanja memorije bez smanjivanja, dok minimizacija sve to pocisti ;)

Probacu poziv SetProcessWorkingSetSize procedure nakon svakog raspakivanja, da vidim kako ide. Vidim i da su dati razlozi zasto ovo "forsirano" ciscenje memorije ne treba izazivati namerno (van Windows-ovog pozivanja pri minimizaciji), pa cu i tome posvetiti dodatnu paznju.

Hvala Daniele jos jednom, a ako nekoga bude interesovalo jos o ovoj temi, pored linka koji je Daniel vec dao, imate jos neke do kojih mozete doci sa te strane, a vrlo su poucni, npr:

http://stackoverflow.com/quest...-be-cleaned-up/2033393#2033393
http://delphi.about.com/od/win...hi-program-memory-optimize.htm
http://stackoverflow.com/quest...-the-memory-manager-to-release
http://stackoverflow.com/quest...nager-to-release-unused-memory

Pozdrav, Igor

[edit] Hehe, nakon citanja ostalih tema, mozda cu ipak ostaviti sve kako jeste ;) Po onome sto se da procitati, forsirano oslobadjanje memorije zapravo i nije pravo oslobadjanje vec samo swap-ovanje iz RAM-a na disk. Kad se za podacima ponovo javi potreba, memorija ce sa diska biti vracena u RAM, cime samo pravimo dupli posao bez potrebe. Windows sam prebacuje (swap-uje) memoriju na disk kad dodje do nestasice RAM-a, cak i kada ne minimizujemo program. Dok god radna memorija nije problem, preferira da resurse drzi u njoj radi boljih performansi (brzi pristup potrebnim podacima). Inace, kako je zakljuceno u pomenutim temama, ovo "zadrzavanje" (cache-ovanje) oslobodjene memorije je odlika FastMM-a, cime poboljsava performanse u uslovima dok ima dovoljno slobodne memorije na raspolaganju.

[Ovu poruku je menjao ((BugA)) dana 26.02.2011. u 03:59 GMT+1]
 
Odgovor na temu

tkaranovic
Tomislav Karanović
Beograd

Član broj: 220507
Poruke: 307



+18 Profil

icon Re: TResourceStream.SaveToFile() jede memoriju...?26.02.2011. u 05:13 - pre 159 meseci
Ako resursi mogu biti u dll biblioteci i ako se može biblioteka učitavati (LoadLibrary) i oslobađati (FreeLibrary), prilikom korišćenja resursa, onda će posle oslobađanja/zatvaranja (FreeLibrary) biblioteke biti i memorija oslobođena.
 
Odgovor na temu

((BugA))
Igor Djordjevic
Bor, Srbija

Član broj: 29241
Poruke: 196
*.dynamic.isp.telekom.rs.

ICQ: 66516695
Sajt: www.MalamutKlub.com


+17 Profil

icon Re: TResourceStream.SaveToFile() jede memoriju...?26.02.2011. u 10:22 - pre 159 meseci
To je tacno, Tomislave, kada resurse stavim u zasebnu biblioteku (dll) i odatle ih ucitavam ne dolazi do porasta (gomilanja) memorije samog procesa kao u prethodnom slucaju. Medjutim, preduslov je da sve bude unutar izvrsnog (exe) fajla, bez bilo kakvih dodatnih fajlova (kao sto je dll) koji bi se morali isporucivati uz exe fajl. Postoji mogucnost da se dll ubaci u sam exe, ali bi se njegovim kasnijim raspakivanjem (vadjenjem) pre LoadLibrary, bilo snimanjem na disk ili ucitavanjem u memoriju, vratili na pocetak price... Cak bi mozda tada bilo jos gore, jer bi se ceo dll smestio u memoriju naseg procesa (umesto pojedinacnih resursa sa pocetka price), pa vise ne bi ni bilo moguce oslobadjanje memorije nakon raspakivanja pojedinih resursa, sve dok se sama biblioteka ne oslobodi (zatvori).

Evo jos jednog zanimljivog linka (obratiti paznju na poduzi odgovor koji je napisao himself):
http://stackoverflow.com/quest...ram-takes-fastmm-vs-borland-mm

Koliko sam ja shvatio, sustina je da je ovo kesiranje neiskoriscenog RAM-a odlika FastMM-a. BorlandMM radi drugacije, ne zadrzava memoriju kao FastMM, ali zato radi (mnogo) sporije ;)
 
Odgovor na temu

tkaranovic
Tomislav Karanović
Beograd

Član broj: 220507
Poruke: 307



+18 Profil

icon Re: TResourceStream.SaveToFile() jede memoriju...?26.02.2011. u 11:10 - pre 159 meseci
Citat:
((-buga))-
To je tacno, Tomislave, kada resurse stavim u zasebnu biblioteku (dll) i odatle ih ucitavam ne dolazi do porasta (gomilanja) memorije samog procesa kao u prethodnom slucaju.


Hvala na ovom obaveštenju. :)

Citat:
((-buga))-
Medjutim, preduslov je da sve bude unutar izvrsnog (exe) fajla, bez bilo kakvih dodatnih fajlova (kao sto je dll) koji bi se morali isporucivati uz exe fajl. Postoji mogucnost da se dll ubaci u sam exe, ali bi se njegovim kasnijim raspakivanjem (vadjenjem) pre LoadLibrary, bilo snimanjem na disk ili ucitavanjem u memoriju, vratili na pocetak price... Cak bi mozda tada bilo jos gore, jer bi se ceo dll smestio u memoriju naseg procesa (umesto pojedinacnih resursa sa pocetka price), pa vise ne bi ni bilo moguce oslobadjanje memorije nakon raspakivanja pojedinih resursa, sve dok se sama biblioteka ne oslobodi (zatvori).


Mislio sam, ako resursi mogu biti u tom konkretnom projektu u biblioteci, mislići da postoji baš ovako neki preduslov.
 
Odgovor na temu

[es] :: Pascal / Delphi / Kylix :: TResourceStream.SaveToFile() jede memoriju...?

[ Pregleda: 2022 | Odgovora: 5 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.