2010-09-02 16 views
9

Zajrzałem do implementacji Array.Resize() i zauważyłem, że nowa tablica jest tworzona i zwracana. Dążę do zerowej alokacji pamięci podczas rozgrywki, dlatego muszę unikać tworzenia nowych typów referencji. Czy zmiana rozmiaru tablicy powoduje uruchomienie Garbage Collectora w poprzedniej macierzy? Tworzę własny program do sprawdzania tablic 2D, ale zasadniczo działa on tak samo, jak metoda .NET Resize().Czy zmiana rozmiaru tablic wywołuje GC?

Jeśli nowa tablica jest mniejsza niż poprzednia, ale nadmiar obiektów został już umieszczony z powrotem w ogólnej puli obiektów, czy spowoduje to wywołanie GC?

Tablice będą stale tworzone w mojej pętli gry, więc muszę postarać się, aby była jak najbardziej efektywna. Próbuję utworzyć array pool jako taki, więc nie ma potrzeby dalszego tworzenia ich w grze. Jeśli jednak metoda zmiany rozmiaru robi to samo, nie ma sensu nie tylko tworzyć instancję nowej tablicy zamiast puli.

Dzięki za pomoc

+0

Może mógłbyś użyć 'List ', która jest w zasadzie automatyczną skalą o zmienionej wielkości, i domyślam się, że kiedy ją zredukujesz, to nie zmniejsza jej natychmiast ... mmh Muszę sprawdzić ... – digEmAll

+3

@digEmAll: 'List ' używa 'T []' wewnętrznie, ale zmienia rozmiar dla ciebie. Innymi słowy: utworzy nowe instancje. –

+0

Dzięki za sugestywę. Lista list przeszła mi przez myśl (jak używam tablic 2D), ale jest nieco bardziej skomplikowana dla mojej gry. – keyboardP

Odpowiedz

12

Array.Resize tak naprawdę nie zmienia oryginalnej tablicy - każdy, kto nadal ma do niej odniesienie, będzie mógł używać jej tak jak poprzednio. Dlatego nie ma możliwości optymalizacji. Szczerze mówiąc jest to źle nazwany metoda, IMO :(

Z docs:

Metoda ta przydziela nową tablicę z określonego rozmiaru, kopiuje elementy ze starej tablicy na nową, a następnie zastępuje starą tablicę z nowy.

Więc nie, to nie będzie można ponownie użyć oryginalnego pamięci lub coś podobnego. to jest po prostu tworząc płytkie kopię z innym rozmiarze.

+0

To dobra uwaga. Byłoby lepiej zaakceptować oryginał pod względem wartości i zwrócić nowy. Całe omijanie tutaj przez odniesienie mogłoby naprawdę zmylić młodszego programistę w tym przypadku. –

+0

Przeszukałem metodę w Reflectorze i po prostu nie czułem się dobrze, gdy zobaczyłem tworzoną nową tablicę. Sądzę, że będę musiał dojść do kompromisu w sprawie projektu i przeprowadzić kilka testów wydajności. Dziękuję za odpowiedź! – keyboardP

2

Tak, używając Array.Resize powoduje nowa tablica mają być przydzielone i stary, aby w końcu być zbierane (o ile nadal istnieją odniesienia do niego gdzieś).

Bardziej niskopoziomowy mechanizm zmiany wielkości tablic może w niektórych przypadkach dokonać niewielkiej optymalizacji (na przykład, gdy tablica jest zmniejszana lub dostępna jest pamięć zaraz po tablicy), ale implementacja .NET nie Zrób to.

1

Niejawnie tak.

Jawnie nie.

1

Każda alokacja zostanie ostatecznie oczyszczona przez GC, gdy nie będzie już żadnych odniesień, więc tak.

Jeśli chcesz uniknąć zmiany rozmiaru tablic, najlepszą rzeczą, jaką możesz zrobić, będzie uprzednie przydzielenie rozmiaru o wystarczająco dużym rozmiarze, aby uniknąć konieczności ponownego przydzielania. W takim przypadku możesz równie dobrze użyć klasy kolekcji o początkowej pojemności określonej w konstruktorze, takiej jak List.