发新话题
打印

[编程代码] PHP程序加速探索之缓存输出

PHP程序加速探索之缓存输出

内容缓存输出 PEAR cache 2 h) v2 n6 |. S" ^* w
  接下来我们开始探索更常用的缓存技术,这也是本文的重点部份。首先我们使用PEAR中的cache包。PEAR可以将内容缓存于文件,数据库或者内存中,我们以文件为例。
2 E8 |9 Z; R2 J
! D2 e; t" a" L  下面是一个没有使用缓存的PHP小程序:( {) {6 n& E8 P4 Z# S; y

3 N7 a  W5 A0 s' L1 E) R' U  pear_content_cache1.php4 P0 g9 T7 l/ |4 r0 Y' P
  4 k3 d$ G$ I0 u" b5 G
<?php
0 Y, ]% r# _) n0 m+ r' R echo "这是内容。<P>";
6 ]1 e$ G: S* q1 e echo "当前时间是" . date('M-d-Y H:i:s A', time()) . "<BR>"; - O" J" z- T6 [7 P" W" z
?> 3 b$ T/ l, z: x6 \) ?7 n) s

' D! p0 D; c+ ^0 t6 u$ n  w  上面这个程序非常简单,现在我们为其加上缓存。
: ^' d! Z, h  T- O" @4 ~' i3 u7 c/ h+ d2 {% o
  pear_content_cache2.php% f9 Y. ]" b% K- \3 w3 a- h/ [* P7 d

3 w6 X9 h. K+ V5 `& E- f+ |<?php % e% a+ }+ N8 I7 p- G
 require_once 'Cache/Output.php';
1 g7 y. g& v1 T5 R- r, x% N
1 Y) R6 L. a( G" e4 @8 ^$ A //设置缓存目录,必须是可写的 ; L& p* w& @" P
 $cacheDir = './pear_cache';
* F" M# h& S, ^$ G6 k9 t0 k $cache = new Cache_Output('file',array('cache_dir' => $cacheDir)); 9 p% m4 P5 v# `4 l4 m

- s# q; a3 }* y* s; n# | //如果nocache变量为空,使用缓存中的内容
5 X' r- B6 u$ ^% a7 ` //如果想获得最新的内容,就要赋值给nocache变量
6 Z: z* ]8 K8 `7 W: H if (empty($_REQUEST['nocache']))
# w3 o/ Q2 J+ z# t, Q) P  \) Z { ) ?' Q$ E# Q  }9 r3 A
  // 建立一个独一的cache标识
, m; x# R. J1 N2 j/ W  // 请求+Cookie信息 8 }4 m9 ?4 t- w+ r  C
  $cache_id = $cache->generateID(array('url' => $_REQUEST,'post' =>$_POST,'cookies' => $HTTP_COOKIE_VARS));   `# |) d) _: C3 n0 }  c
 } % y, R3 e7 G1 _. X
 else 4 H" u  \8 ]; X  w" Y) d5 H, s
 {
9 M: k1 h$ I) C# m( F  //想获得最新的内容,ID为空
& R1 l. v/ W9 `2 `+ D  $cache_id = null;
# v7 C* o2 I' ?# [  f. h }
, Z) B8 l( P* ]$ l: M3 I* F4 h, W' H4 S) t
 //看cache ID对应的缓存内容是否可用
* V+ X% D# E3 H" M6 x0 C; Z: j if ($content = $cache->start($cache_id))
& Y/ ~  ~* |' B: | { 1 O& A4 o  L4 R9 p9 K0 K
  //缓存已存在,直接输出,并结束脚本 + b6 Z# g$ F+ y; ]* ]+ X) \  A$ a
  echo $content;
