首页 > 编程技术 > php

PHP开发程序加速运行探索之慢代码优化方法

发布时间:2016-11-25 16:32

把握了PEAR::BenchMark,现在你已经知道如何测试你的代码,知道如何判定你的代码是快是慢,是哪一部份比较慢。那么接下来我要说的就是如何消灭或优化那部份慢的代码。

  这一点上我个人最主要的经验只有两点,一是消除错误的或低效的循环;二是优化数据库查询语句。其实还存在一些其它的优化细节,比如“str_replace比ereg_replace快”、“echo比print快”等等。这些我暂时都放在一边,稍后我会提到用缓存来对付过于频繁的IO。

  下面我们将三个功能相同,但程序写法不同的函数的效率(消耗的时间)进行对比。

  badloops.php

<?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 '<br>';
 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 '<!--' . $myArray[$i] . ' --> ';
 }
}


function v2($myArray = null) {
 // 效率略有提高
 $max = sizeof($myArray);
 for ($i =0; $i < $max ; $i )
 {
  echo '<!--' . $myArray[$i] . ' --> ';
 }
}

function v3($myArray = null){
 //最佳效率
 echo "<!--", implode(" --> <!--", $myArray), " --> ";
}

?>


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

  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程序都会用到,在实际开发中我发现最影响整个系统效率的就是数据库这部份。至于数据库的优化和数据查询语句的优化,在此限于篇幅不具体讨论。

<?php

//
// Function: 获取远程图片并把它保存到本地
//
//
// 确定您有把文件写入本地服务器的权限
//
//
// 变量说明:
// $url 是远程图片的完整URL地址,不能为空。
// $filename 是可选变量: 假如为空,本地文件名将基于时间和日期
// 自动生成.

function GrabImage($url,$filename="") {
if($url==""):return false;endif;

if($filename=="") {
$ext=strrchr($url,".");
if($ext!=".gif" && $ext!=".jpg"):return false;endif;
$filename=date("dMYHis").$ext;
}

ob_start();
readfile($url);
$img = ob_get_contents();
ob_end_clean();
$size = strlen($img);

$fp2=@fopen($filename, "a");
fwrite($fp2,$img);
fclose($fp2);

return $filename;
}


$img=GrabImage("http://news.bbc.co.uk/images/_1978837_detector_ap100.jpg","");
if($img):echo '<pre><img" width=100% src="'.$img.'"></pre>';
else:echo "false";
endif;

?>

<?PHP
//====================================================
//        FileName:    snap.class.php
//        Summary:    网页快照类
//        Author:        millken(迷路林肯)
//        LastModifed:2007-06-29
//        copyright (c)2007 [email]millken@gmail.com[/email]
//====================================================
class snap{
    var $dir;
    var $log;
    var $contents;
    var $filename;
    var $host;
    var $name;
    var $data_ts;
    var $ttl;
    var $url;
    var $ts;
    function snap(){
        $this->log = "New snap() object instantiated.<br />n";  
        $this->dir = dirname(__FILE__)."/";
    }
    function fetch($url="",$ttl=10){
        $this->log .= "--------------------------------<br />fetch() called<br />n";
        $this->log .= "url: ".$url."<br />n";
        $hosts = parse_url($url);
        $this->host = $hosts['scheme'].'://'.$hosts['host'].'/';
        if (!$url) {
            $this->log .= "OOPS: You need to pass a URL!<br />";
            return false;
        }
        $this->ttl = $ttl;
        $this->url = $url;
        $this->name = md5($this->url);
        $this->filename = $this->dir.$this->name;
        $this->log .= "Filename: ".$this->filename."<br />";
        $this->getFile_ts();
        $this->file_get_content();

    }
    function file_get_content(){
        ob_start();
        $this->ts = time() - $this->data_ts;
        if($this->data_ts <>0 && $this->ts <= $this->ttl){
            $this->log .= "cache has expired<br />";
            @readfile($this->filename);  
            $this->contents = ob_get_contents();
            ob_end_clean();
        }else{
            $this->log .= "cache hasn't expired<br />";       
            @readfile($this->url);  
            $this->contents = ob_get_contents();
            ob_end_clean();
            $this->saveToCache();
        }
        return true;
    }
    function saveToCache(){
        $this->log .= "saveToCache() called<br />";
        //create file pointer
        if (!$fp=@fopen($this->filename,"w")) {
            $this->log .= "Could not open ".$this->filename."<br />";
            return false;
        }
        $this->contents = $this->formaturl($this->contents,$this->host);
        $this->contents = preg_replace("'<script[^>]*?>.*?</script>'si","",$this->contents);
        //write to file
        if (!@fwrite($fp,$this->contents)) {
            $this->log .= "Could not write to ".$this->filename."<br />";
            fclose($fp);
            return false;
        }
        //close file pointer
        fclose($fp);
        return true;
    }
    function getFile_ts(){
        $this->log .= "getFile_ts() called<br />";
        if (!file_exists($this->filename)) {
            $this->data_ts = 0;
            $this->log .= $this->filename." does not exist<br />";
            return false;
        }
        $this->data_ts = filemtime($this->filename);
        return true;
    }
    function formaturl($l1,$l2){
    if (preg_match_all("/(<img[^>]+src=\"([^\"]+)\"[^>]*>)|(<link[^>]+href=\"([^\"]+)\"[^>]*>)|(<a[^>]+href=\"([^\"]+)\"[^>]*>)|(<img[^>]+src='([^']+)'[^>]*>)|(<a[^>]+href='([^']+)'[^>]*>)/i",$l1,$regs)){
      foreach($regs[0] as $num => $url){
       $l1 = str_replace($url,$this->lIIIIl($url,$l2),$l1);
      }
    }
    return     $l1;
    }

