Creating 100 - 200k PDFs through Magento / Zend_Pdf results in memory leak

83 Views Asked by At

Pleaes note

I know that it would be easier to use another PHP Pdf Library, but for now the PDFs are modified Invoices from Magento - and I need the complete order / invoice objects, so please bear with me that there is currently no other option but to use Zend_Pdf


I've tried for three long days now, but it seems that Zend_Pdf through Zend_Pdf_ElementFactory leaks memory.

Every time I run this code (runs in a foreach loop):

protected function _createInvoices($from, $to) 
{
 $invoiceCollection = Mage::getModel('sales/order_invoice')->getCollection()
        ->addFieldToFilter('created_at', array('from' => $from, 'to' => $to));

    $invoiceCollection->setPageSize(self::PAGE_SIZE);
    $lastPage = $invoiceCollection->getLastPageNumber();
    $currentPage = 1;

    // counting created invoices
    $id = 1;

    $path = $this->_getPath();

    ...

    do {
        $invoiceCollection->setCurPage($currentPage);
        $invoiceCollection->load();

        ...

        foreach($invoiceCollection as $invoice) {
            // this is a custom class that extends Mage_Sales_Model_Order_Pdf_Invoice
            $pdfModel = Mage::getModel('foo_bar/magic');

            $pdf = $pdfModel->getPdf(array($invoice));

            $pdf->save($pathName . '.pdf');

            $id++;
        }
        ...

        $currentPage++;
        $invoiceCollection->clear();
    } while ($currentPage <= $lastPage);
}

Using memory_get_usage() right before and after the above code, the usage goes up roughly 20 kbytes for the 500 or so items, but it is in no way linear:

25250040 before getPdf
25431976 after and save getPdf
25433736 before getPdf
25564104 after and save getPdf
25565864 before getPdf
26625368 after and save getPdf
26627128 before getPdf
26748576 after and save getPdf
26750344 before getPdf
26929712 after and save getPdf
26931472 before getPdf
27045440 after and save getPdf
27047200 before getPdf
27273648 after and save getPdf
27275440 before getPdf
27410240 after and save getPdf

Now I've tried using unset($pdf).

I've also went into the Zend_Pdf class and build a __destruct method to set all protected variables to null as well as unsetting them.

After much debugging and using XGui to see the memory usage:

Notice the Zend_Pdf_ElementFactory(_Proxy)::listModifiedObjects

There is a method in Zend_Pdf_ElementFactory which purpose is as stated:

* PDF element factory.
* Responsibility is to log PDF changes

and in line 365 the public function listModifiedObjects is:

/**
 * Enumerate modified objects.
 * Returns array of Zend_Pdf_UpdateInfoContainer
 *
 * @param Zend_Pdf_ElementFactory_Interface $rootFactory
 * @return array
 */
public function listModifiedObjects($rootFactory = null)
{
...

    foreach ($this->_attachedFactories as $factory) {
        $result += $factory->listModifiedObjects($rootFactory);
    }

    return $result;
}

This foreach recursively calls itself for every attached factories... my guess is that it is somewhere here that my memory goes wasted...

Please if you have some clues or directions to point me to how the Zend_Pdf_ElementFactory works or how I could clear it (there is a close method, but as far as i can see it isn't called anywhere), I would greatly appreciate it!

Thanks a lot for helping out :-)

PS: If anything is unclear, i'm happy to provide more details / information

0

There are 0 best solutions below