使用Smarty时显示程序执行时间的方法

当使用Smarty时,似乎没有什么好的方法来实现显示程序执行时间。
WP或者其它程序时都有一个输出程序执行时间的功能,因此,在自己写的程序里,也想实现这一功能。
搜索了一下,发现基本没有这方面的文章。大多数人认为这个没有必要。
本着折腾的精神,开始一行行看Smarty的源码,最终找到一个比较精确计算出程序执行时间的方法。
在程序最开始部分,也就是执行的第一行代码的位置,加上:

1
define('__START_TIME', microtime(TRUE));

然后在smarty_internal_template.php的 renderTemplate函数第一个ob_start前面加上:

1
$_SESSION['__excution_time']=microtime(TRUE) - __START_TIME;

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
   public function renderTemplate ()
    {
        if ($this->resource_object->usesCompiler) {
            if ($this->mustCompile() && $this->compiled_template === null) {
                $this->compileTemplateSource();
            }
            if ($this->smarty->debugging) {
                Smarty_Internal_Debug::start_render($this);
            }
            $_smarty_tpl = $this;
            //计算执行时间 by 荒野无灯 20110401
            //__START_TIME 在程序开始时定义
            //调用 :{nocache}{$smarty.session.__excution_time|string_format:"%.4f"}{/nocache}
            $_SESSION['__excution_time']=microtime(TRUE) - __START_TIME;
            ob_start();
            if ($this->resource_object->isEvaluated) {
                eval("?>" . $this->compiled_template);
            } else {
                include($this->getCompiledFilepath ());
                // check file dependencies at compiled code
                if ($this->smarty->compile_check) {
                    if (!empty($this->properties['file_dependency'])) {
                        $this->mustCompile = false;
                        $resource_type = null;
                        $resource_name = null;
                        foreach ($this->properties['file_dependency'] as $_file_to_check) {
                            If ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'extends' || $_file_to_check[2] == 'php') {
                                $mtime = filemtime($_file_to_check[0]);
                            } else {
                                $this->getResourceTypeName($_file_to_check[0], $resource_type, $resource_name);
                                $resource_handler = $this->loadTemplateResourceHandler($resource_type);
                                $mtime = $resource_handler->getTemplateTimestampTypeName($resource_type, $resource_name);
                            }
                            // If ($mtime != $_file_to_check[1]) {
                            If ($mtime > $_file_to_check[1]) {
                                $this->mustCompile = true;
                                break;
                            }
                        }
                        if ($this->mustCompile) {
                            // recompile and render again
                            ob_get_clean();
                            $this->compileTemplateSource();
                            ob_start();
                            include($this->getCompiledFilepath ());
                        }
                    }
                }
            }
        } else {
            if (is_callable(array($this->resource_object, 'renderUncompiled'))) {
                if ($this->smarty->debugging) {
                    Smarty_Internal_Debug::start_render($this);
                }
                ob_start();
                $this->resource_object->renderUncompiled($this);
            } else {
                throw new SmartyException("Resource '$this->resource_type' must have 'renderUncompiled' methode");
            }
        }
        $this->rendered_content = ob_get_clean();
        if (!$this->resource_object->isEvaluated && empty($this->properties['file_dependency'][$this->templateUid])) {
            $this->properties['file_dependency'][$this->templateUid] = array($this->getTemplateFilepath(), $this->getTemplateTimestamp(),$this->resource_type);
        }
        if ($this->parent instanceof Smarty_Internal_Template) {
            $this->parent->properties['file_dependency'] = array_merge($this->parent->properties['file_dependency'], $this->properties['file_dependency']);
            foreach($this->required_plugins as $code => $tmp1) {
                foreach($tmp1 as $name => $tmp) {
                    foreach($tmp as $type => $data) {
                        $this->parent->required_plugins[$code][$name][$type] = $data;
                    }
                }
            }
        }
        if ($this->smarty->debugging) {
            Smarty_Internal_Debug::end_render($this);
        }
        // write to cache when nessecary
        if (!$this->resource_object->isEvaluated && ($this->caching == Smarty::CACHING_LIFETIME_SAVED || $this->caching == Smarty::CACHING_LIFETIME_CURRENT)) {
            if ($this->smarty->debugging) {
                Smarty_Internal_Debug::start_cache($this);
            }
            $this->properties['has_nocache_code'] = false;
            // get text between non-cached items
            $cache_split = preg_split("!/\*%%SmartyNocache:{$this->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!s", $this->rendered_content);
            // get non-cached items
            preg_match_all("!/\*%%SmartyNocache:{$this->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!s", $this->rendered_content, $cache_parts);
            $output = '';
            // loop over items, stitch back together
            foreach($cache_split as $curr_idx => $curr_split) {
                // escape PHP tags in template content
                $output .= preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '<?php echo \'$1\'; ?>', $curr_split);
                if (isset($cache_parts[0][$curr_idx])) {
                    $this->properties['has_nocache_code'] = true;
                    // remove nocache tags from cache output
                    $output .= preg_replace("!/\*/?%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!", '', $cache_parts[0][$curr_idx]);
                }
            }
            if (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output'])) {
                $output = Smarty_Internal_Filter_Handler::runFilter('output', $output, $this);
            }
            // rendering (must be done before writing cache file because of {function} nocache handling)
            $_smarty_tpl = $this;
            ob_start();
            eval("?>" . $output);
            $this->rendered_content = ob_get_clean();
            // write cache file content
            $this->writeCachedContent('<?php if (!$no_render) {?>'. $output. '<?php } ?>');
            if ($this->smarty->debugging) {
                Smarty_Internal_Debug::end_cache($this);
            }
        } else {
            // var_dump('renderTemplate', $this->has_nocache_code, $this->template_resource, $this->properties['nocache_hash'], $this->parent->properties['nocache_hash'], $this->rendered_content);
            if ($this->has_nocache_code &#038;&#038; !empty($this->properties['nocache_hash']) &#038;&#038; !empty($this->parent->properties['nocache_hash'])) {
               // replace nocache_hash
                $this->rendered_content = preg_replace("/{$this->properties['nocache_hash']}/", $this->parent->properties['nocache_hash'], $this->rendered_content);
                $this->parent->has_nocache_code = $this->has_nocache_code;
            }
        }
    }

