ArthurXF从业10年的CTO,受上海非凡学院邀请,进行PHP,CSS,FREEBSD等网络技能授课培训,有意向参加的,请联系.

  此文章由ArthurXF(肖飞)倾情奉献!
  我们在使用smarty的时候,经常会碰到变量组合成新变量的时候,例如:$aaa$b,$b是可变值,我们需要得到$aaa1,$aaa2,$aaa3等变量.但是在smarty中,这样的变量连接写法是不允许的.

针对这样的问题,我给出下面几种情况的解决方案.
注:<?{和}?>是我定义的smarty定界符,等同于{和},希望大家理解.

引用
1.针对数组的变量连接问题:
<?php
$arrMType = array();
$arrMType[1] = '高交会展';
$arrMType[2] = '学术会议';
$arrData[id] = 1;
?>
在smarty中.
$arrMType[$arrData.id]是错误的.
解决方案:
<?{foreach from=$arrType key=key item=value}?>
<?{if $key == $arrData.type_id}?><?{$value}?><?{/if}?>
<?{/foreach}?>


2.针对文件引用的变量连接问题:
<?PHP
$page="index";
?>
在smarty中,下面的写法都是错误的.
<?{include file=$page.html}?> //这样不能执行成功
<?{include file=$page|cat:".html"}?> //还是不行
解决方案:
<?{include file="`$page`.html"}?>


3.针对函数传递的变量连接问题:
<?PHP
$arrGWeb['module_id'] = 'news';
?>
要在smarty中实现:
<?{url url = "/news/list?type_id=1"}?>
错误的写法:
<?{url url = "/$arrGWeb.module_id/list?type_id=1"}?>
正确的写法:
<?{url url = "/`$arrGWeb.module_id`/list?type_id=1"}?>
注意:"`"这个符号,是数字1前面的那个符号,不是单引号.


ArthurXF从业10年的CTO,受上海非凡学院邀请,进行PHP,CSS,FREEBSD等网络技能授课培训,有意向参加的,请联系.
  PHP手册中只有最多到32进制转换的函数,64进制的没有,这里我提供两个我写的10to64和64to10转换的函数。这两个函数没考虑小数的情况,仅仅为整数的转换。此文由ArthurXF倾情奉献。
引用
/**
* 将64进制的数值转换为10进制的数值
* @author  肖飞 (ArthurXF)
* @param  string  $bit64    指定的64进制字符串
* @return  double
*/
function make_bit10($bit64) {
 $strLetter = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/';    
 $intCount = strlen($bit64);    
 for($i=0;$i<$intCount;$i++) {
   $pos = strpos($strLetter,$bit64[$i]);
   $bit10 += $pos * pow(64,$intCount-1-$i);
 }
 return $bit10;
}

/**
* 将10进制的数值转换为64进制的数值
* @author  肖飞 (ArthurXF)
* @param  double    $bit10    指定10进制数字
* @return  string
*/
function make_bit64($bit10) {
 $strLetter = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/';    //很多大于int取值范围的大数是以字符串形式传入的,这里强制转成double,否则求余会有误差
 settype($bit10,"double");
 $intCount = ceil($bit10/64);    
 for($i=0;$bit10>0;$i++) {
   $key = $bit10 % 64;
   if($key<0) $key = 64 + $key;
   $bit64 .= $strLetter[$key];
   $bit10 = floor($bit10 / 64);
 }
 return strrev($bit64);
}
  很多朋友不太习惯使用集成包安装,都来问我一些用ports安装apache+mysql+php的问题,我这里就重新写一篇文章,来解决这些问题。此文章由ArthurXF倾情奉献,谢谢支持。

一、安装mysql51
引用
先添加mysql组和mysql用户
pw addgroup mysql
pw adduser mysql