    function lIIIIl($l1,$l2){
    if(preg_match("/(.*)(href|src)=(.+?)( |/>|>).*/i",$l1,$regs)){$I2 = $regs[3];}
    if(strlen($I2)>0){
      $I1 = str_replace(chr(34),"",$I2);
      $I1 = str_replace(chr(39),"",$I1);
    }else{return $l1;}
    $url_parsed = parse_url($l2);
    $scheme      = $url_parsed["scheme"];if($scheme!=""){$scheme = $scheme."://";}
    $host      = $url_parsed["host"];  
    $l3       = $scheme.$host;
    if(strlen($l3)==0){return $l1;}
    $path      = dirname($url_parsed["path"]);if($path[0]=="\"){$path="";}
    $pos      = strpos($I1,"#");
    if($pos>0) $I1 = substr($I1,0,$pos);
    //判断类型
    if(preg_match("/^(http|https|ftp):(//|\\)(([w/\+-~`@:%])+.)+([w/\.=?+-~`@':!%#]|(&)|&)+/i",$I1)){return $l1; }//http开头的url类型要跳过
    elseif($I1[0]=="/"){$I1 = $l3.$I1;}//绝对路径
    elseif(substr($I1,0,3)=="../"){//相对路径
          while(substr($I1,0,3)=="../"){
       $I1 = substr($I1,strlen($I1)-(strlen($I1)-3),strlen($I1)-3);
       if(strlen($path)>0){
        $path = dirname($path);
       }
      }
      $I1 = $l3.$path."/".$I1;
    }
    elseif(substr($I1,0,2)=="./"){
      $I1 = $l3.$path.substr($I1,strlen($I1)-(strlen($I1)-1),strlen($I1)-1);
    }
    elseif(strtolower(substr($I1,0,7))=="mailto:"||strtolower(substr($I1,0,11))=="java script:"){
      return $l1;
    }else{
      $I1 = $l3.$path."/".$I1;
    }
    return str_replace($I2,"\"$I1\"",$l1);
    }
}
?>
 

用法test.php:

