Solved

Help speeding up documents made with tcppdf

Posted on 2014-10-05
16
124 Views
Last Modified: 2014-10-10
Hi

I am creating a 30 odd page document in tcpdf and its takes 1 min 17secs. I presume this is because my page had lots of graohcs. Ive tried jpeg, png etc but to difference. I cant cache the document.

I like tcpdf but i need these pages created like lightening fasteven if I have to pay.

However a second investigation of the page shows the sql queries are really slow.

Is it a slow process to add graphics is tcpdf? If not it must be these dv queries to create the page
Any ideas much appreciated

Kind regards
0
Comment
Question by:andieje
  • 8
  • 7
16 Comments
 
LVL 108

Accepted Solution

by:
Ray Paseur earned 400 total points
Comment Utility
It is not a slow process to add graphics to TCPDF.  I would look closely at the database.  You can use EXPLAIN SELECT to learn what the DB engine is doing with your queries.

If you want to time parts of the process to detect where the script is really spending its time, this little timer class may be helpful.

<?php // demo/class_Stopwatch.php
error_reporting(E_ALL);

// A SCRIPT TIMER FOR ALL OR PART OF A SCRIPT PHP 5+
// MAN PAGE http://php.net/manual/en/function.microtime.php
class StopWatch
{
    protected $a; // START TIME
    protected $s; // STATUS - IF RUNNING
    protected $z; // STOP TIME

    public function __construct()
    {
        $this->a = array();
        $this->s = array();
        $this->z = array();
    }

    // A METHOD TO PROVIDE A FINAL READOUT, IF NEEDED
    public function __destruct()
    {
        $ret = $this->readout();
        if (!$ret) return FALSE;
        echo
          __CLASS__
        . '::'
        . __FUNCTION__
        . '() '
        ;
        echo "<b>$ret</b>";
        echo PHP_EOL;
    }

    // A METHOD TO REMOVE A TIMER
    public function reset($name='TIMER')
    {
        // RESET ALL TIMERS
        if ($name == 'TIMER')
        {
            $this->__construct();
        }
        else
        {
            unset($this->a[$name]);
            unset($this->s[$name]);
            unset($this->z[$name]);
        }
    }

    // A METHOD TO CAPTURE THE START TIME
    public function start($name='TIMER')
    {
        $this->a[$name] = microtime(TRUE);
        $this->z[$name] = $this->a[$name];
        $this->s[$name] = 'RUNNING';
    }

    // A METHOD TO CAPTURE THE END TIME
    public function stop($name='TIMER')
    {
        $ret = NULL;

        // STOP ALL THE TIMERS
        if ($name == 'TIMER')
        {
            foreach ($this->a as $name => $start_time)
            {
                // IF THIS TIMER IS STILL RUNNING, STOP IT
                if ($this->s[$name])
                {
                    $this->s[$name] = FALSE;
                    $this->z[$name] = microtime(TRUE);
                }
            }
        }

        // STOP ONLY ONE OF THE TIMERS
        else
        {
            if ($this->s[$name])
            {
                $this->s[$name] = FALSE;
                $this->z[$name] = microtime(TRUE);
            }
            else
            {
                $ret .= "ERROR: CALL TO STOP() METHOD: '$name' IS NOT RUNNING";
            }
        }

        // RETURN AN ERROR MESSAGE, IF ANY
        return $ret;
    }

    // A METHOD TO READ OUT THE TIMER(S)
    public function readout($name='TIMER', $dec=3, $m=1000, $t = 'ms', $eol=PHP_EOL)
    {
        $str = NULL;

        // GET READOUTS FOR ALL THE TIMERS
        if ($name == 'TIMER')
        {
            foreach ($this->a as $name => $start_time)
            {
                $str .= $name;

                // IF THIS TIMER IS STILL RUNNING UPDATE THE END TIME
                if ($this->s[$name])
                {
                    $this->z[$name] = microtime(TRUE);
                    $str .= " RUNNING ";
                }
                else
                {
                    $str .= " STOPPED ";
                }

                // RETURN A DISPLAY STRING
                $lapse_time = $this->z[$name] - $start_time;
                $lapse_msec = $lapse_time * $m;
                $lapse_echo = number_format($lapse_msec, $dec);
                $str .= " $lapse_echo $t";
                $str .= $eol;
            }
            return $str;
        }

        // GET A READOUT FOR ONLY ONE TIMER
        else
        {
            $str .= $name;

            // IF THIS TIME IS STILL RUNNING, UPDATE THE END TIME
            if ($this->s[$name])
            {
                $this->z[$name] = microtime(TRUE);
                $str .= " RUNNING ";
            }
            else
            {
                $str .= " STOPPED ";
            }

            // RETURN A DISPLAY STRING
            $lapse_time = $this->z[$name] - $this->a[$name];
            $lapse_msec = $lapse_time * $m;
            $lapse_echo = number_format($lapse_msec, $dec);
            $str .= " $lapse_echo $t";
            $str .= $eol;
            return $str;
        }
    }
}