开始安装
cd /usr/ports/databases/mysql51-server/
make
make thread-safe-client=enable dtrace=disable assembler=enable with_big_tables=yes with_embedded_server=yes with_local_infile=yes with_plugins=partition,innobase,myisammrg WITH_CHARSET=utf8 WITH_XCHARSET=all WITH_COLLATION=utf8_general_ci WITH_PROC_SCOPE_PTH=yes BUILD_OPTIMIZED=yes BUILD_STATIC=yes SKIP_DNS_CHECK=yes install clean  // 设定编码字符集为utf-8
cp /usr/local/share/mysql/my-large.cnf /etc/my.cnf
//服务器内存1G,但是与apache在一起/usr/local/share/mysql下面有5个my-xxxx.cnf文件
my-small.cnf               最小配置安装,内存<=64M,数据数量最少
my-medium.cnf             32M<内存<64M,或者内存有128M,但是数据库与web服务器公用内存
my-large.cnf               内存=512M
my-huge.cnf               1G<内存<2G,服务器主要运行mysql
my-innodb-heavy-4G.cnf   innodb格式数据大于4G的


因为如果你安装系统的时候默认分配空间的话/var一般的空间比例很小,也就3G,对于大数据库的话,肯定是不够用的,所以我们这里把数据库搬到/usr去,一般/usr的空间都是最大的,这样可以保证数据库空间充足。
搬mysql数据库需要操作下面的命令,如果不搬这个可以跳过。本文适合最新的FreeBSD6.2,其他版本可能文件名会有变化,请自行查找
vi /etc/rc.conf
增加
mysql_dbdir="/usr/local/db/mysql"
重起服务器,再执行下面的命令。
cd  /usr/local
mysql_install_db --user=mysql --datadir=/usr/local/db/mysql/data #建立数据库目录
mysqld_safe & #启动mysql


二、安装apache22+php5
引用
#cd /usr/ports/www/apache22/
选择你需要安装的模块
#make config
如果你的服务器是多个CPU的,可以把Apache以worker模式运行,则需要修改Makefile文件。
# ee Makefile
将WITH_MPM?=      prefork # or worker, event, itk改成:
WITH_MPM?=      worker # or worker, event, itk
开始安装了
# make install clean

安装php5
cd /usr/ports/lang/php5/
make config #选择php的模块,一定要选择apache module,否则不会自动安装到apahce里面的,那样php就不会执行的。
make
make install clean

安装php5-extensions
cd /usr/ports/lang/php5-extensions/
make config #选择php的扩展模块
make
make install clean

配置/usr/local/etc/apache/httpd.conf:
修改

   DirectoryIndex index.html index.htm index index.php index.phps


如果你需要修改网站根目录,就修改下面两个地方,下面仅仅是个例子,大家可根据需要自行修改,确保一致即可。
DocumentRoot "/usr/local/www/web"

 Options Indexes FollowSymLinks
去掉Indexes可以限制浏览你的主页目录

加入
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps #可不加
*注意:第二行主要为查看php代码用,加上的话web目录下的所有扩展名为.phps的文件在被浏览器访问时都显示其源代码

配置/usr/local/etc/php.ini:
cd /usr/local/etc/
cp php.ini-recommended php.ini
vi php.ini
在error_reporting  =  E_ALL前面加上;
将error_reporting = E_ALL & ~E_NOTICE前面的;去掉
*将报错信息设置改成去掉notice

upload_max_filesize = 2M
上传最大文件尺寸可根据需要修改

date.timezone = CST
设置服务器时区为中国的时区


apachectl start
echo "" > /usr/loacl/www/data/info.php
可能你的apache启动的时候和我一样会报这样的错误:
[Wed Jan 02 19:54:30 2008] [warn] (2)No such file or directory: Failed to enable the 'httpready' Accept Filter

解决这个错误,执行如下操作:
kldload accf_http
grep accf /boot/defaults/loader.conf
显示内容如下
accf_data_load="NO" # Wait for data accept filter
accf_http_load="NO" # Wait for full HTTP request accept filter #将这个"NO"改成"YES"
vi /boot/defaults/loader.conf
找到Other modules 就可以找到accf_http_load了。

访问http://服务器的IP/info.php,如果有php的说明文件说明基本的php+apache2已经工作正常!

