[PHP-users 1768] FastTemplate その後

Osamu Shigematsu php-users@php.gr.jp
Tue, 04 Sep 2001 14:40:26 +0900


重松です。こんにちは。

FastTemplate ですが、その後、中をよく読んでいくと、「Fast」とは言っているも
のの、冗長な処理やなんかがかなり多くて、あんまり美しくないことがわかりました。

また、その課程でいくつか気づいたことがありましたので、他に FastTemplate をお
使いになっている方の参考になればと思い、投稿します。

■より高速に文字列に変換するには
意味があるのか、ということ自体がよくわかってないのですが、FastTemplate では、
連想配列のキーを文字列に強制的に変換する操作が随所に見られます。

    $foo_array["$key"]

というのがその書式なのですが、"$key" として文字列に変換するのは、
(string)$key とするよりもコストがずいぶん高いようです。

<?php
function utime()
{
    list($usec,$sec) = explode(" ",microtime());
    return ((double)$sec) + ((double)$usec);
}

    $start = utime();
    $foo = 12345;
    for($i = 0; $i < 100000; ++$i){
        $bar = (string)$foo;
    }
    $end = utime();
    $elapsed = $end - $start;
    print "$elapsed<br>";
?>

$bar = (string)$foo; の場合、0.58 秒程度で処理されますが、
$bar = "$foo"; の場合には、7.3 ほどかかります。

ループ処理自体のコストもありますので、"$foo" とするのは、とても遅い、という
ことがわかりました。

それから、みなさん気にしていないようですが、

    for($i = 0; $i < 100000; $i++)

とかくと、0.59 秒ほどかかりますので、2% ほど速度が低下するようです。


■まともな (と自分では思う) parse_dynamic() 関数
file() で行毎に読み込んだものを、implode() でくっつけたのに、コストの高い
split() を正規表現を使う必要もないのに使ってまた配列に戻すという効率のきわめ
て悪い parse_dynamic() 関数を書き直しました。
# "\n" を区切りにすると、MacOSX など、"\r" を区切り文字にも使う環境で、キチ
ンと処理できないから、"\n|\r" を区切りに使う、という話もなきにしもあらずです
が。。。

//    **********************************************************************

    function parse_dynamic($macro,$macro_name)
    {
        if(empty($macro)) return false;
        
        // The file must already be in memory.
        $parent_tag = $this->DYNAMIC[$macro];
        if(empty($this->$parent_tag)){
            $this->$parent_tag =
$this->get_template($this->FILELIST[$parent_tag]);
        }
        
        if($this->$parent_tag)
        {
            $new_parent = "";
            $new_macro = "";
            
if(mbereg_search_init($this->$parent_tag,"<!--\s*(BEGIN|END)\s+DYNAMIC\s+BLO
CK\s*:\s*$macro\s*-->",'i')){
                $start = 0;
                $inside = false;
                for(;;){
                    $pos = mbereg_search_pos();
                    if(!$pos[1]) break; // No more tags
                    $reg = mbereg_search_getregs();
                    if(5==strlen($reg[1])){ // 5 == strlen("BEGIN")
                        if($inside)
                            $this->error("Found \"BEGIN\" before \"END\"!");
                        $inside = true;
                        $new_parent .=
substr($this->$parent_tag,$start,$pos[0]-$start);
                        $start = $pos[0]+$pos[1];
                    }else{
                        if(!$inside)
                            $this->error("Found \"END\" before \"BEGIN\"!");
                        $inside = false;
                        if(!empty($macro_name)){
                            $new_macro .=
substr($this->$parent_tag,$start,$pos[0]-$start);
                            $new_parent .= '{' . $macro_name . '}';
                        }
                        $start = $pos[0]+$pos[1];
                    }
                    mbereg_search_setpos($pos[0]+$pos[1]); // Advance the
search position
                }
                if($inside)
                    $this->error("Last \"END\" tag was not found!");
                   
                $new_parent .= substr($this->$parent_tag,$start);
                
                $this->$macro = $new_macro;
                $this->$parent_tag = $new_parent;

                return true;
            }else
                $this->error("mbereg_search_init() failure!");
        }else{
            // $parent_tag NOT loaded - MAJOR oopsie
            $this->error("ParentTag: [$parent_tag] not loaded!");
        }
        return false;
    }

//    **********************************************************************
//    Strips a DYNAMIC BLOCK from a template.

    function clear_dynamic($macro/*=""*/)
    {
        return $this->parse_dynamic($macro,"");
    }

でも、思ったんですけど、みなさん、FastTemplate って使ってないのでしょうか?

-- 
Osamu Shigematsu

http://www.ravi.ne.jp/
mailto:shige@ravi.ne.jp