Smarty Forum Index Smarty
The discussions here are for Smarty, a template engine for the PHP programming language.

Total page generation time
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Smarty Forum Index -> Feature Requests
View previous topic :: View next topic  
Author Message
vbAlex
Smarty Rookie


Joined: 26 Oct 2003
Posts: 5
Location: Michigan

PostPosted: Tue Oct 28, 2003 3:04 am    Post subject: Total page generation time Reply with quote

I'd like to be able to have the thing on the bottom of my pages which says how long it took to generate the page -- that would be cool. Although I have found no relativly easy way to do it without integrating inline PHP into the template (which I don't really want to do.)

My request is this: Can somebody make a way to output this timing? Smile
Back to top
View user's profile Send private message Send e-mail AIM Address Yahoo Messenger MSN Messenger
sucresemoule
Smarty n00b


Joined: 28 Oct 2003
Posts: 2

PostPosted: Tue Oct 28, 2003 10:30 am    Post subject: Re: Total page generation time Reply with quote

I include this file at the begining of my main php.
timestart.inc.php :
Code:
<?
$timeStart=gettimeofday();
$timeStart_uS=$timeStart["usec"];
$timeStart_S=$timeStart["sec"];
?>


and timerstop.inc.php at the bottom end :
Code:
<?
$timeEnd=gettimeofday();
$timeEnd_uS=$timeEnd["usec"];
$timeEnd_S=$timeEnd["sec"];

$ExecTime_S=($timeEnd_S+($timeEnd_uS/1000000))-($timeStart_S+($timeStart_uS/1000000));
Print "Execution Time: ".($ExecTime_S*1000)." milliseconds";
?>


The text will appear at the end of the page. Of course you cannot assign the timer value to smarty.

jm
Back to top
View user's profile Send private message
vbAlex
Smarty Rookie


Joined: 26 Oct 2003
Posts: 5
Location: Michigan

PostPosted: Tue Oct 28, 2003 4:57 pm    Post subject: Reply with quote

What I meant was for it to actually be a Smarty variable, so I could put it anywhere on the page I wanted -- instead of having to put it in after I stop the timer.
Back to top
View user's profile Send private message Send e-mail AIM Address Yahoo Messenger MSN Messenger
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Tue Oct 28, 2003 5:33 pm    Post subject: Reply with quote

this can not work. how should smarty know the time it takes to generate the page, while it is still busy generating it?
Back to top
View user's profile Send private message Send e-mail Visit poster's website
andre
Smarty Pro


Joined: 23 Apr 2003
Posts: 164
Location: Karlsruhe, Germany

PostPosted: Wed Oct 29, 2003 9:31 am    Post subject: Reply with quote

I'm using the following trick. Somewhere in your template put a special string. For example:
Code:
{* My Template *}
<html>
<head>...</head>
<body>
  ...
  page generation time: ~ @@@GENERATION_TIME@@@ seconds
</body>


Now in your main php script add the following lines to the beginning / to the end:
[php:1:9d8539fc00]<?php
$_stamp = (double)time() + (double)microtime();

// ... here goes your normal php code

$smarty = new Smarty();
// ... assign your smarty template vars
//
// Notice I am using not display() but fetch() here to get the page
// content as string
$html_output = $smarty->fetch("myTemplate.tpl");

// Now replace our special string with the correct generation time
// and echo it.
echo str_replace("@@@GENERATION_TIME@@@",
(double)time() + (double)microtime() - (double)$_stamp,
$html_output);
?>[/php:1:9d8539fc00]
Back to top
View user's profile Send private message
vbAlex
Smarty Rookie


Joined: 26 Oct 2003
Posts: 5
Location: Michigan

PostPosted: Wed Oct 29, 2003 8:54 pm    Post subject: Reply with quote

andre: Nice code/idea Shocked

Correct me if I'm wrong, but it shouldn't be too hard for Smarty to implement this internally given andre's code. I could see it being a 5 minute project for someone farmiliar with Smarty's source code (*hint* *hint* *hint*.)

Sorry if this is kinda thick, I'm kinda wrapped up in listing to music right now (Michelle Branch: Are You Happy Now? at the moment.)
Back to top
View user's profile Send private message Send e-mail AIM Address Yahoo Messenger MSN Messenger
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Sat Nov 01, 2003 12:35 pm    Post subject: Reply with quote

