|
Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon. |
|
View previous topic :: View next topic |
Author |
Message |
vbAlex Smarty Rookie
Joined: 26 Oct 2003 Posts: 5 Location: Michigan
|
Posted: Tue Oct 28, 2003 3:04 am Post subject: Total page generation time |
|
|
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? |
|
Back to top |
|
sucresemoule Smarty n00b
Joined: 28 Oct 2003 Posts: 2
|
Posted: Tue Oct 28, 2003 10:30 am Post subject: Re: Total page generation time |
|
|
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 |
|
vbAlex Smarty Rookie
Joined: 26 Oct 2003 Posts: 5 Location: Michigan
|
Posted: Tue Oct 28, 2003 4:57 pm Post subject: |
|
|
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 |
|
messju Administrator
Joined: 16 Apr 2003 Posts: 3336 Location: Oldenburg, Germany
|
Posted: Tue Oct 28, 2003 5:33 pm Post subject: |
|
|
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 |
|
andre Smarty Pro
Joined: 23 Apr 2003 Posts: 164 Location: Karlsruhe, Germany
|
Posted: Wed Oct 29, 2003 9:31 am Post subject: |
|
|
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 |
|
vbAlex Smarty Rookie
Joined: 26 Oct 2003 Posts: 5 Location: Michigan
|
Posted: Wed Oct 29, 2003 8:54 pm Post subject: |
|
|
andre: Nice code/idea
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 |
|
boots Administrator
Joined: 16 Apr 2003 Posts: 5611 Location: Toronto, Canada
|
Posted: Sat Nov 01, 2003 12:35 pm Post subject: |
|
|
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 ).
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
Last edited by boots on Sat Nov 22, 2003 4:31 am; edited 1 time in total |
|
Back to top |
|
andre Smarty Pro
Joined: 23 Apr 2003 Posts: 164 Location: Karlsruhe, Germany
|
Posted: Mon Nov 03, 2003 8:06 am Post subject: |
|
|
Wow
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 |
|
boots Administrator
Joined: 16 Apr 2003 Posts: 5611 Location: Toronto, Canada
|
Posted: Mon Nov 03, 2003 9:14 am Post subject: |
|
|
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
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
Last edited by boots on Mon Nov 17, 2003 3:51 pm; edited 1 time in total |
|
Back to top |
|
ZeroFill Smarty Rookie
Joined: 31 Aug 2003 Posts: 28
|
Posted: Sun Nov 16, 2003 8:25 pm Post subject: |
|
|
first off, thanks for the tips
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 |
|
boots Administrator
Joined: 16 Apr 2003 Posts: 5611 Location: Toronto, Canada
|
Posted: Mon Nov 17, 2003 5:48 am Post subject: |
|
|
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 |
|
ZeroFill Smarty Rookie
Joined: 31 Aug 2003 Posts: 28
|
Posted: Sat Nov 22, 2003 2:48 am Post subject: |
|
|
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 |
|
ZeroFill Smarty Rookie
Joined: 31 Aug 2003 Posts: 28
|
Posted: Sat Nov 22, 2003 3:52 am Post subject: |
|
|
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 |
|
boots Administrator
Joined: 16 Apr 2003 Posts: 5611 Location: Toronto, Canada
|
Posted: Sat Nov 22, 2003 4:30 am Post subject: |
|
|
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 |
|
ZeroFill Smarty Rookie
Joined: 31 Aug 2003 Posts: 28
|
Posted: Sat Nov 22, 2003 5:41 am Post subject: |
|
|
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! _________________ my delimiters are <{ and }> |
|
Back to top |
|
|
|
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
|
|