2011-07-15 17 views
5

Próbuję wyśledzić problem z pamięcią przez kilka dni - mój program zużywa około 3 GB pamięci, kiedy powinno używać około 200MB-300MB. Valgrind faktycznie informuje, że używa w szczytowym momencie ~ 300 MB i nie zgłasza żadnych wycieków pamięci.Nie można wyśledzić źródła ogromnego użycia pamięci

Program odczytuje plik wejściowy i przechowuje wszystkie unikalne słowa w tym pliku. Jest wielowątkowy i uruchomiłem go za pomocą 4 wątków. Moje główne źródła danych są:

  • stałym rozmiarze tablicy wchar_t (4MB łącznie)
  • Mapa między słowami i listy wartości stowarzyszonych. To rośnie wraz z rozmiarem danych wejściowych. Jeśli w pliku wejściowym znajduje się 1 000 000 unikalnych słów, w drzewie będzie 1 000 000 wpisów.

Wykonuję ogromną liczbę alokacji i deallokacji (przy użyciu nowych i usuń) - co najmniej dwa na jedno unikalne słowo. Czy to możliwe, że pamięć, którą uwolniłem, nie jest ponownie wykorzystywana z jakiegoś powodu, powodując, że program wciąż zdobywa coraz więcej pamięci? Konsekwentnie pobiera więcej, ponieważ nadal działa.

Generalnie, wszelkie pomysły dotyczące tego, dokąd powinieneś się udać?

Edytuj 1 (na podstawie porady od Grahama): Jedna ścieżka, którą spróbuję, to minimalizacja alokacji. Będę pracował z pojedynczym ciągiem na wątek (który może rosnąć sporadycznie, jeśli słowo jest dłuższe niż ten ciąg), ale jeśli dobrze zapamiętam mój kod, wyeliminuje to ogromną liczbę nowych/usuniętych połączeń. Jeśli wszystko pójdzie dobrze, pozostanę z: jednorazową alokacją bufora wejściowego, jednorazową alokacją ciągu znaków na wątek (z pewnymi reallocs), dwoma allocs na wpis na mapę (jeden dla klucza, drugi dla wartości).

Dzięki!

+0

odpowiedź Grahama wydaje się ważne. W jaki sposób określasz, ile pamięci jest używane i jaki system operacyjny (i czy jest to 64-bitowy lub 32-bitowy)? Czy obiekty, które dopiero tworzysz/usuwasz, to struktury danych lub pełnoprawne obiekty klasowe? – Foon

+0

Używam Valgrind i polecenie free -m (informuje, ile pamięci jest wolnej, daje mi przybliżony pomysł, gdy zużywa mnóstwo pamięci). To jest na 64-bitowym systemie Linux. Próbowałem tego używając std :: string i stringów w stylu c. – lapis

Odpowiedz

7

Prawdopodobnie jest to fragmentacja sterty. Ponieważ przydzielasz i zwalniasz małe bloki w tak dużych ilościach, jest prawdopodobne, że istnieje mnóstwo małych wolnych części, które są zbyt małe, aby można je było ponownie wykorzystać w kolejnych przydziałach. Ponieważ te porcje są skutecznie marnowane, proces musi nadal przyciągać coraz więcej pamięci z systemu, aby honorować nowe przydziały.

Być może uda się złagodzić efekt, najpierw rezerwując wystarczająco dużą domyślną pojemność w każdym ciągu znaków za pomocą string::reserve(), a następnie wyczyszczając ciągi znaków, aby je opróżnić po zakończeniu ich (zamiast usuwać). Następnie zachowaj listę pustych ciągów do ponownego wykorzystania zamiast przydzielania nowych przez cały czas.

EDYCJA: Powyższa sugestia zakłada, że ​​przydzielane obiekty to std::string s. Jeśli tak nie jest, prawdopodobnie nadal możesz zastosować ogólną technikę trzymania starych pustych przedmiotów w celu ponownego użycia.

+0

To brzmi jak najbardziej prawdopodobny problem w tym miejscu, dzięki za wejście! Zmieniono mój oryginalny post ze strategią, której spróbuję. – lapis

0

Pamięć, którą program zwalnia, należy zwrócić do sterty, gdzie może zostać ponownie przydzielona.

Nie oznacza to jednak, że jest on zwalniany z powrotem do systemu operacyjnego. Często aplikacja będzie nadal "posiadać" pamięć, która została przydzielona i uwolniona.

Czy to jest aplikacja dla systemu Windows? Jak przydzielasz i zwalniasz pamięć? A jak określasz, ile pamięci używa aplikacja?

+0

Jeśli używa Valgrind, to jest to Linux. –

+0

Tak, jest zbudowany w systemie Linux przy użyciu gcc 4.4.4, używam new/delete, profilowanie z valgrind i free -m – lapis

0

Powinieneś spróbować zawinąć alokację zasobów do klasy, jeśli możesz. Wywołaj nowe w konstruktorze i usuń w destruktorze. Spróbuj i skorzystaj z zakresu, więc zarządzanie pamięcią odbywa się bardziej automatycznie.

http://en.wikipedia.org/wiki/RAII

Powiązane problemy