这样以后还没完,在同文件buildTemplateFilepath 函数最开始加上上面同样的语句,修改后的函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 /**
     * get system filepath to template
     */

    public function buildTemplateFilepath ($file = null)
    {
        //计算执行时间 by 荒野无灯 20110401
        //__START_TIME 在程序开始时定义,对于缓存的模板,是不会执行 renderTemplate() 方法的,因此这里再加一次。
        //对于缓存了的模板,getRenderedTemplate() 中会执行 smarty_internal_cacheresource_file.php 中的
        // getCachedContents() ,而 getCachedContents() 会调用 $_template->getCachedFilepath() 来获取缓存文件路径.
        //而 $_template->getCachedFilepath() 在模板未过期或开启缓存的情况下又必须调用 cache_resource_object->getCachedFilepath(),而此方法
        //又要调用 $_template->getTemplateFilepath() ,因此执行终止时间放这里比较合适。基本上是和最终时间很接近了。
        //而此函数又要调用smarty_internal_resource_extends.php的 resource_object->getTemplateFilepath()
        //调用 :{nocache}{$smarty.session.__excution_time|string_format:"%.4f"}{/nocache}
        $_SESSION['__excution_time']=microtime(TRUE) - __START_TIME;
//        var_dump('here');exit;

        if ($file == null) {
            $file = $this->resource_name;
        }
        // relative file name?
        if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) {
            foreach((array)$this->smarty->template_dir as $_template_dir) {
                if (strpos('/\', substr($_template_dir, -1)) === false) {
                    $_template_dir .= DS;
                }
                $_filepath = $_template_dir . $file;
                if (file_exists($_filepath)) {
                    return $_filepath;
                }
                if (!preg_match('
/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_template_dir)) {
                    // try PHP include_path
                    if (($_filepath = Smarty_Internal_Get_Include_Path::getIncludePath($_filepath)) !== false) {
                        return $_filepath;
                    }
                }
            }
        }
        // try absolute filepath
        if (file_exists($file)) return $file;
        // no tpl file found
        if (!empty($this->smarty->default_template_handler_func)) {
            if (!is_callable($this->smarty->default_template_handler_func)) {
                throw new SmartyException("Default template handler not callable");
            } else {
                $_return = call_user_func_array($this->smarty->default_template_handler_func,
                    array($this->resource_type, $this->resource_name, &#038;$this->template_source, &#038;$this->template_timestamp, $this));
                if (is_string($_return)) {
                    return $_return;
                } elseif ($_return === true) {
                    return $file;
                }
            }
        }
        return false;
    }

最后是在模板中显示了:

1
{nocache}{$smarty.session.__excution_time|string_format:"%.4f"}{/nocache} seconds
更多
One Response Post a comment
  1. ISayMe

    完全看不懂.嘿嘿.不知道是干嘛用的. :arrow:

Leave a Reply

Note: You may use basic HTML in your comments. Your email address will not be published.

Subscribe to this comment feed via RSS