czy rozmiar tablicy z tstringlistami powiniennem regulować w trakcie działania wątku/programu?
Możesz dynamicznie zmieniać rozmiar tablicy, ale możesz też tego nie robić. Wszystko zależy od przypadku.
Jeśli nie wiesz ile maksymalnie elementów trafi do danego kontenera, to nie wiadomo jak duży blok zaalokować, aby program nigdy nie przekroczył krytycznej liczby elementów. Wtedy korzysta się z takiego typu danych, który może być relokowany w trakcie działania programu — tablica dynamiczna czy ręcznie alokowane i relokowane bloki pamięci (np. GetMem
i ReallocMem
). To daje ci sam język, innych rozciągalnych typów danych, innych niż tablice dynamiczne, nie ma. ;)
Można też skorzystać z klas kontenerów, np. z list i jedną z nich jest TStringList
— im więcej stringów dodasz do niej, tym więcej pamięci będzie samodzielnie alokowała. Żeby ograniczyć liczbę relokacji, lista ta (re)alokuje bufor z miejscem zapasowym. Początkowo wzrost jest wykładniczy, aby ostatecznie osiąść na relokacji bloku z dołożeniem pustego miejsca dla przyszłych 256
elementów.
Plusem takiego podejścia jest to, że bufor dla danych jest w razie potrzeby relokowany, więc może pomieścić dowolną liczbę elementów. Minusem jest to, że wykonywana co jakiś czas relokacja wymaga pozyskania nowego bloku od menedżera pamięci (lub od samego systemu operacyjnego), a cała aktualna zawartość musi zostać przekopiowana w nowe miejsce. To jest czasochłonne i utrudnia cache'owanie danych przez CPU. Coś za coś.
Natomiast jeśli już na etapie pisania kodu wiesz, że elementów nigdy nie będzie więcej niż np. 1000
, to skorzystanie z kontenera o statycznym rozmiarze (np. ze zwykłej tablicy) jest bardzo dobrym rozwiązaniem. Miejsca nigdy nie braknie, a bufor zawsze jest w tym samym miejscu pamięci, więc ułatwia się jego cache'owanie. Minusem jest to, że używa się więcej pamięci niż w praktyce potrzeba, jednak jeśli są to kilobajty czy kilka megabajtów zapasu, to nie przeszkadza to w niczym.
Stąd pytanie czy w trakcie działania programu modyfikować rozmiar tablicy stosownie do ilości zajętych - wykorzystywanych elementów. Jeśli nie są zajęte są .free i nilowane.
Twoja tablica z miejscem dla 2000
list zajmuje 2000 * SizeOf(Pointer)
bajtów, czyli dokładnie 16KB — no nie jest to ilość pamięci, która by była imponująco duża i zmuszała do szukania optymalizacji pod tym kątem.
Zobacz na to z innej strony — czy opłaca się nil
ować puste komórki tej tablicy? Żeby później użyć tej komórki ponownie, najpierw musisz sprawdzić czy jest ona pusta, a więc najpewniej szukasz pierwszej pustej komótki, iterując od poczatku tablicy.
Jeśli usunięcie którejś listy ciągów z tablicy nie może przesuwać pozostałych list, bo np. wątki operują na tej tablicy i używają indeksów, to taka tablica jest spoko. Natomiast jeśli usuwanie i dodawanie list ciągów do tablicy może modyfikować kolejność list w tablicy, to lepiej po prostu skorzystać z listy list — nową listę dodawać zawsze na koniec i pozwolić klasie kontenera zająć się również usuwaniem elementów. W takim przypadku, zamiast z tablicy, skorzystaj z generycznego TFPGObjectList
z modułu FGL
, a za typ elementów wstaw TStringList
:
Kopiuj
uses
FGL;
type
TListOfStringList = specialize TFPGObjectList<TStringList>;