I like andre's suggestion, particularly if used with an output filter (vbAlex: there is no need to modify Smarty when you can customize it with the API Wink).

Here I suggest a slightly longer approach which isn't necessarily even as accurate. Never-the-less, it may be keen to use when tracing between templates and php code. Sort of like this idea but not limited to templates. This example also demonstrates using a static class method as a modifier which is a new feature in the current development version of Smarty. Assuming you do little or nothing after display() and that you do minimal work before starting the timer, this technique should be close to actual processing time--close enough that it is splitting hairs, IMHO. In addition, you gain some flexibility.

First: I have a util class which always gets loaded statically for dev sessions. Here, I will only show the necessary example timer code in that class, but I typically have other handy variable formatting functions in there. The method util::timer() takes two parameters, the first being an action and the second being an optional message. The allowed actions are 'begin', 'end', 'stop' and 'list'.

util.class.php
[php:1:a0785107e1]class util {
function timer($mode='begin', $msg='')
{
global $_timer_blocks, $_timer_history;
switch ($mode) {
case 'begin':
$_timer_blocks[] =array(microtime(), $msg);
break;

case 'end':
$last = array_pop($_timer_blocks);
$_start = $last[0];
$_msg = $last[1];
list($a_micro, $a_int) = explode(' ', $_start);
list($b_micro, $b_int) = explode(' ', microtime());
$elapsed = ($b_int - $a_int) + ($b_micro - $a_micro);
$_timer_history[] = array($elapsed, $_msg, "$_msg [".round($elapsed, 4)."s ".(round(1/$elapsed, 2))."/s]");
if ($msg) {
return "$_msg: {$elapsed}s \n";
}
return $elapsed;
break;

case 'list':
$o = '';
foreach ($_timer_history as $mark) {
$o .= $mark[2] . " \n";
}
return $o;
break;

case 'stop':
$result = '';
while(!empty($_timer_blocks)) {
$result .= util::timer('end', $msg);
}
return $result;
break;
}
}
}[/php:1:a0785107e1]

I create a custom Smarty subclass, SmartyExample.class.php:
[php:1:a0785107e1]include_once 'util.class.php';
class SmartyExample extends Smarty {
function SmartyExample()
{
// the following registers the static class method util::timer() as the "timer" modifier
$class = 'util';
$this->register_modifier('timer', array($class, 'timer'));
// setup smarty as fits your needs...
$this->Smarty();
}
}[/php:1:a0785107e1]

Now in my index.php
[php:1:a0785107e1]include_once 'util.class.php';
util::timer('begin', 'Page'); // starts a timer block with the message 'Page'

include_once 'SmartyExample.class.php';
$smarty = new SmartyExample();
// ... your app work goes here
$smarty->display('example.tpl'); // this template discharges the timer

echo 'history: '.util::timer('list'); // returns a history of timed block results
[/php:1:a0785107e1]

Still with me? We finally see the template:

example.tpl
Code:
First, we will start a new timer--they nest, so this one will count towards the total time for the already running 'Page' timer that was started in index.php.

{"begin"|timer:"template block"}
<p>Now we do something and eventually we want to stop this 'template block' timer. By default, the timer only returns a decimal value of elapsed seconds. By passing true as the optional message, it will print the original message and time in a nice way.

<b>{"end"|timer:true}</b>
<p>The following nests two timers--which are also nested in the still running 'Page' timer.
{"begin"|timer:"level2"}
{"begin"|timer:"level3"}

<p>You can stop all your timers at once using the 'stop' action. This will also stop our initial timer.

<p><b>{"stop"|timer:true|nl2br}</b>From here on, no timers are running. End of template.
<p>


