Zwalnianie tablicy ByteArray za pomocą Actionscript 3

91

Jak wymusić wyładowanie pliku ByteArrayz pamięci za pomocą ActionScript 3?

Próbowałem następujących rzeczy:

// First non-working solution
byteArray.length = 0;
byteArray = new ByteArray();

// Second non-working solution
for ( var i:int=0; i < byteArray.length; i++ ) {
    byteArray[i] = null;
}
Rann Lifshitz
źródło

Odpowiedzi:

35

Myślę, że nie masz się czym martwić. Jeśli System.totalMemoryspadnie, możesz się zrelaksować. Może to być system operacyjny, który nie odzyskuje nowo zwolnionej pamięci (w oczekiwaniu na następny raz, gdy Flash Player poprosi o więcej pamięci).

Spróbuj zrobić coś innego, co wymaga dużej ilości pamięci, a jestem pewien, że zauważysz, że pamięć przydzielona do Flash Playera zmniejszy się i zostanie zamiast tego użyta dla innego procesu.

Jak rozumiem, zarządzanie pamięcią w nowoczesnych systemach operacyjnych nie jest intuicyjne z punktu widzenia ilości przydzielonych każdemu procesowi, a nawet całkowitej przydzielonej ilości.

Kiedy używam mojego Maca przez 5 minut, 95% mojej 3 GB pamięci RAM jest używane i tak pozostanie, nigdy się nie wyłącza. Właśnie tak system operacyjny obsługuje pamięć.

Tak długo, jak nie jest to potrzebne w innym miejscu, nawet procesy, które zakończyły pracę, nadal mają przypisaną pamięć (może to na przykład przyspieszyć ich uruchomienie następnym razem).

Theo
źródło
25

(Nie jestem tego pewien, ale ...)

AS3 używa niedeterministycznego wyrzucania elementów bezużytecznych, co oznacza, że ​​pamięć pozbawiona odwołań zostanie zwolniona za każdym razem, gdy środowisko wykonawcze będzie na to odpowiadać (zazwyczaj nie, chyba że istnieje powód do uruchomienia, ponieważ jest to kosztowna operacja do wykonania). Jest to to samo podejście, które jest używane w większości nowoczesnych języków służących do zbierania elementów bezużytecznych (takich jak C # i Java).

Zakładając, że nie ma innych odniesień do pamięci wskazywanej przez byteArraylub elementów w samej tablicy, pamięć zostanie zwolniona w pewnym momencie po wyjściu z zakresu, w którym byteArrayjest zadeklarowana.

Możesz wymusić zbieranie śmieci, chociaż naprawdę nie powinieneś. Jeśli tak, zrób to tylko w celach testowych. Jeśli zrobisz to na produkcji, znacznie bardziej zaszkodzisz wydajności niż jej pomożesz.

Aby wymusić GC, spróbuj (tak, dwa razy):

flash.system.System.gc();
flash.system.System.gc();

Możesz przeczytać więcej tutaj .

Karl Seguin
źródło
20

Spójrz na ten artykuł

http://www.gskinner.com/blog/archives/2006/06/as3_resource_ma.html

IANA, programista skryptów akcji IANA, ale mam takie wrażenie, ponieważ moduł odśmiecania może nie działać, kiedy tego chcesz.

Stąd http://www.craftymind.com/2008/04/09/kick-starting-the-garbage-collector-in-actionscript-3-with-air/

Dlatego polecam wypróbowanie ich kodu kolekcji i sprawdzenie, czy to pomaga

private var gcCount:int;
private function startGCCycle():void{
    gcCount = 0;
    addEventListener(Event.ENTER_FRAME, doGC);
}
private function doGC(evt:Event):void{
    flash.system.System.gc();
    if(++gcCount > 1){
        removeEventListener(Event.ENTER_FRAME, doGC);
        setTimeout(lastGC, 40);
    }
}
private function lastGC():void{
    flash.system.System.gc();
}
Jax
źródło
16

Niestety, jeśli chodzi o zarządzanie pamięcią we Flash / actioncript, niewiele można zrobić. ActionScript został zaprojektowany tak, aby był łatwy w użyciu (więc nie chcieli, aby ludzie musieli martwić się o zarządzanie pamięcią)

Poniżej przedstawiono obejście problemu, zamiast tworzyć ByteArrayzmienną, spróbuj tego.

var byteObject:Object = new Object();

byteObject.byteArray = new ByteArray();

...

//Then when you are finished delete the variable from byteObject
delete byteObject.byteArray;

Gdzie byteArrayjest właściwość dynamiczna byteObject, można zwolnić przydzieloną jej pamięć.

Czerwony Baron
źródło
16

Myślę, że odpowiedziałeś na swoje własne pytanie.

System.totalMemorypodaje całkowitą ilość „używanej”, a nie przydzielonej pamięci. To prawda, że ​​aplikacja może używać tylko 20 MB, ale ma 5 MB, które jest wolne do przyszłych przydziałów.

Nie jestem pewien, czy dokumentacja Adobe rzuciłaby światło na sposób, w jaki zarządza pamięcią.

Czerwony Baron
źródło
11

Tak więc, jeśli załaduję powiedzmy 20 MB z MySQL, w Menedżerze zadań pamięć RAM dla aplikacji wzrośnie o około 25 MB. Następnie, kiedy zamykam połączenie i próbuję pozbyć się tablicy ByteArray, pamięć RAM nigdy się nie zwalnia. Jeśli jednak używam System.totalMemory, Flash Player pokazuje, że pamięć jest zwalniana, co nie ma miejsca.

Czy Flash Player robi coś takiego jak Java i rezerwuje miejsce na stercie i nie zwalnia go, dopóki aplikacja nie zostanie zamknięta?

Cóż, tak i nie, jak można przeczytać z niezliczonych postów na blogu, że GC w AVM2 jest optymistyczny i będzie działał na swój własny tajemniczy sposób. Działa więc trochę jak Java i próbuje zarezerwować miejsce na sterty. Jeśli jednak pozwolisz mu wystarczająco długo i zaczniesz wykonywać inne operacje, które zużywają znaczną ilość pamięci, zwolni to poprzednie miejsce. Możesz to zobaczyć, używając narzędzia profilującego przez noc, a niektóre testy działają na górze aplikacji.

Pedro
źródło
10

Tak więc, jeśli załaduję powiedzmy 20 MB z MySQL, w Menedżerze zadań pamięć RAM dla aplikacji wzrośnie o około 25 MB. Następnie, kiedy zamykam połączenie i próbuję pozbyć się tablicy ByteArray, pamięć RAM nigdy się nie zwalnia. Jeśli jednak używam System.totalMemory, Flash Player pokazuje, że pamięć jest zwalniana, co nie ma miejsca.

Gracz „uwalnia” pamięć. Jeśli zminimalizujesz okno i przywrócisz je, powinieneś zobaczyć, że pamięć jest teraz znacznie bliżej tego, co pokazuje System.totalMemory.

Możesz być także zainteresowany użyciem narzędzi do profilowania FlexBuilder, które mogą pokazać, czy naprawdę masz wycieki pamięci.


źródło