proszę zobaczyć następną odpowiedź przez @joeblog dla lepszego rozwiązania.
Po pierwsze, nie powinieneś potrzebować całej tej pamięci RAM. To, co powinieneś tutaj zrobić, to pobranie zestawu fragmentów. Nie rób fetchall()
. Zamiast tego użyj znacznie wydajniejszej metody. Zobacz the psycopg2 documentation.
Teraz wyjaśnienie, dlaczego nie jest ona uwalniana i dlaczego nie jest to przeciek pamięci w formalnie poprawnym użyciu tego terminu.
Większość procesów nie zwalnia pamięci z powrotem do systemu operacyjnego po zwolnieniu, po prostu udostępnia ją do ponownego użycia w innym miejscu w programie.
Pamięć może zostać zwolniona do systemu operacyjnego tylko wtedy, gdy program może zagęścić pozostałe obiekty rozproszone w pamięci. Jest to możliwe tylko w przypadku użycia referencji pośrednich uchwytów, ponieważ w przeciwnym razie przeniesienie obiektu unieważniłoby istniejące wskaźniki do obiektu. Pośrednie referencje są raczej nieefektywne, zwłaszcza w nowoczesnych procesorach, w których pogoń za wskaźnikami powoduje, że straszne rzeczy są osiągane.
To, co zwykle zdarza się, chyba że program wykona dodatkową ostrożność, polega na tym, że każda duża porcja pamięci przydzielona z brk()
wyląduje z kilkoma małymi kawałkami, które wciąż są w użyciu.
System operacyjny nie może stwierdzić, czy program nadal używa tej pamięci, czy nie, więc nie może po prostu odebrać jej. Ponieważ program nie ma dostępu do pamięci, system operacyjny zazwyczaj wymienia go z czasem, uwalniając pamięć fizyczną do innych zastosowań. Jest to jeden z powodów, dla których powinieneś mieć przestrzeń wymiany.
Możliwe jest pisanie programów z pamięcią podręczną do systemu operacyjnego, ale nie jestem pewien, czy można to zrobić za pomocą Pythona.
Zobacz także:
Więc: nie jest to faktycznie pamięć wyciek. Jeśli zrobisz coś, co wymaga dużej ilości pamięci, proces ten nie powinien zbytnio wzrosnąć, jeśli w ogóle, użyje ponownie zwolnionej pamięci z ostatniej dużej alokacji.
Dzięki! Potwierdzono, że pamięć jest ponownie wykorzystywana, uruchamiając powyższy kod dwa razy w tym samym procesie. Pamięć nie wzrosła podczas drugiego uruchomienia. –
Chociaż wszystko, co tu powiedziano, jest poprawne, wynik zapytania zwykle zostanie przeniesiony całkowicie po stronie klienta (nie przez 'fetch *()', lecz przez 'execute()'). Tak więc podczas używania 'fetchmany()' zamiast 'fetchall()' może zaoszczędzić trochę pamięci w kategoriach tworzenia obiektów Pythona, przy użyciu kursora po stronie serwera sugerowanego przez @joeblog jest właściwym rozwiązaniem. – piro