News

phpdocx 3.5 General Performance Benchmark

  • 10 / 28 / 2013

We would like to start by saying that, generally speaking, PHPDocX is pretty fast but we do not want that you just take our Word for it (pun intended).

To start with we have prepared a simple phpdocx script that allows us to easily generate from very short to extremely long Word documents.

The idea is simple:

Generate a one page Word report that includes standard elements:

  • header,
  • footer,
  • one complex paragraph with a link, an image, a footnote and advanced formatting,
  • one nested list,
  • one table and
  • a couple of simple paragraphs of plain text.


Loop over it as many times as needed to generate longer reports at will.

The sample code is given here:

 


if(isset($_GET['pages'])){

$pages = $_GET['pages'];

}else{

$pages = 1;

}



require_once '../../classes/CreateDocx.inc';



$docx = new CreateDocx();



//add a header to the document

$headerImage = $docx->addImage(array('name' => '../../examples/files/img/image.png', 'dpi' => 300, 'rawWordML' => true, 'target' => 'defaultHeader'));

$myImage = $docx->createWordMLFragment(array($headerImage));



$docx->addHeader(array('default' => $myImage));



//add a footer with page numbering

$options = array('jc' => 'right',

'b' => 'on',

'sz' => 16,

'color' => 'ff0000',

'rawWordML' => true);



$numbering = $docx->addPageNumber('numerical', $options);



$WordMLFragment = $docx->createWordMLFragment(array($numbering));



$docx->addFooter(array('default' => $WordMLFragment));



//loop over single pages

for($j = 1; $j 'B70000',

'i' => 'on',

'jc' => 'center',

'sz' => 13

);



$docx->addHeading($title,0, $options);



$docx->addText('This is a plain text paragraph for iteration ' .$j . 'but next paragraph includes several elements: complex formatting, links, footnotes and floating images.');



//add a complex paragraph with an image, a link and a footnote

$imageData = $docx->addImage(array('name' => '../../examples/files/img/image.png' , 'scaling' => 50, 'float' => 'right', 'textWrap' => 1, 'rawWordML' => true));

$image = $docx->createWordMLFragment($imageData);



$linkData = $docx->addLink('link to Google', array('url'=> 'http://www.google.es', 'color' => '0000FF', 'u' => 'single', 'rawWordML' => true));

$link = $docx->createWordMLFragment($linkData);



$footnoteData = $docx->addFootnote(

array(

'textDocument' => 'here it is',

'textFootnote' => 'This is the footnote text.',

'rawWordML' => true

)

);

$footnote = $docx->createWordMLFragment($footnoteData);



$text = array();



$text[] = $image;

$text[] =

array(

'text' => 'I am going to write a link: ',

'b' => 'on'

);

$text[] =$link;

$text[] =

array(

'text' => ' to illustrate how to include links. '

);

$text[] =

array(

'text' => ' As you may see is extremely simple to do so and can be done with any other Word element. For example to include a footnote is also as simple as this: ',

);

$text[] = $footnote;

$text[] =

array(

'text' => ', as you see there is a footnote at the bootom of the page. ',

'color' => 'B70000'

);



$docx->addText($text);



//add a nested list

$docx->addText('We now insert a nested list:');



$options = array(

'val' => 1

);

$itemsList= array(

'Line 1',

array(

'Line A',

'Line B',

'Line C'

),

'Line 2',

'Line 3',

);



$docx->addList($itemsList, $options);



//add a table

$docx->addText('We include a table with one of the default Word styles:');



$valuesTable = array(

array(

'Title A',

'Title B',

'Title C'

),

array(

'Line A-1',

'Line B-1',

'Line C-1'

),

array(

'Line A-2',

'Line B-2',

'Line C-2'

),

array(

'Line A-3',

'Line B-3',

'Line C-3'

)

);



$widthTableCols = array(

1000,

2500,

3000

);



$paramsTable = array(

'TBLSTYLEval' => 'MediumShading1PHPDOCX',

'jc' => 'center',

'size_col' => $widthTableCols

);



$docx->addTable($valuesTable, $paramsTable);



//add a page break

if($j != $pages){

$docx->addBreak(array('type' => 'line'));

$docx->addText('If tis is not the last page we insert a page break.');



$docx->addBreak(array('type' => 'page'));

}

}



$docx->createDocx('pages_' . $pages . '_' .rand(1, 999999));

We include a "pages" parameter that allows us to control the total number of pages of the final Word document.

You can download from here a sample result docx with just two pages so you get the feeling for the level of complexity of each individual page (please, do not judge us for the beauty of the result :-)).

The test was run on a server with the following specifications:

  • Intel(R) Core(TM)2 Quad CPU 2.40GHz.
  • 4 GB RAM.
  • HD SATA II 7200rpm.
  • Debian 5.0 32 bits.
  • Apache 2
  • PHP 5.2.6

  • The results are summarized as follows (all times are in milliseconds and rounded to the nearest integer):
     
    # pages Total time (ms) Time /page (ms) Peak memory usage in MB
    0 96 NA 3.26
    1 103 103 3.34
    5 132 26 3.40
    10 165 16 3.51
    50 425 8 6.09
    100 772 8 9.31
    250 1,769 7 18.97
    500 3,429 7 35.07
    750 5,163 7 51.17

    If we assume a time of 96 ms as the "head start" for opening the library and inserting headers and footers we get:
     
    # pages Estimated time (ms) Time /page (ms) Peak memory usage in MB
    1 7 7 3.34
    5 36 7 3.40
    10 69 7 3.51
    50 329 7 6.09
    100 676 7 9.31
    250 1,673 7 18.97
    500 3,333 7 35.07
    750 5,067 7 51.17

    So the time scales linearly (to detect deviations from the linear behavior we have to go to the tenths of milliseconds) with the number of pages.

    So you can create a pretty big 750 pages Word document with hundreds of images, tables and lists in a little more than 5 seconds and using little more than 50MB of RAM at peak usage.

    Note: If we remove the image and footnote from the complex paragraph and we only left some formatting and the link we get an average time per additional page of just 3.6 milliseconds.