2013-03-04 11 views
10

wpadłem właśnie test:Czy limit stosu to 5287 w zmiennej AS3 lub predefiniowany?

function overflow(stack:int = 0):void 
{ 
    if(stack < 5290) 
    { 
     trace(stack); 
     overflow(stack + 1); 
    } 
} 

overflow(); 

To zawsze zgłasza błąd StackOverflow po 5287 połączeń.

Błąd # 1023: Wystąpiło przepełnienie stosu.

Czy ta zmienna jest limitowana (w zależności od specyfikacji maszyny, środowiska itp.) Lub czy jest gdzieś zdefiniowana wartość płaska? Jeśli zmienię instrukcję if na mniej niż 5287, nie otrzymam błędu.

+1

Niektóre informacje na ten temat: http://jacksondunstan.com/articles/949 –

+2

Interesujące. W programie Flash Professional również i ja pomyłkę po 5287. Jednak po uruchomieniu projektu AIR z FlashDevelop, stos osiąga zaledwie 12 000 zanim FlashTevelop 'Trace Overflow' zostanie wyrzucony i bez śladu stos będzie się mylił tuż przed 14,080. – TheDarkIn1978

+0

Przypuszczam, że najcenniejszą rzeczą jest to, jaki byłby dolny limit na tym poziomie. – Marty

Odpowiedz

2

Oczywiście jest zmienny.Ponieważ wszystkie obliczenia, które naprawdę robisz, znajdują się w stosie (kody raportów demontażu pokazują instrukcje pushbyte i inne rzeczy, które pracują ze stosem, jako arytmetyczne nieoperacyjne), ta wartość informuje tylko o tym, ile kontekstów funkcji można umieścić w stosie, dopóki nie przepełni się .

Zdecydowałem się uruchomić kilka testów dla progów rekursji w oparciu o this article, które zostały wymienione w komentarzu Barisa. Wyniki były dość kłopotliwe. Środowisko testowe: FlashDevelop 3.3.4 RTM, Flash player debugger 10.1.53.64, tryb kompilacji flash: release. Tryb "Debugowanie" nie zmieniał liczby kardynalnie, również to sprawdzał.

Locals number  Iterations (static int)  Iterations (Math.random()) 
0     5306       
1     4864       4856 
2     4850       4471 
3     4474       4149 
4     4153       3870 
5     3871       3868 
6     3869       3621 
7     3620       3404 
8     3403       3217 
        3214 
10    3214       3042 
11    3042       3045 
10 mixed   3042  1 value was assigned Math.random() and 9 - static int 
10 advancedRandom 2890  1 value was assigned a custom random with 1 parameter 

Uwaga: wszystkie te wartości zmieniają się w granicach dziesięciu przedziałów między kolejnymi wykonaniami. "Static int" i "Math.random()" są oznaczeniami tego, co jest przypisane do locals w rekursywnie nazywanej funkcji. To jednak prowadzi mnie przyjąć następujące: funkcja

  1. tym wzywa do funkcji rekurencyjnej dodaje funkcjonować kontekst
  2. pamięci dla mieszkańców jest przypisany wraz z jej rodzaju, w kawałki więcej niż 8 bajtów, ponieważ dodanie lokalnego nie zawsze zmniejsza limit rekurencji
  3. Dodanie więcej niż jednego połączenia do określonej funkcji nie dodaje więcej pamięci do kontekstu funkcji
  4. "Fragment pamięci" ma najczęściej 16 bajtów długości, ponieważ ta wartość to 2^N, dodanie jednego int lub Number local nie zawsze zmniejsza rekurencję, a jest to więcej niż 8, jako surowa wartość Zmienna liczbowa przyjmuje 8 bajtów i jest zmiennoprzecinkową podwójną precyzją.
  5. Zakładając, że nr 4 jest poprawny, najlepsza wartość dla rozmiaru kontekstu funkcji wynosi 172 bajty, a całkowity rozmiar stosu to 912632 bajty. To w dużej mierze potwierdza moje początkowe założenie, że rozmiar stosu wynosi w rzeczywistości 1 megabajt w Flash 10. Flash 11 pokazał mi nieco większą liczbę, gdy próbowałem otworzyć testowy SWF w jego debugerze, ale nie przeprowadziłem z nim szerokich testów.
