Help speeding up documents made with tcppdf

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
andiejeAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ray PaseurCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
andiejeAuthor Commented:
Hi - the commentn from ray paseus s not visible
0
Ray PaseurCommented:
Hi, andieje:  What's missing?  I'll be glad to help, ~Ray
0
Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

andiejeAuthor Commented:
Hi. The comment has now appeared.

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

Thanks
0
Ray PaseurCommented:
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
andiejeAuthor Commented:
Ok. I do understand our logic . Im just kncking out quick questions sometimes before looking deeper.
Cross off the easy

Which makes me
0
andiejeAuthor Commented:
Just a quick thought - would adding multiple 2) small graphics cause a problem (im still going to follow up rays explain issue
0
Ray PaseurCommented:
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
andiejeAuthor Commented:
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
andiejeAuthor Commented:
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
Ray PaseurCommented:
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
andiejeAuthor Commented:
or might this do ths job. I'll open a separate question if we are getting off track
0
Ray PaseurCommented:
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
Ray PaseurCommented:
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
Julian HansenCommented:
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.