 <?php
require_once(dirname(__FILE__).'/snap.class.php');
$h = new snap();
$h->fetch($_GET['url']);
//echo $h->log;
echo $h->contents;
?>

方法一. 注重这里有一个预先定义的图片记录集rsmpic 要横向重复的就是图片,请根据你的情况改为你的记录集名称.整洁地将横向重复内容放在一个表格内


<table width="100" border="0" align="center" cellpadding="5" cellspacing="5">

<?php $startrw = '0';// 开始定义横向重复内容 这里设定为 3 行 3 列
$endrw = $HLooper1__index;
$numberColumns = '3';
$numrows = '3';
while(($numrows <> 0) AND (!$rsmpic->EOF))
{
$startrw = $endrw 1;
$endrw = $endrw $numberColumns;?>

<tr>
<?php While (($startrw <= $endrw) AND (!$rsmpic->EOF)) { //开始重复内容?>

<td>
<table width="78%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td><img" width=100% src="../<?php echo $rsmpic->Fields('M_Path'); ?>" border="0"></td>
</tr>
</table>

</td>

<?php
$startrw = $startrw 1;
$rsmpic->MoveNext();}//以上重复td内容 ?>

</tr>

<?php $numrows=$numrows-1;
Wend; } //重复内容结束 ?>
</table>


方法二. 将重复标记拖到<td>外(纵向重复是在<tr>外),加入一个变量, 每重复 1 次加 1, 假如%3等于0 echo 一个"<tr>" . 请仔细看




<table width="100%" border="1" cellspacing="1" cellpadding="5">
<tr>
<?php $str=0;// 开始定义重复函数?>
<?php do { //开始重复?>

<td>
<?php $str ;?>
<?php echo $str; ?>.<?php echo $row_Recordset1['NAME']; ?>
</td>
<?php if ($str%3==0)echo "<tr>"; ?>

<?php } while ($row_Recordset1 = mysql_fetch_assoc($Recordset1)); // 重复td内容?>
</tr>

</table>

flex+php在线拍照

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="100%"  xmlns:ns1="*" backgroundGradientColors="[#ecf9ff, #ecf9ff]" height="100%"  xmlns:ns2="view.*" creationComplete="initApp()">
  <mx:Style>
        Alert{font-size:12px;}
    </mx:Style>
    <mx:Script>
        <![CDATA[
            import mx.events.CloseEvent;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import mx.controls.Alert;
             import mx.managers.CursorManager;
            private static const DEFAULT_CAMERA_WIDTH:Number = 160; //摄像头显示宽度
            private static const DEFAULT_CAMERA_HEIGHT:Number = 120; //摄像头显示高度
            private static const DEFAULT_WEBSERVICE_URL:String = "http://localhost:1888/Web/TestWebService.asmx?WSDL"; //WebService地址
           
            private var m_camera:Camera; //定义一个摄像头
            private var m_localVideo:Video; //定义一个本地视频
            private var m_pictureBitmapData:BitmapData //定义视频截图
            private var pic_width:int;
            private var pic_height:int;
            //[Bindable]
            private var m_pictureData:String;
           
            private function initApp():void
            {
                t_btn_Shooting.enabled = false;
                t_ban_Save.enabled = false;
                initCamera();
               pic_height=m_camera.height;
               pic_width=m_camera.width;
            }
           
            //初始化摄像头
            private function initCamera():void
            {
                m_camera = Camera.getCamera();
                if(m_camera != null)
                {
                    m_camera.addEventListener(StatusEvent.STATUS,__onCameraStatusHandler);
                   
                    m_camera.setMode(DEFAULT_CAMERA_WIDTH,DEFAULT_CAMERA_HEIGHT,30);
                    m_localVideo = new Video();
                    m_localVideo.width = DEFAULT_CAMERA_WIDTH;
                    m_localVideo.height = DEFAULT_CAMERA_HEIGHT;
                    m_localVideo.attachCamera(m_camera);
                    t_vd_Video.addChild(m_localVideo);
                }
                else
                {
                    Alert.show("没有找到摄像头,是否重新查找。","提示:",Alert.OK|Alert.NO,this,__InitCamera);
                    return;
                }
            }
           
            //拍照按钮事件,进行视频截图
            private function SnapshotPicture():void
            {
                m_pictureBitmapData = new BitmapData(DEFAULT_CAMERA_WIDTH,DEFAULT_CAMERA_HEIGHT);
                m_pictureBitmapData.draw(t_vd_Video,new Matrix());
               
                var m_pictureBitmap:Bitmap = new Bitmap(m_pictureBitmapData);
                t_img_Picture.addChild(m_pictureBitmap);
               
                t_panel_Picture.visible = true;
                t_ban_Save.enabled = true;
            }
           
            //保存按钮事件,保存视频截图
            //通过WebService保存
            private function SavePicture():void
            {
                m_pictureData = "";
                //m_pictureBitmapData.setPixel(1,1,6558750);
                //label1.text=m_pictureBitmapData.getPixel(1,1).toString();
               
                for(var i:int = 0; i < DEFAULT_CAMERA_WIDTH; i++)
                {
                    for(var j:int = 0; j < DEFAULT_CAMERA_HEIGHT; j++)
                    {
                        if(m_pictureData.length > 0)
                        {
                            m_pictureData += "," + m_pictureBitmapData.getPixel(i,j).toString();
                        }
                        else
                        {
                            m_pictureData = m_pictureBitmapData.getPixel(i,j).toString();
                        }
                    }
                }
                service.getOperation("createjpeg").send(pic_width,pic_height,m_pictureData);
               // t_ws_SavePicture.SavePicture.send();
              
            }
            internal function faultHandler(evt:FaultEvent):void{
   //labelresult.text="error";
   CursorManager.removeBusyCursor();
   Alert.show("保存出错","提示",Alert.YES,this);
   
  }
  internal function createImage(evt:ResultEvent):void{
      //dg_article.dataProvider=evt.result; 
      CursorManager.removeBusyCursor();
   Alert.show("保存成功","提示",Alert.YES,this);
   var date:Date=new Date();
   this.left.headerphoto.source="http://www.tiyi88.com/image/header/0.jpg?id="+date.getMilliseconds();
  }
            //检测摄像头权限事件
            private function __onCameraStatusHandler(event:StatusEvent):void
            {
                if(!m_camera.muted)
                {
                    t_btn_Shooting.enabled = true;
                }
                else
                {
                    Alert.show("无法链接到活动摄像头,是否重新检测。","提示:",Alert.OK|Alert.NO,this,__InitCamera);
                }
                m_camera.removeEventListener(StatusEvent.STATUS,__onCameraStatusHandler);
            }
           
            //当摄像头不存在,或连接不正常时重新获取
            private function __InitCamera(event:CloseEvent):void
            {
                if(event.detail == Alert.OK)
                {
                    initApp();
                }
            }
        ]]>
    </mx:Script>
    <mx:RemoteObject id="service" fault="faultHandler(event)" showBusyCursor="true"
              source="image" destination="amfphp">
  <!--定义远程方法-->
  <mx:method name="createjpeg" result="createImage(event)"/>
  </mx:RemoteObject>
 <ns1:header x="137" y="10">
 </ns1:header>
 <ns1:left1 x="137" y="158" id="left">
 </ns1:left1> 
  <mx:Panel x="406" y="158" width="180" height="232" layout="absolute" title="视频拍照" fontSize="12">
        <mx:VideoDisplay id="t_vd_Video" width="160" height="146"/>
        <mx:ControlBar horizontalAlign="right">
            <mx:Button id="t_btn_Shooting" label="拍照" click="SnapshotPicture()"/>
        </mx:ControlBar>
    </mx:Panel>
    <mx:Panel id="t_panel_Picture" x="647" y="158" width="180" height="232" layout="absolute" title="拍照图片" fontSize="12" visible="false">
        <mx:Image id="t_img_Picture" x="0" y="0" width="160" height="144"/>
        <mx:ControlBar  horizontalAlign="right">
            <mx:Button id="t_ban_Save" label="保存" click="SavePicture()" />
        </mx:ControlBar>
    </mx:Panel>
</mx:Application>

绘制头像文件:

<?php
class Image{
 
 public function createjpeg($width,$height,$bitmap_data)
 {
  $img=imagecreatetruecolor($width,$height);
  $m_tempPics=explode(',',$bitmap_data);
   for ($i = 0; $i < $width; $i++)
            {
                for ($j = 0; $j < $height; $j++)
                {
                    $pic_argb =(int) $m_tempPics[$i * $height + $j];
                    imagesetpixel($img,$i,$j,$pic_argb);
                }
            }
        imagejpeg($img,"../../image/header/0.jpg");
        imagedestroy($img);
        return true;
 }
}
?>

标签:[!--infotagslink--]

您可能感兴趣的文章: