Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clear memory being used by PHP

I'm running into an interesting problem. I'm using PHPUnit, and my tests take more memory every single time I run them. Ie...

2.25 MB

2.5 MB

3.0 MB

3.5 MB .......

Does anyone know how to clear out the memory that is being consumed, and can anyone advise me on exploring this in depth? The immediate problem is that some of my larger tests are running out of memory, and simply continuing to increase the max memory allotment in PHP isn't good enough...I need to know why a PHPUnit test running from command line would have memory usage which "sticks around" between runs.

like image 700
Calvin Froedge Avatar asked Nov 24 '12 01:11

Calvin Froedge


2 Answers

The memory increase has three to four reasons:

1) PHPUnit collects code coverage data

There is nothing you can do about this except turn off code coverage.

2) PHPUnit caches file tokens for code coverage

You can use <phpunit cacheTokens="false"> in your PHPUnit xml. See the note about this in http://phpunit.de/manual/current/en/installation.html#installing.upgrading

3) PHPUnit doesn't properly clean up after itself

In its current implementation it keeps the test cases around because thats where the result data is stored. In the future this will be changed to be more efficent but for now it's how things works.

4) Leading to "4": You need to clean up after your self too

Since the TestCase instances are keep around your member variables are kept around too.

Meaning you can save a lot of memory by using

public function tearDown() {
    unset($this->whatever);
}

but doing so is very tedious.

My suggestion is to have a base test class for all your TestCases and use this:

class MyBaseTest extends \PHPUnit_Framework_TestCase {

    protected function tearDown()
    {
        $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);
            }
        }
    }
}

This will clean up after you in a nice, automated way.

(props for the snippet go to: http://kriswallsmith.net/post/18029585104/faster-phpunit)


PHPUnit can't do this in a backwards compatible way that wouldn't break people's projects so you have to add it for you own :)

like image 199
edorian Avatar answered Oct 01 '22 17:10

edorian


Calvin, as per discussed in the chat, it was due to missing reset features.

When testing, we must ensure that the test environment is consistent so that we're able to get accurate results. Computing is Input/Output and hence we should use Fixtures in PHPUnit to reset storage to prevent "memory leaks" like these.

like image 43
mauris Avatar answered Oct 01 '22 18:10

mauris