开机后自动启动:
echo 'mysql_enable="YES" ' >> /etc/rc.conf
echo 'apache22_enable="YES" ' >> /etc/rc.conf
以便开机后自动启动mysql apache
如果启动不了,就执行下面的命令
cp /usr/local/share/mysql/mysql.server /usr/local/etc/rc.d/mysql.sh
这样mysql就可以自动执行了。

以上文章是由ArthurXF倾情奉献,谢谢支持!

现在ArthurXF本人正在搞PHP等技术培训,如果想学习的人可以跟我联系。另外培训的招生简章在这个网址,想了解的可以去看看。加我QQ:29011218交流也可。
PHP培训招生简章
Tags: , , ,
  这个发现是由一个问题引发出来的。如何根据字符串的位置,把字符串该位置的字符取出来?一般就是用substr函数取该位置长度为1的字符出来就实现了,可是我们还有更加简便的办法,请看下面:
引用
$str = "abc";
echo $str[1];
结果会是 b。
这样其实在php里字符串$str,本身就是数组$str。
$str = "abc";
等同于
$str[0] = "a";
$str[1] = "b";
$str[2] = "c";


这样上面的问题就太容易解决了,把位置减1,再带入数组即可。哈哈,方便啊!
Tags:

PHP 程序加速探索

2007/08/11 19:17 ArthurXF
- (一)简介
- (二)是否需要加速?
- (三)如何加速?
   -<1> 测试
       ◆ 服务器负载测试 ApacheBench
       ◆ 脚本执行速度测试 PEAR:: Benchmark
   -<2> 加速
       ◆ 代码优化
      ◆ 压缩输出 Gzip
      ◆ 内容缓存输出 PEAR Content cache
      ◆ 函数缓存输出 PEAR Function cache
      ◆ 加速工具软件 APC、Turck MMCache、PHPA、Zend Performance Suite
- (四)总结

(一)简介

  本文尝试对PHP程序加速的各个方面进行探索,包括必要性以及从不同角度采取的具体措施。希望有助于读者了解PHP程序加速,并应用于实际。

(二)是否需要加速?

  这个问题听起来有点愚蠢。在这个时代,很少有人会怀疑时间是最宝贵的财富,尤其是在商业市场上。程序执行越快,用户就节约越多的时间,这样你的程序就可以用更少的时间和服务器资源为用户服务,从而产生更多效益。
我想对于大部份人(包括我自己)来说,很多WEB项目都是在很紧张的时间里完成的,通常没有经过缜密的思考和严格的测试。当开始一个新的WEB项目。很多人都在构建那种“快而乱”的应用,缺乏必要的时间来调整和改良代码,这时优化和加速就是我们必须采取的措施。
  然而需要特别指出的是,并不是所有程序都需要加速。
  优化已完成的代码是很浪费时间的,最好的方法是在写代码的时候就注意到效率,然后完成项目后只优化确实需要优化的那部份。一般一个程序只会有少数几个影响速度的瓶颈,将它们找出来并解决掉,程序就可以很好地运行。另外,当遇到执行效率低下的情况,首先要用大局的眼光来找出影响效率的主要因素,而不要拘泥于细节—例如数据量过大,服务器带宽不够,或硬件配置过低,在这样的情况下,优化代码于事无补。
  另外,在没有发现程序有明显的执行缓慢的迹象时,就不要太吹毛求疵,为了改进一些非常细节的代码而浪费时间。用这些时间,你可以完成另一个项目或为原来的项目完成一个扩展功能。当然你可以笑话我不够负责,没有把工作做得尽善尽好,我也可以说你是完美主义者:-)  
  综上,在你决定为你的PHP程序提速之前,问问自己是否有必要。

(三)如何加速?

要回答“如何加速”这个问题前,需要先回答以下两个小问题:
你的程序慢在哪一部份?
PHP可以从哪几个方面考虑加速?
  第一个小问题显然我无法给你答案,但我建议你用“测试脚本执行速度”的方法来解决。只有找出限制速度的瓶颈,才能考虑如何去解决。
  第二个小问题我大概的答案是:代码优化,压缩输出,内容缓存输出,函数缓存输出,加速/缓存工具软件。如果你知道更多请告诉我:-)
  下面我们来详细地研究一下这几个方面的相关技术。当然实际上每个方面都有无数的细节可以讨论,下面的内容难免会有片面的地方,欢迎补充。

<1> 测试
◆ 服务器负载测试


  服务器负载太大而影响程序效率也是很常见的,我们需要对此进行测试。这里我以目前最常用的Apache服务器为例。
  Apache服务器自带有一个叫AB(ApacheBench)的工具,在bin目录下。使用这个轻巧的工具我们可以对服务器进行负载测试,看看在重负荷之下服务器的表现如何。ApacheBench 可以针对某个特定的 URL 仿真出连续的联机请求,同时还可以仿真出同时间点数个相同的联机请求,因此利用 ApacheBench 可帮助我们在网站开发期间仿真实际上线可能的情况,利用仿真出来的数据作为调整服务器设定或程序的依据。
  在命令行下输出:

./ab -n number_of_total_requests \
-c number_of_simultaneous_requests \
http://your_web_server/your_php_app.php

例如:

./ab -n 1000 -c 50 http://www.domain.com/myapp.php

  AB将同时向http://www.domain.com/myapp.php发出50个并发请求,共发出1000次。
  测试结果将可能是这样的:

Server Software: Apache/2.0.16
Server Hostname: localhost
Server Port: 80
Document Path: /myapp.php
Document Length: 1311 bytes
Concurrency Level: 50
Time taken for tests: 8.794 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 1754000 bytes
HTML transferred: 1311000 bytes
Requests per second: 113.71
Transfer rate: 199.45 kb/s received
Connection Times (ms)
min avg max
Connect: 0 0 5
Processing: 111 427 550
Total: 111 427 555

  myapp.php每秒钟可以处理的请求数为113.71个。将请求数增加,看看服务器能否处理更大的压力。你也需要调节Apache的MaxClients, ThreadsPerChild, MaxThreadsPerChild 等参数,基于你的 httpd.conf 中的 MPM 模块选择。
  如果你想得到更详细的信息,请到www.apache.org上查阅一些更深入的文档,包括模块和第三方的提高效率的工具。修改httpd.conf后,要重启Apache服务器,然后再用AB测试。你会看到每秒请求数增加或减少。
  记下每次的参数,最后选择最佳效率的那种配置。
  要指出的是,除了AB,还有许多优秀的服务器性能测试软件。另外,如果你的服务器不是 Apache,请自行寻找测试方法。

◆ 脚本执行速度测试

  前面有提到,只有找到影响速度的代码,我们才有可能进行优化。PEAR的benchmark包中的Benchmark_Timer类和Benchmark_Iterate类,可以用来很方便地测试脚本执行的速度。(关于PEAR的安装与配置请自行查看相关资料)
首先用Benchmark_Iterate类来测试程序中某个函数或类的某个方法的执行时间。

benchmark1.php


require_once('Benchmark/Iterate.php');
$benchmark = new Benchmark_Iterate();

$benchmark->run(10, 'myFunction','test');
$result = $benchmark->get();
echo "

"; print_r($result); echo "
";
exit;

function myFunction($var) {
   // do something
   echo 'Hello ';
}

?>

  建立benchmark Iterate对象$benchmark,这个对象用来执行myFunction函数10次。
  $argument变量每次都传递给myFunction. 多次运行的分析结果存入$result,然后用benchmark对象的get()方法来获取。这个结果用print_r()输出到屏幕。通常会输出这样的结果:
  Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello
Array(
   [1] => 0.000427    [2] => 0.000079    [3] => 0.000072    [4] => 0.000071    [5] => 0.000076    [6] => 0.000070    [7] => 0.000073    [8] => 0.000070    [9] => 0.000074    [10] => 0.000072    [mean] => 0.000108    [iterations] => 10)
  myFunction的每次执行,benchmark对象都会跟踪执行时间。并且会计算平均的执行时间([mean]那一行)。通过多次运行目标函数,你可以得到该函数的平均运行时间。
  在实际测试中,函数的次数应当至少1000次左右,这样可以得到较客观的结果。

  现在我们看看另一个测试脚本运行时间的方法--使用Benchmark_Timer类来测试一段代码执行所消耗的时间及这一段代码中每次调用与下一次调用间的时间。

