2016-03-16 27 views
6

Chúng tôi có vấn đề với bộ nhớ bị rò rỉ khi tải Học thuyết trong các thử nghiệm phpunit của chúng tôiSymfony và PHPUnit bộ nhớ bị rò rỉ

Bắt đầu cho tài liệu Symfony của: http://symfony.com/doc/2.7/cookbook/testing/doctrine.html chúng tôi đã viết bài kiểm tra này:

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() { 
    } 
} 

chúng tôi đã nhận kết quả này (php_memory_usage giữa dấu ngoặc đơn):

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) 

Nếu chúng tôi xóa trình quản lý học thuyết tải trong thiết lập, chúng tôi có (32,7M) cho mỗi bài kiểm tra

Đây có phải là cách thích hợp để dỡ bỏ học thuyết sau mỗi bài kiểm tra trong chức năng teardown không?

+0

có vẻ ổn với tôi. bạn có bất kỳ thứ curl nào trong đó không? khiến tôi bị rò rỉ bộ nhớ thảm khốc – DevDonkey

+0

@DevDonkey không có gì chính xác hơn trong bài kiểm tra: không có curl, không truy cập DB ... chỉ cần gọi giáo lý mà không cần sử dụng nó (vì vậy có lẽ nó tải tất cả siêu dữ liệu). Dường như tất cả thông tin này được nạp trong bộ nhớ sẽ không được giải phóng, ngay cả với kernel-> shutdown() – Cedric

Trả lời

3

Các giải pháp đầy đủ như được tìm thấy ở đây: https://github.com/symfony/symfony/issues/18236

Đối với mỗi dịch vụ được sử dụng trong các thử nghiệm phpunit, bạn phải giải phóng nó bằng cách gán null cho biến nếu bạn muốn bộ thu gom rác để giải phóng bộ nhớ.

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

    $this->em->close(); 

    $this->em=null; 

    gc_collect_cycles(); 
} 
+1

Tôi không nghĩ rằng caling 'gc_collect_cycles();' bằng tay là thực sự quan trọng. Dù sao, bắn tốt đẹp! –

+1

@SmoothAf Tôi đồng ý với bạn, điểm ở đây là $ this-> em = null – Cedric

0

Nó không phải là một rò rỉ bộ nhớ, chỉ là một dòng chảy bình thường bởi vì bạn khởi động hạt nhân 16 lần.

Chỉ cần thử thêm gc_collect_cycles(); vào phương thức tearDown() của bạn và bạn sẽ thấy mức sử dụng bộ nhớ đó giảm. Hoặc bạn có thể thiết lập memory_limit đến 50M và bạn sẽ thấy gc mà nó hoạt động tự động

+2

gc_collect_cycles(); trong tearDown không thay đổi bất cứ điều gì, chính xác cùng một cách sử dụng bộ nhớ có hoặc không có nó. memory_limit là những gì tôi đã làm cho đến bây giờ, nhưng trên thực tế, các thử nghiệm thực sự của tôi sử dụng bộ nhớ hiện nay nhiều hơn 4G! Vì vậy, nó không phải là một giải pháp nữa – Cedric

1

Để làm điều này dễ dàng hơn cho bạn, bạn có thể có một BaseTestCase.php với một chức năng teardown và đặt bên này:

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

Đó đoạn mã sẽ giúp bạn tiết kiệm từ một số nhức đầu :)