2016-03-16 18 views
6

Abbiamo problemi con perdita di memoria durante il caricamento Dottrina nei nostri test PHPUnitSymfony e PHPUnit perdita di memoria

di partenza per la documentazione di Symfony: http://symfony.com/doc/2.7/cookbook/testing/doctrine.html che abbiamo scritto questo test:

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; 

class memoryleakTest extends KernelTestCase 
{ 
    private $em; 

    protected function setUp() 
    { 
     self::bootKernel(); 

     $this->em = static::$kernel->getContainer() 
      ->get('doctrine') 
      ->getManager(); 
    } 

    protected function tearDown() 
    { 
     parent::tearDown(); 

     $this->em->close(); 
    } 

    function testEEE1() { 
    } 
    function testEEE2() { 
    } 
    function testEEE3() { 
    } 
    function testEEE4() { 
    } 
    function testEEE5() { 
    } 
    function testEEE6() { 
    } 
    function testEEE7() { 
    } 
    function testEEE8() { 
    } 
    function testEEE9() { 
    } 
    function testEEE10() { 
    } 
    function testEEE11() { 
    } 
    function testEEE12() { 
    } 
    function testEEE13() { 
    } 
    function testEEE14() { 
    } 
    function testEEE15() { 
    } 
    function testEEE16() { 
    } 
} 

abbiamo ottenuto questo risultato (php_memory_usage tra parentesi):

testEEE1: . (42M) 
testEEE2: . (42.7M) 
testEEE3: . (43.3M) 
testEEE4: . (44M) 
testEEE5: . (44.8M) 
testEEE6: . (45.5M) 
testEEE7: . (46.1M) 
testEEE8: . (46.8M) 
testEEE9: . (47.4M) 
testEEE10: . (48.1M) 
testEEE11: . (48.7M) 
testEEE12: . (49.4M) 
testEEE13: . (50.1M) 
testEEE14: . (50.7M) 
testEEE15: . (51.4M) 
testEEE16: . (52M) 

Se togliamo il carico dottrina manager in setup, abbiamo ottenuto (32,7M) per ogni prova

È un modo corretto di scaricare la dottrina dopo ogni test nella funzione di teardown?

+0

mi sembra a posto. hai comunque qualche roba arricciata? che mi ha causato perdite di memoria catastrofiche – DevDonkey

+0

@DevDonkey nient'altro che esattamente nulla nel test: nessun arricciamento, nessun accesso al database ... semplicemente chiamando la dottrina senza usarla (quindi forse carica tutti i metadati). Sembra che tutte queste informazioni caricate in memoria non vengano rilasciate, anche con un kernel-> shutdown() – Cedric

risposta

3

La soluzione completa come state trovate qui: https://github.com/symfony/symfony/issues/18236

Per ogni servizio utilizzato nel test PHPUnit, è necessario liberarlo assegnando nulla alla variabile se vuoi che il garbage collector liberi memoria.

protected function tearDown() 
{ 
    parent::tearDown(); 

    $this->em->close(); 

    $this->em=null; 

    gc_collect_cycles(); 
} 
+1

Non penso che il comando 'gc_collect_cycles();' sia manualmente molto importante. Ad ogni modo, bel colpo! –

+1

@SmoothAf Sono d'accordo con te, il punto qui è $ this-> em = null – Cedric

0

Non è una perdita di memoria, solo un flusso normale perché si avvia il kernel 16 volte.

Basta provare ad aggiungere gc_collect_cycles(); nel metodo tearDown() e vedrete che l'utilizzo della memoria è diminuito. In alternativa è possibile impostare memory_limit a 50M e vedrete che gc non funziona automaticamente

+2

gc_collect_cycles(); in tearDown non cambia nulla, esattamente lo stesso uso della memoria con o senza di esso. memory_limit è quello che ho fatto fino ad ora, ma in realtà, i miei test reali utilizza ora più di memoria 4G! Quindi non è più una soluzione – Cedric

1

Per renderlo ancora più facile per voi, si può avere un BaseTestCase.php con una funzione di teardown e mettere questo all'interno:

// Remove properties defined during the test 
    $refl = new \ReflectionObject($this); 
    foreach ($refl->getProperties() as $prop) { 
     if (!$prop->isStatic() && 0 !== strpos($prop->getDeclaringClass()->getName(), 'PHPUnit_')) { 
      $prop->setAccessible(true); 
      $prop->setValue($this, null); 
     } 
    } 

Quel pezzo di codice vi salverà da qualche mal di testa :)