benchmark2.php

require_once 'Benchmark/Timer.php';
$timer = new Benchmark_Timer();
$timer->start();
$timer->setMarker('start_myFunction');

for($i=0; $i<10; $i++){
   myFunction($argument);
}
$timer->setMarker('end_myFunction');
$timer->stop();
$profiling = $timer->getProfiling();

echo '
Time elapsed: ' .
$timer->timeElapsed('start_myFunction','end_myFunction') .'
';
echo '
'; print_r($profiling); echo '
';
exit;

function myFunction($var) {
   static $counter = 0;
   // do something
   echo $counter++ . ' ';
}
?>


  首先,建立一个benchmark timer对象$timer。然后调用start()方法,表示开始计时。 SetMaker()方法用来标记要测试的代码段。MyFunction()函数在循环中被调用,表示一段要执行的代码(当然实际中不会这么简单)。然后再用$timer对象的setMarker()方法标记程序执行终点。分析信息用getProfiling()来获取。在两个标记间程序执行消耗的时间用timeElapsed()方法计算出来(就像例子中的循环)。最后,用print_r()输出信息到屏幕:
Array(    [0] => Array        (            [name] => Start            [time] => 1085730111.27175200            [diff] => -            [total] => 1085730111.271752        )     [1] => Array        (            [name] => start_myFunction            [time] => 1085730111.27203800            [diff] => 0.000286            [total] => 1085730111.272038        )     [2] => Array        (            [name] => end_myFunction            [time] => 1085730111.27263200            [diff] => 0.000594            [total] => 1085730111.272632        )     [3] => Array        (            [name] => Stop            [time] => 1085730111.27271800            [diff] => 0.000086            [total] => 1085730111.272718        ))
0 1 2 3 4 5 6 7 8 9
Time elapsed: 0.000594

  通过这种方法,你可以在代码中设置大量时间段标记,获取每段代码执行时消耗的时间,很容易可以看出到底是哪一部份的代码影响了整个程序的运行效率。然后开始着手对这部份代码进行改进。
  用以上两种方法,你可以找出代码中最影响速度的部份代码。另外还可以用来对优化后的代码进行测试,看看到底执行速度提高了多少。通过测试->优化->测试->优化 …这样不断循环,你可以最终确定提供最佳效率的代码。

<2> 加速

◆ 代码优化
  掌握了PEAR::BenchMark,现在你已经知道如何测试你的代码,知道如何判断你的代码是快是慢,是哪一部份比较慢。那么接下来我要说的就是如何消灭或优化那部份慢的代码。
这一点上我个人最主要的经验只有两点,一是消除错误的或低效的循环;二是优化数据库查询语句。其实还存在一些其它的优化细节,比如“str_replace比ereg_replace快”、“echo比print快”等等。这些我暂时都放在一边,稍后我会提到用缓存来对付过于频繁的IO。
下面我们将三个功能相同,但程序写法不同的函数的效率(消耗的时间)进行对比。

badloops.php

require_once('Benchmark/Iterate.php');
define('MAX_RUN',100);
$data = array(1, 2, 3, 4, 5);

doBenchmark('v1', $data);
doBenchmark('v2', $data);
doBenchmark('v3', $data);
function doBenchmark($functionName = null, $arr = null)
{
   reset($arr);
   $benchmark = new Benchmark_Iterate;
   $benchmark->run(MAX_RUN, $functionName, $arr);
   $result = $benchmark->get();
   echo '
';
   printf("%s ran %d times where average exec time %.5f ms",$functionName,$result['iterations'],$result['mean'] * 1000);
}

function v1($myArray = null) {
   // 效率很差的循环
   for ($i =0; $i < sizeof($myArray); $i++)
   {
       echo ' ';
   }
}

function v2($myArray = null) {
   // 效率略有提高
   $max = sizeof($myArray);
   for ($i =0; $i < $max ; $i++)
   {
       echo ' ';
   }
}