Which should generate something along the lines of (don't bother to check my numbers, I made them up):
Quote:
First, we will start a new timer--they nest, so this one will count towards the total time for the already running 'Page' timer that was started in index.php.

Now we do something and eventually we want to stop this 'template block' timer. By default, the timer only returns a decimal value of elapsed seconds. By passing true as the optional message, it will print the original message and time in a nice way.
template block: 0.002212s

The following nests two timers--which are also nested in the still running 'Page' timer.

You can stop all your timers at once using the 'stop' action. This will also stop our initial timer.
level3: 0.002211s
level2: 0.004444s
Page: 0.011013s
From here on, no timers are running. End of template.
history: template block [0.0022s 454.55/s] level3 [0.0022s 454.55/s] level2 [0.0044s 227.27/s] Page [0.0110s 90.91/s]

Almost needless to say, this is but a starting point you can extend and customize to meet your style and needs.

Have Fun Smile


Last edited by boots on Sat Nov 22, 2003 4:31 am; edited 1 time in total
Back to top
View user's profile Send private message
andre
Smarty Pro


Joined: 23 Apr 2003
Posts: 164
Location: Karlsruhe, Germany

PostPosted: Mon Nov 03, 2003 8:06 am    Post subject: Reply with quote

Wow Shocked
That's quite nice, boots. But why are you using a modifier to handle the timer? Whouldn't a plugin function make more sense here?
Something like {timer mode="begin" message="template block"}
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Mon Nov 03, 2003 9:14 am    Post subject: Reply with quote

Hi Andre. Thanks for your comment and a very good question.

I used a modifier for a few reasons, but mainly because they can be used inline and combined. Also, I meant this as an example and it is not often you see folks implementing custom functionality with modifiers, so I thought I would show that Smile

I mention it, but don't show that the timer actually returns a decimal value instead of text if you don't pass any message to 'end' or 'stop'. That means that {'end'|timer} returns a number which you might like to use in a calculation or conditional.

So using the modifier approach I can do this:
Code:
{if "end"|timer > .5}

Whereas with a function, I would have to implement some assign logic. The other nice thing is that modifiers require less syntax. Compare the above with:
Code:
{timer action="end" assign="end"}
{if $end > .5}

Say I do want to assign, I can use the standard template functionality:
Code:
{assign var="end" value="end"|timer}

Further, it is actually a little easier to implement a custom modifier since they use a normal PHP calling convention instead of requiring you to deal with the passed $params array. Unfortunately, they don't pass you a local reference to the calling smarty instance, but that can be worked around if required.

In this and indeed, most cases, you aren't even concerned that it is Smarty that is calling your functionality anyhow. In my case, I was hooking Smarty to an already existing method in an already existing static class. I didn't want to put Smarty specific code in my otherwise general class and I didn't see the point of writing a wrapper for the already exisiting function so that Smarty could properly use it. In other words, I wanted to do as little as possible and with as few specializations as possible and I think that modifiers do a better job of enabling that than template functions. In cases like this where a generalized function is being packaged, I think it sometimes makes sense. For cases where you are packaging Smarty specific functionality (ie. code that relies on Smarty in some way) then it makes sense to consider a template function.

It comes down to taste, really, and I think modifiers are one of the nicest syntax features in Smarty. Of course, it would be fairly straightforward to adapt as a template function, so feel free if that suits you better Wink


Last edited by boots on Mon Nov 17, 2003 3:51 pm; edited 1 time in total
Back to top
View user's profile Send private message
ZeroFill
Smarty Rookie


Joined: 31 Aug 2003
Posts: 28

PostPosted: Sun Nov 16, 2003 8:25 pm    Post subject: Reply with quote

first off, thanks for the tips Very Happy

boots, for your suggestion, what does "/s" mean in

history: template block [0.0022s 454.55/s] level3 [0.0022s 454.55/s] level2 [0.0044s 227.27/s] Page [0.0110s 90.91/s]
_________________
my delimiters are <{ and }>
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Mon Nov 17, 2003 5:48 am    Post subject: Reply with quote

ZeroFill--in [0.0022s 454.55/s ...] I show first the elapsed time in seconds (known as the period) and then I show the #/s -- ie. how many times that period can occur sequentially in a single second (known as the frequency). Doesn't mean *too* much but I am used to looking at things in terms of frequency.
Back to top
View user's profile Send private message
ZeroFill
Smarty Rookie


Joined: 31 Aug 2003
Posts: 28

PostPosted: Sat Nov 22, 2003 2:48 am    Post subject: Reply with quote

Fix in next post

Code:
<p><b>{"stop"|timer:true|nl2br}</b>From here on, no timers are running. End of template.

Quote:
Page: 0.011013s
From here on, no timers are running. End of template.


when trying to do the same thing, "Page" doesnt show up.
[php:1:74d8f8dc80]
// top of index.php
Util::timer('begin', 'Page');

// bottom of index.php
$html_output = $smarty->fetch("form_list.tpl");
echo str_replace("@@@GENERATION_TIME@@@",
number_format((double)time() + (double)microtime() - (double)$_stamp, 6),
$html_output);
[/php:1:74d8f8dc80]
Code:

// footer.tpl
<{"begin"|timer:"footer block"}>
<p align="center"> <b>Sponsored By:</b><br />
  <a href="http://cft.org" target="_blank"><img src="/images/cftlogo.gif" width="230" height="75" border="0"></a><br />
</p>
<{if $show_page_load}>
    <center>
      Page created in @@@GENERATION_TIME@@@ seconds  <br /><{num_queries}> Queries Executed<br />     
    </center>
<{/if}>

</body>
</html>
<{if isset($debug)}>
   <pre>
   <center>--------------------debug below--------------------</center>
   <{$superglobals|print_r}>
   <{$smarty_obj|print_r}>
   <{num_queries}>
<{/if}>

<{"end"|timer:true}><br />
<{"stop"|timer:true|nl2br}><br />

Code:

// bottom of smarty output (doesn't show Page like in your sample)
footer block: 0.000217s

_________________
my delimiters are <{ and }>


Last edited by ZeroFill on Sat Nov 22, 2003 4:22 am; edited 1 time in total
Back to top
View user's profile Send private message
ZeroFill
Smarty Rookie


Joined: 31 Aug 2003
Posts: 28

PostPosted: Sat Nov 22, 2003 3:52 am    Post subject: Reply with quote

i decided to duplicate your demo but ended up with
Quote:

First, we will start a new timer--they nest, so this one will count towards the total time for the already running 'Page' timer that was started in index.php.
Now we do something and eventually we want to stop this 'template block' timer. By default, the timer only returns a decimal value of elapsed seconds. By passing true as the optional message, it will print the original message and time in a nice way. template block: 2.90000000001E-005s

The following nests two timers--which are also nested in the still running 'Page' timer.

You can stop all your timers at once using the 'stop' action. This will also stop our initial timer.

From here on, no timers are running. End of template.

history: template block [0s 34482.76/s] level3 [0s 40000/s] level2 [0.0001s 13157.89/s] Page [0.0594s 16.84/s]


[edit]
FIX
[php:1:c5b2d660a3]
//FIND

case 'stop':
while(!empty($_timer_blocks)) {
util::timer('end', $msg);
}
break;

//REPLACE WITH
case 'stop':
while(!empty($_timer_blocks)) {
$return[] = util::timer('end', $msg);
}
return implode(null,$return);
break;
[/php:1:c5b2d660a3]
Quote:

First, we will start a new timer--they nest, so this one will count towards the total time for the already running 'Page' timer that was started in index.php.
Now we do something and eventually we want to stop this 'template block' timer. By default, the timer only returns a decimal value of elapsed seconds. By passing true as the optional message, it will print the original message and time in a nice way. template block: 2.8E-005s

The following nests two timers--which are also nested in the still running 'Page' timer.

You can stop all your timers at once using the 'stop' action. This will also stop our initial timer.

level3: 2.5E-005s
level2: 7.7E-005s
Page: 0.020828s
From here on, no timers are running. End of template.

history: template block [0s 35714.29/s] level3 [0s 40000/s] level2 [0.0001s 12987.01/s] Page [0.0208s 48.01/s]

[/edit]
_________________
my delimiters are <{ and }>
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Sat Nov 22, 2003 4:30 am    Post subject: Reply with quote

Hi ZeroFill.

I see you just updated your fix to almost the same thing I just came up with. The fix I used to correct my original post uses a string instead of an array to achieve the same result.

Thanks for pointing this out!
Back to top
View user's profile Send private message
ZeroFill
Smarty Rookie


Joined: 31 Aug 2003
Posts: 28

PostPosted: Sat Nov 22, 2003 5:41 am    Post subject: Reply with quote

boots wrote:
Hi ZeroFill.

I see you just updated your fix to almost the same thing I just came up with. The fix I used to correct my original post uses a string instead of an array to achieve the same result.

Thanks for pointing this out!
ah! string, duh, now why didn't i think of that! Smile
_________________
my delimiters are <{ and }>
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Smarty Forum Index -> Feature Requests All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP