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?
 
Ray PaseurConnect With a Mentor Commented:
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
 
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
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
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 PaseurConnect With a Mentor Commented:
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 HansenConnect With a Mentor Commented:
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
All Courses

From novice to tech pro — start learning today.