+0

Jeśli więc czas nie jest czynnikiem, w jaki sposób ktoś przeprowadza dokładnie ten sam test i otrzymuje inną wartość? – Marty

+0

Czas może być czynnikiem, ponieważ są zdarzenia, które Flash strzela, które również zużywają część stosu. Wydaje się, że czas jest drobnym problemem, większa część pochodzi z innych źródeł, najprawdopodobniej z lokalnych i funkcjonalnych łączy. Odpowiedź Mimima jasno pokazuje, że linki funkcyjne odgrywają pewną rolę, moje odpowiedzi, że miejscowi również odgrywają pewną rolę, a także dają wskazówkę na temat linków funkcyjnych również odgrywających rolę. – Vesper

0

Musst być zmienny! Właśnie skompilowałem twoją próbkę i dostaję do 5274 przed przepełnieniem stosu.

@baris ów dla mxmlc kompilatora

+1 dla przepełnienie stosu pytanie ^^

2

Hm, to jest interesujące. Spojrzałem na link, który dał Barış. Wygląda na to, że może być ze "złożonością metody", ale nie jestem pewien, jak ją przetestować. Używam Flash CS5, publikowanie dla Flash Player 10, Actionscript 3 (oczywiście).

oryginalny:

function overflow(stack:int = 0):void { 
    if(stack < 5290){ 
     trace(stack); 
     overflow(stack + 1); 
    } 
} 
// gives 5287 

Teraz dodanie jednego Math.random() zadzwonić do przepełnienia() metoda:

function overflow(stack:int = 0):void { 
    Math.random(); 
    if(stack < 5290){ 
     trace(stack); 
     overflow(stack + 1); 
    } 
} 
// gives 4837 

Dodawanie wielu Math.random() wywołuje żadnej różnicy, ani zapisuje go w zmiennej lokalnej lub dodaje inny parametr do metody overflow() w celu przeniesienia tej losowej wygenerowanej wartości do wartości domyślnej

function overflow(stack:int = 0):void { 
    Math.random(); 
    Math.random(); 
    if(stack < 5290){ 
     trace(stack); 
     overflow(stack + 1); 
    } 
} 
// still gives 4837 

W tym momencie Próbowałem różnych połączeń matematyczne, takie jak:

// just the change to that 1 line: 
Math.pow() // gives 4457 
Math.random(), Math.sqrt(), Math.tan(), Math.log() // gives 4837 

Co ciekawe, to nie wydaje się ważne, co można przejść do klasy Math, ale pozostaje na stałym poziomie:

Math.sqrt(5) vs Math.sqrt(Math.random()) // gives 4837 
Math.tan(5) vs Math.tan(Math.random()) // gives 4837 
Math.pow(5, 7) vs Math.pow(Math.random(), Math.random()) // 4457 

Aż przykuty 3 z nich:

Math.tan(Math.log(Math.random())); // gives 4457 

to wygląda jak dwa Math wymaga od tej „grupy” jest „równy” do jednego Math.pow() zadzwonić? = B Mieszanie Math.pow() i coś innego nie wydaje się, aby zmniejszyć wartość mimo:

Math.pow(Math.random(), Math.random()); // gives 4457 

Jednak łączenia dwóch Math.pow() 's

Math.pow(Math.pow(Math.random(), Math.random()), Math.random()); // 4133 

mogę iść w kółko, ale zastanawiam się, czy istnieje jakiś wzór:

Results: 5287, 4837, 4457, 4133 
Differences: 450 380 324 
+0

To w połączeniu z faktem, że drugi odbierający uzyskał niższy wynik w tym samym teście, sprawia, że ​​myślę, że to czas. Ma to największe znaczenie, gdy uzyskuje się różne wyniki na maszynach o różnej wydajności, a także w przypadku bardziej złożonych przypadków testowych. – Marty

+0

@MartyWallace Bez względu na czas, tylko kontekst. Sprawdź poniżej swoją odpowiedź. – Vesper

+0

Wzory są grafiki C/X, gdzie C jest stałą (dostępny rozmiar stosu), a X to rozmiar kontekstu funkcji, który wydaje się dość złożony. – Vesper

Powiązane problemy