پریشب که سرم خلوت شد، گفتم یه نگاهی به اسکریپتهای سایت بندازم و یک سری Benchmark در مورد سرعت اجرای اسکریپتها، انجام بدم. برای این منظور IDE محبوبم یعنی Zend Studio 3.0 رو اجرا کردم و تحت IE روی Localhost یه Profile از Home Page سایت گرفتم. عجب نتایجی! زمان اجرای اسکریپتهای صفحه اصلی سایت حدود ۱۳۳۹ میلی ثانیه شد! تعجب کردم و Functions Statistics رو بررسی کردم دیدم بعله! این News Feed سایت که با SAX API نوشته بودم، چیزی حدود ۷۹۰ میلی ثانیه از زمان اجرای کل رو بخودش اختصاص داده. کلاسی که برای این منظور نوشته بودم بررسی کردم دیدم راه بهینه تری نمی تونم پیدا کنم و باید یه فکر تازه تری بکنم تا این SimpleXML نسخه ۵ بیاد و ما رو نجات بده! یه جا خونده بودم که Tim Bray از کمک نویسندگان مشخصات XML گفته بود که از Perl Regex ها برای تفسیر اسناد XML استفاده میکنه. خوب فکر جالبیه. با اینکه اگه بخوایم مفسرهایی تمام و کمال بنویسیم با این روش یکم سخت هست اما برای مواردی که فقط قسمتهای خاصی از سند XML مورد نیاز باشه و این وسط DTD ها رو هم نادیده بگیریم، روشی هست که از نظر پرفورمنس و سرعت بسیار بسیار سریعتر از SAX و XPath هست و نسبت به DOM هم تفاوت فابل توجهی داره. بدین منظور، دیشب اومدم و یک کلاس نوشتم که خیلی راحت با دو خط کد! بتونید یک RSS Reader ساده و سریع به سایتتون اضافه کنید. از قابلیتهایی که این کلاس داره اینه که کاملا Template Base هست و می تونید کاملا به صورت جداگانه هر طرح و فرمی که میخواهید با HTML بسازید و با قراردادن یک سری نشانه ها، محل قرارگرفتن نام سایت، URL سایت، عناوین و لینک های مربوطه رو مشخص کنید. قابلیت دیگه اون، کش کردن فایل روی Server هست که با تعیین یک زمان انقضا News Feed شما بروزرسانی میشه. من تو این کلاس علاوه بر اینکه مفاهیم ابتدایی یک Template Engine رو از دید خودم پیاده سازی کردم، شما رو با یکسری توابعی که شاید کمتر باهاشون کار کرده باشید، آشنا میکنم. باز هم می گم که این کلاس خیلی خیلی ساده هست و تنها کاری که میکنه محتوای تگ title و link ها رو تفسیر میکنه. از اونجایی که من می بینم اکثرا از همین دو المنت در سایتها استفاده میکنند و معمولا XSL رو هم نادیده میگیرند، همین امکان رو بهش اضافه کردم(که ۱۰۰ درصد قابل تعمیم دادنه) بدین ترتیب سرعت اجرای اون کمتر از یک دهم زمان تفسیر RSS توسط SAX هست.
بعد از دریافت فایل فشرده از اينجا، محتویات اون رو عینا روی Serverتون آپلود کنید، یه دایرکتوری هست به نام rss_reader که می تونید نام دیگه ای براش انتخاب کنید، اگه نامش رو عوض کردید خط دوم کد زیر رو هم اصلاح کنید. در ضمن این دایرکتوری باید قابل نوشتن توسط کاربری باشه که وب سرور تحت اون اسکریپتها رو تفسیر میکنه(nobody) بنابراین CHMOD رو ۷۷۷ تنظیم کنید.
<?php
require('easyrss.class.php');
define('CACHEDIR', './rss_reader');
$rssSample = new EasyRSS('http://www.phpmystery/rss/', 60, 'template.htm', CACHEDIR);
echo $rssSample->parseFeed();
?>
خط اول، کلاس EasyRSS رو اينکلود ميکنيم، خط دوم دايرکتوری کش رو مشخص ميکنيم. خط سوم از کلاسمون يک نمونه ميگيريم و تابع سازنده رو با آدرس کامل فايل RSS يا آدرس کامل مولد اون، زمان انقضا بر حسب دقيقه، نام و مسير سند HTML ای که بعنوان تمپليت استفاده خواهيم کرد و نهايتا مسير دايرکتوری کش، صدا میکنیم. در خط آخر هم با اجرای يک متد از کلاس خيلی قشنگ News Feed امون رو تحويل ميگيرم.
فعلا یکم عجله دارم توضیح بیشتر برای بعد، اگه کسی مشکلی داشت کامنت بگذاره.
نمونه اش هم اينجاست.
کد خود کلاس هم اینه:
<?php
class EasyRSS {
var $rssUrl;
var $xmlFile;
var $expireTime;
var $template;
var $cachDir;
var $xmlDocument;
var $lastUpdate;
function EasyRSS($rssUrl_in, $expireTime_in, $templateFileName_in, $cacheDir_in) {
$this->rssUrl = $rssUrl_in;
$this->xmlFile = $cacheDir_in.'/'.$this->url2File();
$this->expireTime = (int)$expireTime_in;
$this->cachDir = $cacheDir_in;
$this->template = file_get_contents($templateFileName_in);
}
function url2File() {
$url = parse_url($this->rssUrl);
return ereg_replace('[^[:alnum:]]','_',$url['host']).'.xml';
}
function getFeed() {
if (is_writable($this->cachDir)) {
$xmlDocument = implode ('', file($this->rssUrl));
if(!empty($xmlDocument)) {
$fp = @fopen($this->xmlFile,"w");
fwrite($fp,$xmlDocument);
fclose($fp);
@chmod($this->xmlFile,0766);
return true;
}
} else {
return false;
}
}
function isExpired() {
$this->lastUpdate = filemtime($this->xmlFile);
return (time() > $this->lastUpdate + $this->expireTime * 60) ? true : false;
}
function parseFeed(){
if (!file_exists($this->xmlFile) || $this->isExpired()) {
$this->getFeed();
}
$this->xmlDocument = file_get_contents($this->xmlFile);
$pattern = '/<title>([^<]*)/';
preg_match_all($pattern, $this->xmlDocument, $titles);
$pattern = '/<link>([^<]*)/';
preg_match_all($pattern, $this->xmlDocument, $links);
$items = array();
if (PHP_VERSION < '5.0') {
for ($counter = 0; $counter < count($titles[1]); $counter++) {
$items[$titles[1][$counter]] = $links[1][$counter];
}
} else {
$items = array_combine($titles[1], $links[1]);
}
return $this->parseTemplate($items);
}
function parseTemplate(&$results) {
$loopContent = $finalOutput = '';
$template = $this->template;
$keys = array_keys($results);
$values = array_values($results);
$output = str_replace('#WEBSITEURL#', $values[0], $template);
$output = str_replace('#WEBSITE#', $keys[0], $output);
ereg('(.*)<!-- #STARTLOOP# -->(.*)<!-- #ENDLOOP# -->(.*)', $output, $matches);
for ($counter = 1; $counter < count($keys); $counter++) {
$loopContent .= str_replace('#LINK#', $values[$counter], $matches[2]);
$loopContent = str_replace('#TITLE#', $keys[$counter], $loopContent);
}
$matches[3] = str_replace('#LASTUPDATE#', date('Y-m-d@H:i:s', $this->lastUpdate), $matches[3]);
$finalOutput =$matches[1].$loopContent.$matches[3];
return $finalOutput;
}
}
?>
واژه نامه:
Code profiling در اصل، به معنی سنجش مدت زمانی است که اسکريپت اجرا ميشود.
|