2016-03-20 33 views
5

Obecnie pracuję nad niektórymi obliczeniami naukowymi, dla których moje podstawowe pętle obliczeniowe są wykonywane wielokrotnie z rekursywnymi wywołaniami, o ile co najmniej jeden parametr jest fałszywy.Ograniczone wywołania funkcji w nodejs w tej samej operacji?

Obecnie mój serwer nodejs zatrzymuje się na około 905 - 915. rekurencyjnym wywołaniu funkcji.

Dziwne jest to, że się nie psuje ani nie generuje żadnego błędu. Po prostu przestaje robić cokolwiek -> nie więcej logów itp.

Czy to jest pewne zachowanie ochronne z węzła, aby uniknąć przepełnienia?

Walczę z tym od kilku tygodni, próbując ograniczyć "pętle" za pomocą możliwie inteligentnego oprogramowania.

Dziękuję za pomoc & porady. Pozdrowienia Noa.

Zgodnie z wnioskiem I zapewnić pewną abstrakcję mojego aktualnego kodu

Mam nadzieję, że to pomaga. Nie mogę umieścić tutaj mojego oryginalnego kodu, ponieważ składa się on z ponad 1,5 tysiąca linii - tam dużo do sprawdzenia. Ale poniższy przykład obejmuje logikę podstawową za wywołaniem rekursywnym.

// Contains objects which contain an array 
// which represents the amount of the ex_obj terms 
var amount = { 
    a:[10,10], 
    b:[7.5,7.5], 
    c:[2.5,2.5,2.5,2.5] 
} 

// Contains objects, which contain an array of other objects 
// that represent some selection 
// Each object in an array consists of different values per attribute per 1 amount 
var ex_obj = { 
    a: [ 
    {aa: 1.41, ab: 0.143, ac: 0.5}, 
    {aa: 1.30, ab: 1.43, ac: 0.42} 
    ], 
    b: [ 
    {aa: 0.32, ab: 5.54, ac: 1.3}, 
    {aa: 0.33, ab: 4.49, ac: 2.5} 
    ], 
    c: [ 
    {aa: 0.54, ab: 1.4, ac: 3.5}, 
    {aa: 0.39, ab: 1.434, ac: 3.91}, 
    {aa: 0.231, ab: 1.44324, ac: 2.91}, 
    {aa: 0.659, ab: 1.554, ac: 3.9124}, 
    ] 
} 

// Here we have an object that represents 
// the "to be" state which should be achieved 
var should_be ={ 
    aa: 14.534, 
    ab: 3.43, 
    ac: 5.534 
} 

function calculate(){ 
    // Now we want to mulitply the amount object values with 
    // the ex_obj values 

    for(let prop in ex_obj){ 
    for(let i = 0, i < ex_obj[prop].length, i++){ 
     for(let propa in ex_obj[prop][i]){ 
     // here every aa,ab,ac gets mulitplied with the 
     // contains of the amount obj for the matching 
     // propertyname 
     } 
    } 
    } 

    // the next step is to check if the sum of all ex_obj property 
    // child values per aa, ab and ac match the should_be propertie values 

    // if everything is above the should_be and not too high then the 
    // programm can stop here and print out the amount obj. 

    // if the sum of the ex_obj properties is too little 
    // compared to the should_be obj 
    // we need to check which property is too little 
    // e.g. aa is too little 
    // then we check where aa in the ex_obj per 1 value is 
    // the highest 
    // then we increment the matching amount property child 
    // and start calculate() again 

    // same procedure for - if something is too much 
} 
+1

Węzeł powoduje względną prostotę zastępowania wywołań rekurencyjnych za pomocą wywołań asynchronicznych i całkowitego unikania wzrostu stosu. Podaj więcej szczegółów i przykładowy kod ... – Amit

+0

Wątpię, czy możemy Ci pomóc bez wyświetlania kodu. Przepełnienie stosu bardzo dobrze radzi sobie z pytaniami, które zawierają prawdziwy kod, a nie tak dobrze z pytaniami koncepcyjnymi bez kodu. – jfriend00

+0

Mam zaktualizowane moje pytanie –

Odpowiedz

5

Ponieważ Twój kod nie jest kompletny, trudno powiedzieć dokładnie, co się stało. Jeśli przekroczysz limit stosu wywołań węzła, otrzymasz wyjątek, chociaż 1000 rekursji zwykle nie stanowi problemu.

Możliwe, że dusisz pętlę zdarzeń Node.js. Zamiast bezpośrednio wywołanie funkcji rekurencyjnej, można spróbować zadzwonić

process.nextTick(function(){calculate()}) 
+0

Dziękuję, że wypróbuję tę metodę już dziś! –

+0

To nie zatrzymuje już wykonywania funkcji, ale kończy się nieskończoną pętlą - co może być powodem, dla którego domyślne wywołanie funkcji zostało zatrzymane po kilku pętlach bez żadnego innego wzorca. –

+0

Cieszę się, że to mogło Cię skierować w dobrym kierunku –

1

To nie jest zaskoczony, że bezpośrednie wywołanie rekurencyjne spowoduje przepełnienie stosu, jednak wydaje się, że częste wywołania funkcji dostanie węzeł rozłączyć (BTW nie wiem, dlaczego tak się dzieje :()

Na przykład poniższy skrypt zostanie zamrożony na około 4k ~ 5k pętli na moim komputerze z procesorem 1,6 GHz i 3,3 GiB pamięci, a węzeł ciągle przełyka moją dostępną pamięć

var i = 0; 
function cal() { 
    console.log(++i); 
    process.nextTick(cal); 
} 
cal(); 

Ale jeśli zmieniłem process.nextTick(cal); do setTimeout(cal, 0);, wszystko działa poprawnie.

Jeśli chodzi o twoje pytanie, myślę, że możesz użyć w swoim skrypcie czegoś w rodzaju setTimeout(calculate, 100), aby zapobiec rekurencyjnemu wywołaniu i odroczyć je nieco.

+0

Proces.nextTick zrobił to dla mnie.Chociaż teraz kończę w niekończącej się pętli - ale może to być błąd programistyczny na końcu. :) –