Opróznianie ramu. Visual C++ .NET 2008


(Jsgronek) #1

jak w temacie - twórzę program w C++ na platformę .net. Niestety program po dłuższej pracy zabiera coraz wiecej pamięci . Stąd moje pytanie - w jaki sposób zwolnic niewykorzystywaną przez program pamięc? Szukałem odpowiedzi w necie dobre 1,5 godziny ale nigdzie nie było to w czytelny sposób objaśnione.

Z góry dziękuję za pomoc.

Pozdrawiam


(matiit) #2

A czy w końcu brakuje tej pamięci, czy system drastycznie zwalnia? Może po prostu sobie cachuje to, a jak trzeba to zwolni.


(Jsgronek) #3

Chodzi o to że program to benchmark. Jak włączy sie go to zajmuje tam 5mb z czyms po pierwszym teście zabiera 6,5mb i po każdym kolejnym razem ta liczba wzrasta mimo że za kożdym razem wywoływana jest ta sama funkcja.


(Cieplok) #4

Spróbuj może używać bloku using do co większych obiektów jeśli wykorzystujesz takowe (jakieś listy, bitmapy; nie wiem czego używasz), wymusi to ich natychmiastowe usunięcie z GC.

Z tego co wiem to chyba nie możliwości ręcznego wywoływania oczyszczania pamięci (przynajmniej kiedyś tak było może wprowadzili takie coś).


(Jsgronek) #5

posiedziałem troche nad tym i udało mi się stwierdzić że problem polega na zmiennych. Tj zmienna słuzy jako licznik powtórzen operacji (w zależności jak duza bedzie koncowa liczba przypisana do zmiennej tak duza ocena wystawiana przez benchmark). Po wykonaniu operacji zmiennej która przebrała wartość np 80000 zostaje przypisana wartość 0. Problem w tym że podczas wzrastania przypisanej liczby zwieksza sie ilość pamięci przypisanej do programu a po nadpisaniu zmiennej liczbą 0 ilość pamięci nie maleje przez co przy każdym kolejnym wykonywaniu funkcji przypisywane sa do programu kolejne kb pamieci ram mimo ze wystarczyła by pamięc przypisana po pierwszysm wykonaniu. Uff mam nadzieje ze ktoś coś z tego zrozumie :wink: I nie wiem właśnie jak pozbyć się tego uciązliwego problemu.

Dodam jeszcze że z ciekawości zainstalowałem program Speed-x (obcina programom przypisaną ale niewykorzystywaną pamięc) i pamięc przypisana spadła do maksymalnie 2mb podczas gdy już po pierwszym przebiegu benchmarka program zabierał 6,5mb a po każdym kolejnym 1mb wiecej.


(Cieplok) #6

Chyba jednak nie za bardzo rozumiem ale mogę powiedzieć, iż:

  • jeśli masz zmienna, załóżmy że int, i do niej wpisujesz np wartość 80000 a potem 0 to ona zajmuje dokładnie tyle samo miejsca w pamięci

  • i zajmuje jej w tej sytuacji bardzo mało (na pewno nie spowoduje to takiego wzrostu zapotrzebowania na pamięć)

  • czy przechowujesz gdzieś jakieś wyniki tych iteracji o których wspominałeś? Bo jeśli tak to one mogą się kumulować w pamięci.


(Jsgronek) #7

powiem tak mam obiekt timer1. on co sekunde podwyższa wartość zmiennej timer a potem mam:

funkcja wywoływana przez przycisk{

//zeruje wszystkie zmienne potrzebne do obliczeń

start:

//tutaj jakieś obliczenia obciązające procesor

meter++; // licznik

if (timer < 60){goto start;}

}

zmieniam wartość tekst etykiety label1 na meter

to tak w uproszczeniu.

w sumie mam 2 zmienne wartości meter (około 80000) i jedną osiągającą połowę tego.


(Cieplok) #8

O jejku jejku a co to za konstrukcja?? Ponoć piszesz na nowoczesną platformę .NET, a używasz instrukcji goto!! To jest niedopuszczalne natychmiast zmień swój kod!!

Poza tym czy nie jest tak że twój program zabiera coraz więcej pamięci do pewnej granicznej wartości po czym jest ona zwalniana to rozsądnych rozmiarów? Kiedyś pisałem program który na starcie brał 24MB później po kilku symulacjach zwiększało się do około 80MB i znów spadało do około 30 i tak w koło. Za bardzo mi to nie przeszkadzało. Na słabszych kompach nie wzrastało powyżej 50 więc uznałem że to .NET sam dobiera rozmiar jaki może wykorzystać i po jego przekroczeniu uruchamia oczyszczanie.

Więc jeśli to nie są wielkie rozmiary to może pozostaje ci się pogodzić z tym stanem rzeczy. W końcu pisząc pod .NET godzisz się na nieco zmniejszoną wydajność.


(Jsgronek) #9
  1. piszę na .net od tygodnia więc chyba mnie to usprawiedliwia;)

  2. Czym mogę zastąpić tą konstrukcję?

  3. Czy to coś zmienia w głównym temacie?


(Cieplok) #10
  1. usprawiedliwia jak najbardziej

2.

funkcja wywoływana przez przycisk{

//zeruje wszystkie zmienne potrzebne do obliczeń

while (timer < 60){

   meter++;

   funkcjaDoObliczen();

}

}

void funkcjaDoObliczen()

{

//tutaj jakieś obliczenia obciązające procesor

}

to najprostsza możliwa wariacja. nie znam dokładnie jaki kod wykonujesz w zakomentowanych miejscach i gdzie zwieszasz timer ale to sa szczegoly z ktorymi zapewne sobie poradzisz

  1. to nie zmienia nic w glownym temacie. czy naprawde jest konieczne ograniczenie zapotrzebowania na pamiec? czy to sa az takie roznice?

(Jsgronek) #11

Az tak duze nie są ale jednak fakt że może zabierać 1/4 tego co zabiera jest upierdliwy...

Dzięki za przykład :wink:


(Somekindsoftware) #12

To pisz w C albo Asemblerze.

.NET jest po to, żeby szybko tworzyć funkcjonalne aplikacje, które nie wymagają wybitnej optymalizacji i super wydajności. A zarządzaniem pamięcią zajmuje się platforma - właśnie po to, by odciążyć programistę.

Co do oczyszczania pamięci - dawno temu słyszałem o metodzie Collect() - spróbuj, może pomoże.

GC::Collect();

(Jsgronek) #13

Dziękuję za wszystkie rady i porady - dzięki nim poprawiłem swój program. a co do ramu - sprawdziłem metodę Collect() jednak opróżniała ona tylko 4 kb ramu - jednak pomimo tego dziękuję za pomoc. Problem częsciowo rozwiązałem w następujący sposób - stwierdziłem że po prostu pamięć przypisana nie jest i tak przezeń wykorzystywana więc w razie czego WIndows przypisałby ten ram programowi który będzie go wykorzystywał wiec te dość duże liczby i tak nie mają znaczenia. jednak dla adekwatności rozmiaru programu (100kb) wykorzystałem trimming ( SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1):wink: - dla chętnych http://www.techblog.tomksoft.com/progra ... ation.html wiem że w praktyce nic to nie pomaga jednak mniejsze liczby mnie cieszą :wink:.

P.S: cieplok >> dzięki za wskazówki - myślę że teraz kod mojego programu bardziej pasuje do platformy na która jest tworzony.

Jeszcze raz dziękuje i pozdrawiam :wink: