2015-12-20 49 views
6

Sto provando a creare un gioco pool mobile in React Native, 0.17, per esperienza e sto incontrando problemi relativi alla garbage collection. In questo momento ho dieci cerchi che vengono resi simultaneamente che rimbalzano sullo schermo. Tuttavia, il consumo di memoria per l'applicazione sta aumentando nel tempo e non so come risolvere questo problema.Problema di emissione di memoria Native React

Sembra che questo fosse un problema React Native nelle versioni precedenti e noto che cade in memoria nel tempo come mostrato nel grafico qui, ma in un'applicazione molto più grande, sono preoccupato che questo potrebbe essere un problema. Qualcun altro ha avuto problemi simili o soluzioni?

Il codice pertinente è qui e qualsiasi aiuto è molto apprezzato. Grazie!

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

La piena applicazione può essere trovato alla https://github.com/heliumsoule/React-Native-Pool se si desidera eseguire l'applicazione per voi stessi.

Grazie ancora.

+0

this.setState (this.state); Cosa fa? Non l'ho mai incontrato prima. – Hasen

risposta

0

È Ho un sacco di variabili temporanee, sia numeri semplici che oggetti.Non sono del tutto sicuro se questo finisce per essere colpito di frequente o se le animazioni si estendono su più fotogrammi. Se è ogni fotogramma, direi che stai solo eseguendo un tonnellate di allocazioni Si accumulano nel tempo e causano piccole pause quando viene attivato il garbage collector.

Per ridurre il numero di allocazioni, è possibile convertire le variabili temporanee in variabili di istanza, che possono essere riutilizzate.

io non sono abbastanza con le API di animazione familiare per sapere se ci sono eventuali ottimizzazioni lì ..

+0

James, ho provato il tuo suggerimento e creato variabili di istanza piuttosto che riallocare le variabili, ma l'utilizzo della memoria continua a salire (più gradualmente però). – user1844067

+0

Felice che mi ha aiutato un po '. Tieni presente che finché esegui allocazioni, dovresti aspettarti che la memoria rallenti lentamente prima di essere liberata. Questo è solo il modo in cui funzionano le moderne macchine virtuali JS. Potrebbe essere il momento di familiarizzare con il debug della memoria. Una volta che la tua app è in esecuzione, fai un paio di istantanee. Puoi confrontarli per vedere cosa sta aumentando l'utilizzo. – James

0

avete due macchine virtuali che entrambi eseguire la raccolta dei rifiuti alle loro condizioni. La JVM e JavaScript.

Questo articolo potrebbe aiutarvi:

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

Inoltre, vi consiglio di commento fuori tanto codice come si può e vedere l'effetto sulla memoria. Quindi commenta un po 'alla volta e vedi qual è il codice che fa aumentare più rapidamente il consumo di memoria.

+0

Michael, grazie per il tuo articolo. Non so se ci sono due VM perché JavaScript è stato riprodotto qui in un framework React Native. So che il consumo di memoria principale è con il metodo triggerAnimation che viene chiamato ogni TIMING_CONFIG, che specifica solo l'intervallo di tempo tra le chiamate. Tuttavia, non so come ottimizzare ulteriormente il codice dopo il suggerimento di James. – user1844067

+0

Non sono un esperto di Android, ma il framework React Native è Java e il motore JS utilizzato per eseguire il codice React Native è V8. La tua app chiama Java da JavaScript e viceversa. Cosa succede se il programma viene eseguito per un tempo molto lungo?Sia Java che V8 potrebbero rimandare parte della loro garbage collection fino a quando il dispositivo non ha memoria o il processo sta usando il limite. –