function v3($myArray = null){
   //最佳效率
   echo " ";
}
?>

  程序输出的结果大概是这样的:

v1 ran 100 times where average exec time 0.18400 ms
v2 ran 100 times where average exec time 0.15500 ms
v3 ran 100 times where average exec time 0.09100 ms

  可以看到,函数的执行时间变少,效率上升。
  函数v1有个很明显的错误,每一次循环的时间,都需要调用sizeof()函数来计算。函数v2则在循环外把$myArray数组的元素个数存到$max变量中,避免了每次循环都要计算数组的元素个数,所以效率提高了。函数v3的效率最高,利用了现成的函数,避免循环。
  这个例子只是给你一个感性的认识,明白什么是相对高效的代码。在实际开发中,我相信会有很多人会迷迷糊糊地写出很多低效率的代码。要把代码写得精炼而高效,恐怕需要时间去锤炼:-) 但这是另一个话题了,我们略过不谈。
  数据库应用基本上每个PHP程序都会用到,在实际开发中我发现最影响整个系统效率的就是数据库这部份。至于数据库的优化和数据查询语句的优化,在此限于篇幅不详细讨论。你可以参看这两篇文章:
http://www.phpe.net/articles/340.shtml
http://www.phpe.net/articles/323.shtml
  及这篇讨论:
http://club.phpe.net/index.php?s=&act=ST&f=15&t=4783&st=0(前面几篇贴子总结不错),主要是针对MySQL的。

◆压缩输出 gzip

  利用Apache中的mod_gzip模块,我们可以利用gzip的压缩算法来对Apache服务器发布的网页内容进行压缩后再传输到客户端的浏览器。如果是纯文本的内容,效果非常明显,大约可以压缩到原来的30%-40%,使用户的浏览速度大大加快。
  Gzip需要客户端浏览器支持,目前大部份浏览器都支持gzip,如IE,Netscape,Mozilla等,所以这种方法值得一试。我们可以利用PHP中的预定义变量$_SERVER[‘HTTP_ACCEPT_ENCODING’]来判断客户端浏览器是否支持gzip。

gzip1.php


if(ereg('gzip',$_SERVER['HTTP_ACCEPT_ENCODING'])) {
   //浏览器支持
} else {
   //浏览器不支持,输出其它内容
}
?>

  接下来我们对上面这个PHP程序进行扩展,使用ob_start(ob_gzhandler)来将网页内容压缩,存入缓冲并发送给支持gzip的浏览器,浏览器会自动将压缩后的内容解压,显示。

gzip2.php

define('MAX',100);

if(ereg('gzip',$_SERVER['HTTP_ACCEPT_ENCODING']))
{
   //浏览器支持gzip,将内容压缩并缓冲输出
   ob_start("ob_gzhandler");
   $output = '';

   for($i=0;$i<=MAX;$i++)
   {
       $output .= "This is line $i
";
   }
   echo "浏览器支持gzip压缩输出
";
   echo $output;
}
else
{
   //浏览器不支持,直接输出
   for($i=0;$i<=MAX;$i++)
   {
       $output .= "This is line $i
";
   }

   echo "浏览器不支持gzip压缩输出
";
   echo $output;
}
?>


  使用gzip压缩生成的网页的HTTP头信息与一般的网页相比中会多出这样的信息:

Content-Encoding: gzip
Content-Length: 270

  如果你想得到更详细的信息,请参看mod_gzip项目主页:
http://sourceforge.net/projects/mod-gzip/

  类似地,我们也可以利用mod_deflate,压缩率比mod_gzip略低一些。调用zip函数需要耗用服务器内存,所以要慎用,视需求而定。

◆ 内容缓存输出 PEAR cache

  接下来我们开始探索更常用的缓存技术,这也是本文的重点部份。首先我们使用PEAR中的cache包。PEAR可以将内容缓存于文件,数据库或者内存中,我们以文件为例。
  下面是一个没有使用缓存的PHP小程序:

pear_content_cache1.php

echo "这是内容。