// DEMONSTRATE THE USE -- INSTANTIATE THE STOPWATCH OBJECT
$sw  = new Stopwatch;

// SET A STOPWATCH NAME THAT REFLECTS THE PARTS OF THE SCRIPT WE WANT TO TIME
$g_timer = 'GOOGLE TIMER';

// START A TIMER TO GET ELAPSED TIME FOR A CALL TO GOOGLE
$sw->start($g_timer);

// PERFORM SOME ACTIVITY THAT YOU WANT TO TIME (READS GOOGLE WEB PAGE)
$page = 'https://www.google.com';
$html = file_get_contents($page);

// GET A READOUT OF THE TIMER WHILE IT IS STILL RUNNING
echo nl2br($sw->readout($g_timer));
echo "<br/>" . PHP_EOL;

Open in new window

0
 

Author Comment

by:andieje
Comment Utility
Hi - the commentn from ray paseus s not visible
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
Hi, andieje:  What's missing?  I'll be glad to help, ~Ray
0
 

Author Comment

by:andieje
Comment Utility
Hi. The comment has now appeared.

What's the quickest way for generating pdf in php?

Thanks
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
What's the quickest way for generating pdf in php?
The question missed the point.  What you really want to find out is "Where is the script spending its time?" and once you know the answer to that question then go back to the "quickest way" part.  I am almost 100% certain that it's not about generating a PDF.  Whenever there is a performance problem in a web application it's caused by the I/O subsystem, since disk access is about 3 orders of magnitude slower than RAM memory access.  In modern applications this is the database.  That's why I recommended EXPLAIN SELECT.

One of our E-E colleagues has a good article about this subject.
http://www.experts-exchange.com/Database/MySQL/A_1250-3-Ways-to-Speed-Up-MySQL.html
0
 

Author Comment

by:andieje
Comment Utility
Ok. I do understand our logic . Im just kncking out quick questions sometimes before looking deeper.
Cross off the easy

Which makes me
0
 

Author Comment

