2015-12-20 10 views
6

Ich versuche, ein Handy-Pool-Spiel in React Native, 0.17, für die Erfahrung zu erstellen und habe Probleme mit der Garbage Collection. Im Moment habe ich zehn Kreise, die gleichzeitig gerendert werden und auf dem Bildschirm herumspringen. Der Speicherverbrauch für die Anwendung nimmt jedoch im Laufe der Zeit zu und ich weiß nicht, wie ich dieses Problem angehen soll.Native Memory Leakage-Animation reagieren Problem

Es scheint, dass dies ein React Native Problem in früheren Versionen war und ich merke, fällt im Laufe der Zeit wie in der Grafik hier gezeigt, aber in einer viel größeren Anwendung, ich bin besorgt, dass dies Problem sein kann. Hat jemand anderes ähnliche Probleme oder Lösungen?

Der entsprechende Code ist hier und jede Hilfe wird sehr geschätzt. Vielen Dank!

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> 
    ); 
}, 

Die vollständige Anwendung kann bei https://github.com/heliumsoule/React-Native-Pool gefunden werden, wenn Sie für sich selbst die Anwendung ausgeführt werden soll.

Sie wieder danken.

+0

this.setState (this.state); Was macht das? Ich bin nie zuvor darauf gestoßen. – Hasen

Antwort

0

Sie Ich habe eine Menge temporärer Variablen, sowohl einfache Zahlen als auch Objekte, ich bin mir nicht ganz sicher, ob dies häufig passiert oder ob die Animationen mehrere Frames umfassen. Wenn es sich um jeden Frame handelt, würde ich annehmen, dass Sie nur einen ausführen Tonnen von Zuweisungen Sie bauen sich im Laufe der Zeit auf und verursachen kleine Pausen, wenn der Garbage Collector ausgelöst wird.

Um die Anzahl der Zuweisungen zu reduzieren, könnten Sie die temporären Variablen in Instanzvariablen konvertieren, die wiederverwendet werden können.

Ich bin nicht vertraut genug mit den Animations APIs zu wissen, ob es irgendwelche Optimierungen sind ..

+0

James, ich habe Ihren Vorschlag ausprobiert und Instanzvariablen erstellt, anstatt die Variablen neu zuzuweisen, aber die Speicherauslastung steigt immer noch (allerdings langsamer). – user1844067

+0

Froh das half ein bisschen. Denken Sie daran, dass Sie, solange Sie Zuweisungen vornehmen, erwarten sollten, dass der Arbeitsspeicher langsam wächst, bevor er freigegeben wird. So funktionieren moderne JS-VMs. Es könnte Zeit sein, sich mit dem Debuggen des Speichers vertraut zu machen. Sobald deine App läuft, nimm ein paar Schnappschüsse. Sie können sie vergleichen, um zu sehen, wo die Nutzung wächst. – James

0

Sie haben zwei virtuelle Maschinen, die sowohl die Garbage Collection zu ihren eigenen Bedingungen durchzuführen. Die JVM und JavaScript.

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

Auch ich schlage vor, Sie so viel Code kommentieren, wie Sie und die Wirkung auf das Gedächtnis sehen:

Sie aus diesem Artikel könnte helfen. Dann kommentieren Sie jeweils etwas und sehen Sie, welcher Code den Speicherverbrauch am schnellsten ansteigen lässt.

+0

Michael, danke für deinen Artikel. Ich weiß nicht, ob es zwei VMs gibt, weil JavaScript hier in einem React Native Framework gerendert wird. Ich weiß, dass der Hauptspeicherverbrauch mit der Methode triggerAnimation erfolgt, die bei jeder TIMING_CONFIG aufgerufen wird, die nur die Zeit zwischen den Aufrufen angibt. Ich weiß jedoch nicht, wie ich den Code nach James 'Vorschlag weiter optimieren kann. – user1844067

+0

Ich bin kein Android-Experte, aber das React Native-Framework ist Java und die JS-Engine zum Ausführen des React Native-Code ist V8. Ihre App ruft Java von JavaScript an und umgekehrt. Was passiert, wenn Sie das Programm für eine sehr lange Zeit laufen lassen?Sowohl Java als auch V8 verzögern möglicherweise einige ihrer Garbage Collection, bis das Gerät nicht mehr genügend Arbeitsspeicher zur Verfügung hat oder der Prozess sein Limit verwendet. –