2015-12-20 22 views
6

Próbuję zbudować mobilną grę bilardową w React Native, 0.17, dla doświadczenia i mam problemy z garbage collection. Obecnie mam dziesięć kręgów, które są renderowane jednocześnie, które odbijają się od ekranu. Jednak zużycie pamięci dla aplikacji rośnie z czasem i nie wiem, jak rozwiązać ten problem.React Native Memory Leakage Animation Issue

Wygląda na to, że był to problem typu React Native we wcześniejszych wersjach i zauważam, że z czasem spadły w pamięci, jak pokazano na wykresie, ale w znacznie większej aplikacji obawiam się, że może to być problem. Czy ktoś inny miał podobne problemy lub miał rozwiązania?

Odpowiedni kod jest tutaj i każda pomoc jest bardzo doceniana. Dziękuję Ci!

var test = React.createClass ({

getInitialState: function() { 
    var circs = []; 
    for (var i = 0; i < startCount; i++) { 
     circs.push({ 
      id: i, 
      x: 0, 
      y: 0, 
      vx: 2 + Math.random() * 2, 
      vy: 2 + Math.random() * 2, 
      dx: 0, 
      dy: 0, 
      cOb: new Animated.ValueXY({x: 0, y: 0}), 
     }); 
    } 

    return { 
     circles: circs, 
     stop: 1 
    }; 
}, 
stopCircle: function() { 
    this.state.stop = -1 * this.state.stop; 
    this.setState(this.state); 
}, 
componentDidMount: function() { 
    this.animateCircles(); 
}, 
animateCircles: function() { 
    this.triggerAnimation(this.animateCircles); 
}, 
triggerAnimation: function(ani) { 
    for (var i = 0; i < this.state.circles.length; i++) { 
      var cCircle = this.state.circles[i]; 
      if (cCircle.x * cCircle.x + cCircle.y * cCircle.y > DIST_TO_EDGE * DIST_TO_EDGE) { 
       var prevX = cCircle.x - cCircle.vx; 
       var prevY = cCircle.y - cCircle.vy; 
       var exitX = (1.5 * prevX + .5 * cCircle.x)/2; 
       var exitY = (1.5 * prevY + .5 * cCircle.y)/2; 
       cCircle.x = prevX; 
       cCircle.y = prevY; 

       var exitRad = Math.sqrt(exitX * exitX + exitY * exitY); 
       exitX = exitX * DIST_TO_EDGE/exitRad; 
       exitY = exitY * DIST_TO_EDGE/exitRad; 

       var twiceProjFactor = 2 * (exitX * cCircle.vx + exitY * cCircle.vy)/(DIST_TO_EDGE * DIST_TO_EDGE); 
       cCircle.vx = cCircle.vx - twiceProjFactor * exitX; 
       cCircle.vy = cCircle.vy - twiceProjFactor * exitY; 
       break; 
      } 
    } 
    if (this.state.stop == 1) { 
     for (var k = 0; k < this.state.circles.length; k++) { 
      this.state.circles[k].x += this.state.circles[k].vx; 
      this.state.circles[k].y += this.state.circles[k].vy; 
     } 
    } 
    this.setState(this.state); 
    var animateC = []; 
    for (var i = 0; i < this.state.circles.length; i++) { 
     var currCirc = this.state.circles[i]; 
     animateC.push(
      Animated.timing(currCirc.cOb, { 
       ...TIMING_CONFIG, 
       toValue: {x: currCirc.x, y: currCirc.y} 
     })); 
    } 
    Animated.parallel(
     animateC 
    ).start(ani); 
}, 
getStyle: function(which) { 
    return [ 
     styles.circle, 
     {transform: this.state.circles[which].cOb.getTranslateTransform()} 
    ]; 
}, 
render: function() { 
    return (
     <View style={styles.container}> 
      <View style={styles.edge}> 
      </View> 
      { 
       this.state.circles.map(function(c, i) { 
        return (
         <TouchableWithoutFeedback key={i} onPress={this.stopCircle}> 
          <Animated.View style={this.getStyle(i)} /> 
         </TouchableWithoutFeedback> 
        ); 
       }, this) 
      } 
     </View> 
    ); 
}, 

Pełne aplikacji można znaleźć na https://github.com/heliumsoule/React-Native-Pool jeśli chcesz uruchomić aplikację dla siebie.

Jeszcze raz dziękuję.

+0

this.setState (this.state); Co to oznacza? Nigdy wcześniej tego nie spotkałem. – Hasen

Odpowiedz

0

Ty Mam wiele zmiennych tymczasowych, zarówno proste liczby, jak i obiekty.Nie jestem całkowicie pewien, czy to się często kończy, czy też animacje obejmują wiele klatek. Jeśli to jest każda klatka, to zgaduję, że po prostu wykonujesz tona przydziałów e gromadzą się w czasie i powodują niewielkie pauzy po uruchomieniu wyrzucacza śmieci.

Aby zmniejszyć liczbę przydziałów, można przekonwertować zmienne tymczasowe na zmienne instancji, które można ponownie wykorzystać.

nie jestem na tyle z API animacji zaznajomieni wiedzieć czy istnieją jakieś optymalizacje ..

+0

James, Próbowałem twoją sugestię i stworzyłem zmienne instancji, zamiast ponownie przydzielać zmienne, ale użycie pamięci wciąż rośnie (bardziej stopniowo). – user1844067

+0

Cieszę się, że trochę pomogło. Pamiętaj, że tak długo, jak robisz alokacje, powinieneś oczekiwać, że pamięć powoli zacznie się podnosić, zanim zostanie uwolniona. Tak właśnie działają współczesne maszyny wirtualne JS. Być może nadszedł czas, aby zapoznać się z debugowaniem pamięci. Gdy aplikacja jest już uruchomiona, wykonaj kilka migawek. Możesz je porównać, aby zobaczyć, co rośnie w użyciu. – James

0

Masz dwie wirtualne maszyny, które wykonują zarówno zbieranie śmieci na własnych warunkach. JVM i JavaScript.

Ten artykuł może ci pomóc:

http://moduscreate.com/dynamic-memory-and-v8-with-javascript/

Ponadto, proponujemy wykomentuj tyle kodu, jak można zobaczyć efekt pamięci. Następnie skomentuj po trochu i zobacz, który kod przyspiesza wzrost zużycia pamięci.

+0

Michael, dzięki za twój artykuł. Nie wiem, czy istnieją dwie maszyny wirtualne, ponieważ JavaScript jest renderowany tutaj w strukturze React Native. Wiem, że głównym zużyciem pamięci jest metoda triggerAnimation, która nazywa się co TIMING_CONFIG, która właśnie określa czas między wywołaniami. Jednak nie wiem, jak zoptymalizować kod po sugestii Jamesa. – user1844067

+0

Nie jestem ekspertem od androidów, ale struktura React Native to Java, a mechanizm JS używany do wykonywania kodu React Native to V8. Twoja aplikacja wywołuje Java z JavaScript i odwrotnie. Co się stanie, jeśli program zostanie uruchomiony przez bardzo długi czas?Zarówno Java, jak i V8 mogą odroczyć niektóre z ich zbierania śmieci, dopóki urządzenie nie ma za mało pamięci lub proces używa swojego limitu. –