";
echo "当前时间是" . date('M-d-Y H:i:s A', time()) . "
";
?>

  上面这个程序非常简单,现在我们为其加上缓存。

pear_content_cache2.php

require_once 'Cache/Output.php';

//设置缓存目录,必须是可写的
$cacheDir = './pear_cache';
$cache = new Cache_Output('file',array('cache_dir' => $cacheDir));

//如果nocache变量为空,使用缓存中的内容
//如果想获得最新的内容,就要赋值给nocache变量
if (empty($_REQUEST['nocache']))
{
   // 建立一个独一的cache标识
   // 请求+Cookie信息
   $cache_id = $cache->generateID(array('url' => $_REQUEST,'post' =>$_POST,'cookies' => $HTTP_COOKIE_VARS));
}
else
{
   //想获得最新的内容,ID为空
   $cache_id = null;
}


//看cache ID对应的缓存内容是否可用
if ($content = $cache->start($cache_id))
{
   //缓存已存在,直接输出,并结束脚本
   echo $content;
   exit();
}

// 缓存中不存在该内容,生成新内容并写入缓存
echo "这是内容。

";
echo "当前时间是" . date('M-d-Y H:i:s A', time()) . "
";
// 把内容写入缓存
echo $cache->end();
?>

  分别刷新这两个文件,你会发现pear_content_cache1.php中的“当前时间是”这一行中的时间是随着刷新而变化的,而pear_content_cache2.php中的这一行则不变。这是由于pear_content_cache2.php使用了缓存,将用户请求的内容存入静态文件中。当用户再次请求时,它直接从文件中输出,而不需要用程序动态生成内容。
  对于pear_content_cache2.php,如果用户想要读取最新的信息,而不是缓存中成旧的信息。那么可以用http://…/pear_content_cache2.php?nocache=1 来访问,这将禁用缓存功能。刷新一下看看,你将发现时间会随之变化。
  总结一下PEAR内容缓存类的使用:
  1.包含PEAR包 要注意设对路径。
  2.包含Output.php中的cache类
require_once 'Cache/Output.php';
  3.设置缓存目录
$cacheDir = './pear_cache';
  确认这个目录是可写的。Cache数据将会写入这个目录的子目录中。
  4.建立一个输出缓存对象
$cache = new Cache_Output('file',array('cache_dir' => $cacheDir));
  第一个参数表示我们使用基于“文件”方式的缓存,第二个参数是一个与缓存目录相关联的数组。
  5.产生一个唯一的cache ID
$cache_id = $cache->generateID(array('url' => $_REQUEST,'post' =>$_POST,'cookies' => $HTTP_COOKIE_VARS));
  这里$cache对象的generateID()方法通过提供一个信息数组(URL, HTTP POST data, 和 HTTP cookie)来独一无二地标识这个请求,与其它请求区分开来。
  6.增加一个逻辑判断语句看是否对应于cacheID的缓存数据是否已经存在,如果存在,获取数据并结束脚本。
if ($content = $cache->start($cache_id))
{   echo $content;
   exit();
}
  7. 将产生内容的代码放在以上逻辑语句之后,并结束使用cache对象。
echo $cache->end();

◆ 函数缓存输出 PEAR cache

  PEAR除了可以对输出的内容进行缓存处理外,还可以将对某个函数的调用结果缓存起来。这是个很有趣的功能,如果你的程序要频繁使用到某个函数,而且调用的结果相同的话,我建议你不妨试试,特别是当这个函数运行起来比较慢的时候。

  下面我们实现对一个执行起来很慢的函数slowFunction()的缓冲调用。

require_once 'Cache/Function.php';


$cacheDir = './pear_cache/';
$cache = new Cache_Function('file',array('cache_dir' => $cacheDir));
$arr = array('苹果', '梨','西瓜');
$cache->call('slowFunction', $arr);
echo '
';

$arr = array('苹果', '梨','西瓜');
slowFunction($arr);

function slowFunction($arr = null)
{
   echo "一个执行起来很慢的函数 :(
";
   echo "当前时间是 " . date('M-d-Y H:i:s A', time()) . '
';
   foreach ($arr as $fruit)
   {
       echo "我吃了一个 $fruit
";
   }
}
?>

      以下是示例的脚本执行结果:
