Skripty : Optimalizace paměti

Popis

Normálně FPDF komprimuje celé PDF v metodě _putpages() na samém konci generování PDF, to může vést k velkému dekomprimovanému PDF, které je uloženo v paměti. Tato úprava komprimuje každou hotovou stránku v _endpage() to sníží celkovou paměť při generování velkých souborů ve formátu PDF.

To test with minimal external influences, use a file such as the provided test.php. In one terminal window as root run top like so:

~> top -q | grep php

spusťte skript z příkazové řádky pomocí:

~> php -f test.php > with_opt.pdf

The "top" terminal window will scroll detailing memory usage of php (press q to exit). Then altering test.php to use the base class and running:

~> php -f test.php > no_opt.pdf

will show the original behaviour giving identical sized PDF files (no_opt.pdf and with_opt.pdf). On a 600 MHz dual processor typical results were that the optimised php code uses a maximum of 7.3 Megabytes wheareas the original uses 15 M. Both tests typically take 2 minutes 15 secs. Over very large reports (2000 pages +) the optimised version is very slightly slower by a few seconds.

Remark: there is also another script for memory optimisation.

Zdrojový kód

<?php
require('fpdf.php');

class PDF_Opt extends FPDF

{

function _putpages()
{
    $nb=$this->page;
    if(!empty($this->AliasNbPages))
    {
        // Nahradit počet stran
        for($n=1;$n<=$nb;$n++)
        {
            if($this->compress)
                $this->pages[$n]=gzcompress(str_replace($this->AliasNbPages,$nb,gzuncompress($this->pages[$n])));
            else
                $this->pages[$n]=str_replace($this->AliasNbPages,$nb,$this->pages[$n]);
        }
    }
    if($this->DefOrientation=='P')
    {
        $wPt=$this->DefPageFormat[0]*$this->k;
        $hPt=$this->DefPageFormat[1]*$this->k;
    }
    else
    {
        $wPt=$this->DefPageFormat[1]*$this->k;
        $hPt=$this->DefPageFormat[0]*$this->k;
    }
    $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
    for($n=1;$n<=$nb;$n++)
    {
        // Strana
        $this->_newobj();
        $this->_out('<</Type /Page');
        $this->_out('/Parent 1 0 R');
        if(isset($this->PageSizes[$n]))
            $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$this->PageSizes[$n][0],$this->PageSizes[$n][1]));
        $this->_out('/Resources 2 0 R');
        if(isset($this->PageLinks[$n]))
        {
            // Odkazy
            $annots='/Annots [';
            foreach($this->PageLinks[$n] as $pl)
            {
                $rect=sprintf('%.2F %.2F %.2F %.2F',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);
                $annots.='<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
                if(is_string($pl[4]))
                    $annots.='/A <</S /URI /URI '.$this->_textstring($pl[4]).'>>>>';
                else
                {
                    $l=$this->links[$pl[4]];
                    $h=isset($this->PageSizes[$l[0]]) ? $this->PageSizes[$l[0]][1] : $hPt;
                    $annots.=sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>',1+2*$l[0],$h-$l[1]*$this->k);
                }
            }
            $this->_out($annots.']');
        }
        $this->_out('/Contents '.($this->n+1).' 0 R>>');
        $this->_out('endobj');
        // Obsah stránky
        $p=$this->pages[$n];
        $this->_newobj();
        $this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
        $this->_putstream($p);
        $this->_out('endobj');
    }
    //Pages root
    $this->offsets[1]=strlen($this->buffer);
    $this->_out('1 0 obj');
    $this->_out('<</Type /Pages');
    $kids='/Kids [';
    for($i=0;$i<$nb;$i++)
        $kids.=(3+2*$i).' 0 R ';
    $this->_out($kids.']');
    $this->_out('/Count '.$nb);
    $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$wPt,$hPt));
    $this->_out('>>');
    $this->_out('endobj');
}

function _endpage()
{
    parent::_endpage();
    if($this->compress)
        $this->pages[$this->page] = gzcompress($this->pages[$this->page]);
}

}

?>


Příklad

Zde je příklad ukázkového skriptu:
<?php
ini_set('memory_limit','100M');
ini_set('max_execution_time',0);

require('memory_opt.php');


$pdf = new PDF_Opt();
$pdf->AddPage();
$pdf->SetFont('Arial','',9);

// generuje konstantní množství textu pro testování
$txt = '';
for($i=1; $i<200; $i++)
    $txt .= 'ashfsd kjsahkasjh akjhdsfjkh djshf sjkh ';
for($i=1; $i<1000; $i++)
    $pdf->Write(9,$txt);

$pdf->Output();
?>


Ukázka

fpdf-optimalizace-pameti.pdf

Download

fpdf-optimalizace-pameti.zip

Informace

Author: Philip Clarke
License: FPDF