by:andieje
Comment Utility
Just a quick thought - would adding multiple 2) small graphics cause a problem (im still going to follow up rays explain issue
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
Why not show us the code for the TCPDF creation process and show us your test data?  I don't really understand "adding multiple 2) small graphics" but if I see the code and data, I can set up my own tests and take some measurements.
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Author Comment

by:andieje
Comment Utility
Its a project i have been handed over and its butchered. Code and cut and paste from everyywhere. And i thnk there are dependeneies i cant distribute

However i cannot turn down generosity such as that. I will look

The prebious was typo -  (20) small graphics was

Also the grphics are being resized and i dont know whether to just make a copy at the right size or if a pdf 'frame' can handle this quickly

I will find something i can send

Thanks lifesaver ray
0
 

Author Comment

by:andieje
Comment Utility
Ray - you know your wonderful stopwatch

does it give you an indivudual and cumulative total for each line of code. It would be nice to have to a diagnostic tool like that that shows where your code id dawdling

Im not 100% sure not being an 00 php programming

thanks
0
 
LVL 108

Assisted Solution

by:Ray Paseur
Ray Paseur earned 400 total points
Comment Utility
Ahh, perhaps we are starting to get to the heart of the matter.  20 graphics is 10X 2 graphics, so an order of magnitude difference.  And resizing the graphics can be done a number of different ways.  A smart way to do this would be to choose the resolution and dimensions you require and store permanent copies of the graphics at the right dimensions and resolutions.  Graphics on the web and in print is a pretty broad topic.  These articles touch the tip of this iceberg.

http://www.experts-exchange.com/Software/Photos_Graphics/Images_and_Photos/A_5931-Putting-Your-Photos-Online.html

http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_6554-Use-PHP-to-Make-an-Image-Thumbnail.html
0
 

Author Comment

by:andieje
Comment Utility
or might this do ths job. I'll open a separate question if we are getting off track
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
The StopWatch class lets you start and stop timers anywhere you want in your code.  When the script ends, you will get a readout of the timers.  To use the class, just include it in your script (you can do that at the end of the script if you want to avoid cluttering the code too much).  Put the start() and stop() method calls into the appropriate places.  The code snippet shows an example of how to use it.
0
 

Author Comment

by:andieje
Comment Utility
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
That's a great tool!  And there are other monitors built into things like phpUnit, etc.  A google search will turn up more.  I think it comes down to what you want to achieve.  The StopWatch will let you see what's slow, then we can have a dialog here that focuses on the slow part.  Here's a minimalist example to show the essential moving parts.  You can start() and stop() as many timers as you want.  
http://iconoun.com/demo/temp_andieje.php

<?php // demo/temp_andieje.php
ini_set('display_errors', TRUE);
error_reporting(E_ALL);
echo '<pre>';


// SEE http://www.experts-exchange.com/Programming/Languages/Scripting/PHP/Q_28531628.html#a40371250


$signal = 'About to sleep 5 seconds';
$sw = new Stopwatch();
$sw->start($signal);
sleep(5);
$sw->stop($signal);


// A SCRIPT TIMER FOR ALL OR PART OF A SCRIPT PHP 5+
// MAN PAGE http://php.net/manual/en/function.microtime.php
class StopWatch
{
    protected $a; // START TIME
    protected $s; // STATUS - IF RUNNING
    protected $z; // STOP TIME

    public function __construct()
    {
        $this->a = array();
        $this->s = array();
        $this->z = array();
    }

    // A METHOD TO PROVIDE A FINAL READOUT, IF NEEDED
    public function __destruct()
    {
        $ret = $this->readout();
        if (!$ret) return FALSE;
        echo
          __CLASS__
        . '::'
        . __FUNCTION__
        . '() '
        ;
        echo "<b>$ret</b>";
        echo PHP_EOL;
    }

    // A METHOD TO REMOVE A TIMER
    public function reset($name='TIMER')
    {
        // RESET ALL TIMERS
        if ($name == 'TIMER')
        {
            $this->__construct();
        }
        else
        {
            unset($this->a[$name]);
            unset($this->s[$name]);
            unset($this->z[$name]);
        }
    }

    // A METHOD TO CAPTURE THE START TIME
    public function start($name='TIMER')
    {
        $this->a[$name] = microtime(TRUE);
        $this->z[$name] = $this->a[$name];
        $this->s[$name] = 'RUNNING';
    }

    // A METHOD TO CAPTURE THE END TIME
    public function stop($name='TIMER')
    {
        $ret = NULL;

        // STOP ALL THE TIMERS
        if ($name == 'TIMER')
        {
            foreach ($this->a as $name => $start_time)
            {
                // IF THIS TIMER IS STILL RUNNING, STOP IT
                if ($this->s[$name])
                {
                    $this->s[$name] = FALSE;
                    $this->z[$name] = microtime(TRUE);
                }
            }
        }

        // STOP ONLY ONE OF THE TIMERS
        else
        {
            if ($this->s[$name])
            {
                $this->s[$name] = FALSE;
                $this->z[$name] = microtime(TRUE);
            }
            else
            {
                $ret .= "ERROR: CALL TO STOP() METHOD: '$name' IS NOT RUNNING";
            }
        }

        // RETURN AN ERROR MESSAGE, IF ANY
        return $ret;
    }

    // A METHOD TO READ OUT THE TIMER(S)
    public function readout($name='TIMER', $dec=3, $m=1000, $t = 'ms', $eol=PHP_EOL)
    {
        $str = NULL;

        // GET READOUTS FOR ALL THE TIMERS
        if ($name == 'TIMER')
        {
            foreach ($this->a as $name => $start_time)
            {
                $str .= $name;

                // IF THIS TIMER IS STILL RUNNING UPDATE THE END TIME
                if ($this->s[$name])
                {
                    $this->z[$name] = microtime(TRUE);
                    $str .= " RUNNING ";
                }
                else
                {
                    $str .= " STOPPED ";
                }

                // RETURN A DISPLAY STRING
                $lapse_time = $this->z[$name] - $start_time;
                $lapse_msec = $lapse_time * $m;
                $lapse_echo = number_format($lapse_msec, $dec);
                $str .= " $lapse_echo $t";
                $str .= $eol;
            }
            return $str;
        }

        // GET A READOUT FOR ONLY ONE TIMER
        else
        {
            $str .= $name;

            // IF THIS TIME IS STILL RUNNING, UPDATE THE END TIME
            if ($this->s[$name])
            {
                $this->z[$name] = microtime(TRUE);
                $str .= " RUNNING ";
            }
            else
            {
                $str .= " STOPPED ";
            }

            // RETURN A DISPLAY STRING
            $lapse_time = $this->z[$name] - $this->a[$name];
            $lapse_msec = $lapse_time * $m;
            $lapse_echo = number_format($lapse_msec, $dec);
            $str .= " $lapse_echo $t";
            $str .= $eol;
            return $str;
        }
    }
}

Open in new window

0
 
LVL 51

Assisted Solution

by:Julian Hansen
Julian Hansen earned 100 total points
Comment Utility
An alternative measuring mechanism
Using an array, the PHP __LINE__ magic constant and the microtime function you can profile an application quite easily by adding a single line at each measuring point.

The following code measures the efficiency of itself by iterating 1000000 times and on each iteration performing a measurement. The point of the exercise is to demonstrate that you can easily create a profile for an application simply by copying this line
if (defined('TIMER')) $timer[] = array(__LINE__, microtime(true));

Open in new window

To each point in your application where you want to perform a measurement and that the cost of doing this is negligible as the results from running this code will demonstrate.

At any point you can dump a complete performance trace of your application which will show the line number and the timestamp for that line number. A simple post processing function can then take this data and work out where the bottle knecks are.
<pre>
<?php
//DEFINE TO INDICATE WHETHER WE ARE PROFILING OR NOT
define('TIMER',true);

// ARRAY TO STORE TIME VALUES
$timer = array();

// DUMMY ARRAY FOR MEASURING ASSIGNMENT COST
$other = array();

// CAPTURE A PROFILE POINT
if (defined('TIMER')) $timer[] = array(__LINE__, microtime(true));

// PERFORM A LOOP SIGNIFICANT TIMES TO 
// REGISTER A MICROTIME VALUE. WE DIVIDE
// BY LOOP MAX TO FIND OUT ACTUAL COST
for($i=0; $i<100000; $i++){
  // THIS IS WHAT WE ARE MEASURING - COST OF 
  // TAKING A TIMESTAMP AND STORING IT
  if (defined('TIMER')) $other[] = array(__LINE__, microtime(true));
}

// CAPTURE A SECOND PROFILE POINT
if (defined('TIMER')) $timer[] = array(__LINE__, microtime(true));

// DUMP OUR PROFILE POINTS
print_r($timer);

// DISPLAY THE DIFFERENCE
echo "Difference: " . ($timer[1][1] - $timer[0][1]) . "<br/>";

// DUMP OUR LOOP PROFILE ARRAY TO A FILE 
// JUST TO PROVE IT DID SOMETHING

file_put_contents('metrics.txt', print_r($other, true));
?>
</pre>

Open in new window

0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Router for PHP reqeusts 12 29
Re-imbursement Claim System 3 20
Generating a set of random unique numbers 6 17
PHP string issue 5 15
Both Easy and Powerful How easy is PHP? http://lmgtfy.com?q=how+easy+is+php (http://lmgtfy.com?q=how+easy+is+php)  Very easy.  It has been described as "a programming language even my grandmother can use." How powerful is PHP?  http://en.wikiped…
This article will explain how to display the first page of your Microsoft Word documents (e.g. .doc, .docx, etc...) as images in a web page programatically. I have scoured the web on a way to do this unsuccessfully. The goal is to produce something …
The viewer will learn how to count occurrences of each item in an array.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

6 Experts available now in Live!

Get 1:1 Help Now