! ^4 g% c7 Q' U* }  exit(); % ~# \$ `" p9 t9 U7 |
 } ( h6 E8 Y- m- n4 f. t( V  u
$ u+ X) P7 k/ k! q* c6 x
 // 缓存中不存在该内容,生成新内容并写入缓存
8 E+ \8 w( i1 M! }8 _# h0 Q! a% [ echo "这是内容。<P>"; / _6 E: G/ o) I' R! p! {3 q
 echo "当前时间是" . date('M-d-Y H:i:s A', time()) . "<BR>";
& c/ l' y5 {/ K
; R) q% R# J) Q- R0 t- T& v$ o // 把内容写入缓存
4 q, q4 Z5 j! j; n echo $cache->end(); $ c8 r/ t1 G, c+ U- V5 [
?>
. B3 F+ q& o! ?' h+ r& w. O) |# A0 {5 |  L
  分别刷新这两个文件,你会发现pear_content_cache1.php中的“当前时间是”这一行中的时间是随着刷新而变化的,而pear_content_cache2.php中的这一行则不变。这是由于pear_content_cache2.php使用了缓存,将用户请求的内容存入静态文件中。当用户再次请求时,它直接从文件中输出,而不需要用程序动态生成内容。
/ ~6 U/ i, n- x+ R- F2 S& W& i+ y4 X: h$ i4 K  A: ^. H: C
  对于pear_content_cache2.php,如果用户想要读取最新的信息,而不是缓存中成旧的信息。那么可以用http://…/pear_content_cache2.php?nocache=1 来访问,这将禁用缓存功能。刷新一下看看,你将发现时间会随之变化。
5 L2 p& j, `( S
( i1 [4 }8 z' Y+ [. l; A  总结一下PEAR内容缓存类的使用:
. X; k  ^; v# o, i3 w2 |6 |* O5 p3 Y( Z9 i
  1.包含PEAR包 要注意设对路径。, n: ^/ I4 R- I+ ^
 
2 |  Q2 P( j  k7 ?  2.包含Output.php中的cache类
3 F+ h; n7 s/ Q/ l/ z+ v( f3 p. H# c( U  l/ o$ X2 ~
require_once 'Cache/Output.php';
$ W7 {& U* N5 r0 K+ Z
/ L0 J$ K  f4 Q$ J% S5 @7 i4 e2 M  3.设置缓存目录/ i) ?; z6 u0 R
; D. B: \* o: q8 {$ m8 {: V* s
$cacheDir = './pear_cache';
6 A$ q0 u0 h+ }# o, y& o. H. V6 V' z: ~+ d7 M
  确认这个目录是可写的。Cache数据将会写入这个目录的子目录中。
. v$ K# a! S9 N# k9 h4 g: W# {4 S8 R: l3 a, x
  4.建立一个输出缓存对象* [4 }" J% I; c% x

) B% w  g. U0 h; H( j$cache = new Cache_Output('file',array('cache_dir' => $cacheDir)); $ z1 Y2 B7 `/ l  T! g

+ Y- V1 F7 q; Q9 ^" p9 B) W  第一个参数表示我们使用基于“文件”方式的缓存,第二个参数是一个与缓存目录相关联的数组。4 X/ W4 V+ z. R( F
) c) Q. {0 @. G) x; }  A: g
  5.产生一个唯一的cache ID
' V# m/ g  U( B9 k' N$ H' p& t7 a
$cache_id = $cache->generateID(array('url' => $_REQUEST,'post' =>$_POST,'cookies' => $HTTP_COOKIE_VARS));
3 r3 D4 _& r& D
) y. ~' S* c- e$ |, p; d5 I  这里$cache对象的generateID()方法通过提供一个信息数组(URL, HTTP POST data, 和 HTTP cookie)来独一无二地标识这个请求,与其它请求区分开来。+ h& Q. [9 }! i8 t5 t) x6 v' J" y
! n0 M& `' r, r; n5 A
  6.增加一个逻辑判断语句看是否对应于cacheID的缓存数据是否已经存在,如果存在,获取数据并结束脚本。# B( _# h' x3 q$ Y2 D* b: ?
9 Z3 r. q1 c! n
if ($content = $cache->start($cache_id)) - }3 m- w* n3 t; m  ?+ l6 h
{ ( [8 D; i9 C5 C
 echo $content;
! h. f" I7 Y5 C+ G& \, q exit(); & [# X$ }; ]+ m4 E5 ^! G/ m% v" @, b
}
8 {0 X3 H- `; s, z3 R
0 q3 s3 X) G! y7 {$ c8 ?& h  7. 将产生内容的代码放在以上逻辑语句之后,并结束使用cache对象。/ a* F5 E  M: N. e3 D3 h2 C
! J6 t, ~. ~9 q: y& B
echo $cache->end();
" `' p2 N# G+ ?3 a0 l+ D5 g
2 w' s$ a$ @8 w( e  函数缓存输出 PEAR cache
' i  x" E; E8 U! w' e7 f  m( o% q; x$ P7 Z' U4 a( I6 G5 v8 e+ Y
  PEAR除了可以对输出的内容进行缓存处理外,还可以将对某个函数的调用结果缓存起来。这是个很有趣的功能,如果你的程序要频繁使用到某个函数,而且调用的结果相同的话,我建议你不妨试试,特别是当这个函数运行起来比较慢的时候。
- @$ J/ y9 f4 T0 {7 Q) G( y
3 ?1 I% \' h. W( R0 j" ]  下面我们实现对一个执行起来很慢的函数slowFunction()的缓冲调用。
6 c# l: k* ?0 e" H  I# K' s, k4 K$ v5 H/ d& j$ q
<?php
9 e+ Q: Z# g9 F5 f1 N: ^4 S/ u require_once 'Cache/Function.php'; : ?% c/ Q1 {( h5 Y1 h
! L6 p9 s3 g, H. S/ Z. x
 $cacheDir = './pear_cache/'; . O3 x! x  g# o1 p4 x8 f8 m* g
 $cache = new Cache_Function('file',array('cache_dir' => $cacheDir));
; }+ [5 h8 I  F0 K7 g2 x $arr = array('苹果', '梨','西瓜'); / k( J$ H, d, U9 ]: a, z
 $cache->call('slowFunction', $arr); & ~" w1 }: B# r: I0 [3 y& x
 echo '<BR>'; ! f, f2 e$ C( P0 C* H* I

1 i( \- c) Z7 L* v $arr = array('苹果', '梨','西瓜'); + Z1 P: O" s, p: p
 slowFunction($arr); * s0 J+ m1 i7 a# o! V, Z% Z

; j' `! ^2 K4 E  Z! } function slowFunction($arr = null)
6 G* ~* h/ j. P: q) w {
# f/ _$ W. `- ]7 U$ Y2 @# m, v: }  echo "一个执行起来很慢的函数 :( <br>";
4 d: r& n; k7 K% K; ?! q1 ?  echo "当前时间是 " . date('M-d-Y H:i:s A', time()) . '<br>'; ( w+ y$ T& t. N' b1 m( L
  foreach ($arr as $fruit)
$ Y3 m! n, u  E! I, t! j  {
- a5 z% H; C) C- H! O. W% v   echo "我吃了一个 $fruit <br>";
4 M# h- c  X. v  } 4 e9 w5 p3 j& i# k+ I/ A! R4 J
 )
7 s/ q! |* a" x2 J: z! s+ M6 f?>
  Y7 A& s- n9 X3 t9 l; V# o# U' t$ z% @$ S; \( _1 b) N% j  @
  以下是示例的脚本执行结果:0 Z2 N# B; f+ y5 w: e( Y/ e
/ ?) |7 Q( p+ h: U
  一个执行起来很慢的函数! g( H6 P, V$ q
: H& h+ [2 r! y4 `" B5 {
  当前时间是 Jul-28-2004 17:15:57 PM
, |' O5 B8 ?! c, d" Y0 r7 V  我吃了一个 苹果 - x% i, w, @' M) D8 ^  Y
  我吃了一个 梨 ; V; `! E6 b3 S$ ^6 T9 N
  我吃了一个 西瓜 6 g! o4 `' S) S+ p1 x
  G1 k8 G5 y9 ?) K0 Y
  一个执行起来很慢的函数 :( ! Z' a8 t2 L! S
  当前时间是 Jul-28-2004 17:17:55 PM
7 _6 s5 g- l7 r" b  我吃了一个 苹果
6 s9 V1 _) b$ s, l4 E+ a+ X  我吃了一个 梨 + ^* ^! t2 t9 K5 V8 i$ a7 c/ L
  我吃了一个 西瓜9 m; H+ Z+ u0 Q+ `+ M% a" d
3 O- p& n: S+ O+ A1 f& |6 q
  代码中,Cache/Function.php类用来执行函数缓冲功能。$cache变量是一个Cache_Function对象,使用基于文件的函数缓存,存入$cacheDir目录。要缓存一个函数调,Cache_Function对象$cache的call()方法要像这样使用:$cache->call(‘slowFunction’, $arr);5 i: e! e% x% J- l4 i' r( G

5 ~- C( k9 t: ^0 Z0 `. s6 {! ]  这里,slowFunction()函数被调用,参数为一个数组$arr,这个函数被缓存在$cacheDir目录下的一个文件里。任何在此之后的对这个函数的调用,将会由$cache->call()返回该函数执行的结果。 函数缓存和使用方法和内容缓存很相似,不再多说,具体请查看PEAR手册。
发新话题