fprintf i pamieć RAM

0

Witam. Pisze programy do symulacji i ostatnio natrafiłem na problem któego nie mogę rozgryźć. Programy mi się w trakcie długich symulacji wysypywały, czasami bez komunikatów czasami z komunikatam o problemach z załądowaniem biblioteki curses. Zauważyłem, że zżera mi pamięć RAM. Testowałem kod, analizowałem i doszedłem do momentu w którym stwierdziłem, że to się dzieje przez wywołąnie funkcji fprintf. Wydawało mi się to dziwne, ale nic innego nie znalazłem. Napisałęm więc krótki programik testowy:

#include <stdio.h>

int main(int argc, char **argv)
{

        FILE *fileOutput;
	char _file[255] = "";
	
for(long i=0; i<100000000; i++){
       	sprintf(_file, "./pliki/t%d.txt", i);
        fileOutput = fopen(_file,"w");
	if (!fileOutput) {
		return 0;
	}
        fprintf(fileOutput, "%ld\n", i);
        if(!fclose(fileOutput)) ; else printf("error");
}
	return -1;
}

Okazuje się, że jak się ten program odpali (nie ważne czy pod Winem czy pod Linuxem) to pamięć przydzielona do procesu jest stała, ale globalny wskaźnik pamięci PC-ta pokazuje, że systematycznie ona ginie, aż do wyczerpania 100%.
Czy ktoś może mi powiedzieć o co chodzi. NIe wiem, czy ja robię jakiś błąd w zapisie, którego nie mogę wyłapać, czy to jest jakiś inny powód.
Będę wdzięczny za pomoc :-).

0

Mi to bardziej wygląda na błąd przy sprintf, zamiast %d daj %ld może będzie poprawnie zdejmować zmienne ze stosu.

0

Nie to chyba nie to, tam rzeczywiście jest %d ale to chyba sprawdzałem też z %ld, zresztą testowalem to też na int z %d i to samo sie dzieje. Nie mogę za chiny dojść o co chodzi. Sprawdzę to jeszcze raz, ale to jednak chyba nie to.

Sprawdzone, dzieje się to samo. U mnie akura to rosnie ok 1MB/sek RAMu :/.

Dodatkowo ciekawe jest to, że jak proces potraktuje killem albo się skończy to ten ram sie zwalnia dopiero jak usunę te pliki utworzone przez program. Pytałem się znajomych i sam analizowałem to na kilku kodach i praktycznie dzieje się to wszędzie w różnym tempie. Akurat ten kod działał długo i uwidoczniło się to wysypaniem procesów i tym, że pamięć się nie zwolniła.

0

-z każdym plikiem związany iwęzeł, a system próbuje trzymać w pamięci ostatnio używane iwęzły
-operacje dyskowe są buforowane przez system, co też zajmuje ram
-do 100000000 plików trzeba dużego dysku(coś koło 500GB). Nawet jeżeli te pliki będą puste, to zapełnisz tablicę iwezłów plików (mówię o EXT3)

W jakim celu potrzebujesz 100 000 000 plików?
Operacje na plikach są bardzo kosztowne i nawet jeżeli być miał dysk 1 TB i 16 GB ramu to utworzenie 100 milionów plików zajmie ci z godzinę.
Nie możesz wrzucić wszystkich danych do kilku plików(np. po 100MB)?

0

Inna sprawa, że i windows i linux posiadają buforowanie zapisu - zmieniona zawartość pliku, nowe dane czyli pliki są przechowywanie w ramie zamiast zapisywane bezpośrednio na dysk. Cały ten cyrk ma za zadanie przyśpieszyć dostęp do dysku, pozwala oszczędzić dysk redukując ilość ruchów głowic. Nie pamiętam dokładnie jak wygląda mechanizm pod względem zasad, którymi się systemy kierują przy określaniu momentu opróżnienia buforów, ale od czegoś są API fflush (FILE*) z stdlib i z WINAPI FlushFileBuffers (HANDLE). Dodaj

