Optymalizacja wykorzystania pamięci programu Delphi

Podczas pisania długotrwałych aplikacji - programy, które spędzą większość dnia zminimalizowane do paska zadań lub zasobnik systemowy, może okazać się ważne, aby program nie „uciekał” z wykorzystaniem pamięci.

Dwie kolumny po prawej stronie wskazują użycie procesora (czas) i pamięci. Jeśli proces poważnie wpłynie na którykolwiek z nich, system zwolni.

Rzeczy, które często wpływają na użycie procesora, to program, który zapętla się (poproś dowolnego programistę, który zapomniał umieścić instrukcję „czytaj dalej” w pętli przetwarzania plików). Tego rodzaju problemy można zwykle dość łatwo naprawić.

Z drugiej strony użycie pamięci nie zawsze jest oczywiste i wymaga zarządzania bardziej niż poprawiania. Załóżmy na przykład, że uruchomiony jest program typu przechwytywania.

Ten program jest używany przez cały dzień, być może do przechwytywania telefonu w punkcie pomocy lub z innego powodu. Nie ma sensu wyłączać go co dwadzieścia minut, a następnie uruchamiać ponownie. Będzie używany przez cały dzień, choć w rzadkich odstępach czasu.

instagram viewer

Jeśli ten program opiera się na dużym przetwarzaniu wewnętrznym lub ma dużo grafiki w swoich formach, wcześniej czy później zużycie pamięci będzie rosnąć, pozostawiając mniej pamięci dla innych częstszych procesów, zwiększając aktywność stronicowania i ostatecznie spowalniając komputer.

Powiedzmy, że zamierzasz zaprojektować program z główną formą i dwiema dodatkowymi (modalnymi) formami. Zwykle, w zależności od wersji Delphi, Delphi wstawi formularze do jednostka projektu (Plik DPR) i będzie zawierać wiersz do utworzenia wszystkich formularzy podczas uruchamiania aplikacji (Aplikacja. CreateForm (...)

Linie zawarte w jednostce projektu są zaprojektowane przez Delphi i są idealne dla osób, które nie znają Delphi lub dopiero zaczynają z niego korzystać. Jest to wygodne i pomocne. Oznacza to również, że WSZYSTKIE formularze zostaną utworzone podczas uruchamiania programu, a NIE, gdy będą potrzebne.

W zależności od tego, o co chodzi w projekcie i zaimplementowanej funkcjonalności, formularz może zużywać dużo pamięci, więc formularze (lub ogólnie: obiekty) powinny być tworzone tylko w razie potrzeby i niszczone (uwalniane), gdy tylko przestaną być niezbędny.

Zarówno „DialogForm”, jak i „OccasionalForm” należy usunąć z listy „Automatyczne tworzenie formularzy” i przenieść na listę „Dostępne formularze”.

Należy pamiętać, że opisana tutaj strategia opiera się na założeniu, że dany program jest programem typu „przechwytywanie” w czasie rzeczywistym. Można go jednak łatwo dostosować do procesów typu wsadowego.

Delfy próbował to zminimalizować i ma własną architekturę zarządzania pamięcią, która wykorzystuje znacznie mniejsze bloki, ale tak jest praktycznie bezużyteczne w środowisku Windows, ponieważ przydział pamięci ostatecznie zależy od systemu operacyjnego.

Gdy system Windows przydzieli blok pamięci procesowi, który zwalnia 99,9% pamięci, Windows nadal będzie widział, że cały blok jest w użyciu, nawet jeśli faktycznie jest tylko jeden bajt bloku używany. Dobrą wiadomością jest to, że system Windows zapewnia mechanizm usuwania tego problemu. Powłoka zapewnia nam API o nazwie SetProcessWorkingSetSize. Oto podpis:

Z definicji funkcja SetProcessWorkingSetSize ustawia minimalne i maksymalne rozmiary zestawu roboczego dla określonego procesu.

Ten interfejs API ma na celu umożliwienie ustawiania niskiego poziomu minimalnych i maksymalnych granic pamięci dla przestrzeni wykorzystania pamięci procesu. Ma jednak wbudowane małe dziwactwo, które jest najbardziej szczęśliwe.

Jeśli zarówno minimalna, jak i maksymalna wartość są ustawione na $ FFFFFFFF, wówczas API tymczasowo skróci ustawiony rozmiar do 0, zamieniając go z pamięci i natychmiast po odbija się z powrotem do pamięci RAM, będzie miała przydzieloną minimalną ilość pamięci (wszystko dzieje się w ciągu kilku nanosekund, więc dla użytkownika powinno to być niedostrzegalny).

Wywołanie tego interfejsu API będzie wykonywane tylko w określonych odstępach czasu - nie w sposób ciągły, więc nie powinno mieć żadnego wpływu na wydajność.

Teraz okresowo sprawdzaj liczbę ostatnich tyknięć w stosunku do „Teraz”, a jeśli różnica między nimi jest większa niż okres uważany za bezpieczny okres bezczynności, skróć pamięć.

Teraz zdecyduj, po jakim czasie program zostanie uznany za bezczynny. W moim przypadku zdecydowaliśmy się na dwie minuty, ale możesz wybrać dowolny okres w zależności od okoliczności.

Dostosowanie tej metody do długich czasów przetwarzania lub procesów wsadowych jest dość proste. Zwykle masz dobry pomysł, gdzie rozpocznie się długi proces (np. Początek pętli czytającej miliony rekordów bazy danych) i gdzie się zakończy (koniec pętli odczytu bazy danych).

Po prostu wyłącz licznik na początku procesu i włącz go ponownie na końcu procesu.