一个执行起来很慢的函数 :(
当前时间是 Jul-28-2004 17:15:57 PM
我吃了一个 苹果
我吃了一个 梨
我吃了一个 西瓜

一个执行起来很慢的函数 :(
当前时间是 Jul-28-2004 17:17:55 PM
我吃了一个 苹果
我吃了一个 梨
我吃了一个 西瓜
  代码中,Cache/Function.php类用来执行函数缓冲功能。$cache变量是一个Cache_Function对象,使用基于文件的函数缓存,存入$cacheDir目录。要缓存一个函数调,Cache_Function对象$cache的call()方法要像这样使用:$cache->call(‘slowFunction’, $arr);
  这里,slowFunction()函数被调用,参数为一个数组$arr,这个函数被缓存在$cacheDir目录下的一个文件里。任何在此之后的对这个函数的调用,将会由$cache->call()返回该函数执行的结果。
  函数缓存和使用方法和内容缓存很相似,不再多说,具体请查看PEAR手册。

  以上我们都是利用优化代码的方法对程序进行提速,接着我们要关注一下PHP加速的另一个领域—缓存工具软件。这类软件都是从优化PHP运行环境来提速的,不需要改变任何代码。我们可以大概地将它们称为“执行码优化/缓存工具”,你可以理解为它们用来实现比较底层的优化/缓存。

  以下列出目前比较常用的此类工具,具体哪种效果最好,请用自己的服务器环境测试:
(一)APC Alternative PHP Cache
http://apc.communityconnect.com/
  APC运行于Linux和FreeBSD,你需要自己编译安装。按照其开发人员的说法,在他们的测试环境下可以提高脚本速度50%-400%。并且APC是个开源项目,已经加入了PHP的PECL库,很值得一试。
(二)Turck MMCache
http://turck-mmcache.sourceforge.net/
  Turck MMCache似乎是此类软件中目前最受欢迎的一种,它开放源代码,完全免费。它将PHP代码预编译并缓存起来,同时也对PHP运行环境进行一定优化。按照其官方文档的说法,MMCache可以明显地减轻服务器的负载,并提高脚本执行速度1-10倍。
  MMCache与另一个知名的加速软件Zend Optimizer兼容,但注意必需先安装MMCache(php.ini中设置)。除了加快PHP程序的速度,MMCache还可以将PHP代码加密。
  Turck MMCache同时支持Linux和Win32平台。
(三)PHPA  the PHP Accelerator
http://www.php-accelerator/
  PHPA又是另一个流行的PHP加速软件。在其官方网站上有分别使用PHPA与APC、Zend Cache的PHP脚本执行测试对比,其表现略优于APC,略逊于Zend Cache。
   PHPA支持Linux, FreeBSD, OpenBSD, BSDi和Solaris系统.
(四)Zend Performance Suite
http://www.zend.com/
   Zend Performance Suite是老牌的PHP加速/优化软件,依托于PHP领域最知名的Zend公司。目前已经推出4.0版本,它可以为PHP应用提供程序加速,内容缓存,文件压缩,下载服务等,功能十分强大,获得好几个PHP杂志的推荐奖—但是不得不提起,它也很昂贵,目前的价格是1875美元。
以上几种加速软件,希望读者按照服务器环境自行测试并选择其中最适用的,因为我没有办法提供一个普遍适用的测试标准来判断哪种方案是最有效的。综合起来看,我个人认为Turck MMCache是个值得推荐的选择,免费而且功能相当出色。

(四)总结

  以上从多个角度较为全面细致地阐述了PHP加速的相关技术,包括测试技术,加速技术(压缩,缓存等),基本上都有附代码和范例。希望本文有助于读者全面了解PHP程序加速并在实际应用中选择合适的加速方案。

Tags: ,
分页: 8/11 第一页 上页 3 4 5 6 7 8 9 10 11 下页 最后页 [ 显示模式: 摘要 | 列表 ]