fflush(fileOutput);

i powiedz czy nadal robi takie cuda. Deskryptory w pamięci też swoje robią - nie jest powiedziane, że od razu są niszczone po zamknięciu pliku, są powiązane z buforowaniem.

p.s. zamiast 100000000 plików lepiej zrobić jeden z rekordami o stałym rozmiarze lub ew. zmiennym + nagłówek /ew. można go dla wygody dać do oddzielnego pliku/.
p.s.2: jeżeli o WinApi chodzi to polecam zapoznanie się z flagami FILE_FLAG_WRITE_THROUGH i FILE_FLAG_NO_BUFFERING dla CreateFile

0

Ok dzięi, sprawdzę to i dam znać co z tego wyjdzie.
Do tej pory jakoś tego nie zauważyłem bo symulacje były krótkie, a teraz jak to wszystko idzie kilka dni i tych zapisów się trochę pojawiło, to zaczęły się cyrki.
PS: W kodzie programu symulacji te pliki nie są zapisywane naraz, pomiędzy zapisami jest sporo obliczeń. Tak naprawdę są 2 sytuacje: 1 - dopisywanie do pliku, 2 - zapis w osobnych plikach (nie wszystkie w 1 katalogu).

Sprawdziłem tą funkcję fflush, nic to nie daje. To jest jakieś dziwne. Jeszcze raz przeanalizowałem ile tak naprawdę tych zapisów do pliku jest: do 1 pliku dopisuje co pewien czas i w sumie ma on ok 1MB, i potem jest kilkadziesiąt (ok 20) plików kilku KB też zapisywanych co pewien czas no i jeszcze co pewien czas nadpisuje dane do 1 pliku - ok kilku KB.
Tak naprawdę to ten efekt zauważyć można na kilku kodach, ale na każdym z różną intensywnością. Nie mogę znaleźć innego błędu. Może mi ktoś powiedzieć, czy jeśli jest to jeszcze inny powód, to możliwe, żeby pamięć nie była widoczna w zasobach procesu tylko gdzieś tam wyciekała nie wiadomo gdzie i po zakończeniu procesu nie była zwalniana?

Może ktoś wpadnie jeszcze na jakiś pomysł. Będę wdzięczny :)

0

Możesz użyć biblioteki do pakowania plików(np bezpłatnego zliba: www.zlib.net)
Dla danych tekstowych zmniejszy to wielkość plików jakieś 10 razy.
Możesz też umieszczać kilka plików w jednym archiwum.

0

Ludzie przecie to czyste wariactwo: 100 mln plików! [rotfl]

Przypominam sobie jednego 'mistrza programowania',
który zrobił program do fakturowania, i zapisywał tam
każdą fakturkę w osobnym pliku.

Sprzedał to cudo pewnej piekarni,
i gdy facet robił zestawienie miesięczne, to czekał kilkadziesiąt minut.
(tych faktur nie było oczywiście milion, ale sprzęt inny - lata 90te,
zeszłego tysiąclecia, ma się rozumieć) :-)

Katalogi na NFTS mogą być kompresowane przez system.

0

Z tymi milionami to raczej przesada. Ale jeśli chodzi o długie symulacje fizyczne, to duża ilość niezależnych plików jest uzasadniona. Taka symulacja lubi trwać i kilka miesięcy więc:

  1. głupio, jak po 40-tu dniach błąd programu zamaże wszystkie wyniki, bo cały czas pracuje na tym samym pliku
  2. wygodnie jest otrzymywać od czasu do czasu wyniki w kawałkach i je sobie obrabiać, kiedy symulacja myśli nad nowymi
  3. ale to i tak wystarczy zapisywać/dopisywać raz na kilkadziesiąt minut, więc to wyjdzie kilka tysięcy, a nie milionów.

1 użytkowników online, w tym zalogowanych: 0, gości: 1