最近写了段用纯真IP库查询IP地址的程序,我测了下,查询10000次需要18秒,CPU达到了48%大家看看怎么提升下效率。我是PHP新手,爱好提升程序性能,不过还在摸索<?php
class qqwry {
private $ipary;
private $firstip;
private $lastip;
private $iptotle;
function __construct($ipDataBase='qqwry.dat'){
$this->ipary=fopen($ipDataBase,'rb');
}
function __destruct(){
fclose($this->ipary);
}
function get($ip){
if ( !strpos($ip,'.') ) return 'invalid ip';
if (  preg_match('/^192\.168\.[\d\.]+$/',$ip) || preg_match('/^127\.0\.[\d\.]+$/',$ip) ) return '对方与你在同一局域网';
$this->firstip=$this->getlong();
$this->lastip=$this->getlong();
$this->iptotle=($this->lastip-$this->firstip)/7;
$ip=$this->ipToInt($ip); $searchF=0;
$searchE=$this->iptotle;
$findip=$this->iptotle; while ( $searchF <= $searchE ){
$searchM=floor(($searchF+$searchE)/2);
fseek($this->ipary,$this->firstip+$searchM*7); //直接从中间开始索引
$beginip=strrev(fread($this->ipary,4)); //获取IP开始地址
if ( $ip<$beginip ) {  //小于中间索引
$searchE=$searchM-1;
}else{
fseek($this->ipary,$this->getlong3());
$endip=strrev(fread($this->ipary,4)); // 获取中间记录的结束IP地址
if ( $ip>$endip ){
$searchF=$searchM+1;
}else{
$findip=$this->firstip+$searchM*7;
break;
}
}
}
//获取地址信息
fseek($this->ipary,$findip);
$ipstart=long2ip($this->getlong());
$offset=$this->getlong3();
fseek($this->ipary,$offset);
$ipend=long2ip($this->getlong());

$byte=fread($this->ipary,1); //标识 switch(ord($byte)){
case 1: // 标志字节为1,表示国家和区域信息都被同时重定向
$countryOffset=$this->getlong3();
fseek($this->ipary,$countryOffset);
$byte=fread($this->ipary,1);
switch(ord($byte)){
case 2:    // 标志字节为2,表示国家信息又被重定向  
fseek($this->ipary,$this->getlong3());
$country=$this->getstring();
fseek($this->ipary,$countryOffset+4);
$area=$this->getarea();
break;
default:
$country=$this->getstring($byte);
$area=$this->getarea();
break;
}
break;
case 2: //标志字节为2,表示国家信息被重定向
fseek($this->ipary,$this->getlong3());
$country=$this->getstring();
fseek($this->ipary,$offset+8);
$area=$this->getarea();
break;
default:// 否则,表示国家信息没有被重定向
$country=$this->getstring();
$area=$this->getarea();
break;
}
if ($country==='CZ88.NET'){
$country='未知';
}
if ($area==='CZ88.NET'){
$area='未知';
}
return $country.' '.$area;
}
private function getlong(){
$result=unpack('Vlong',fread($this->ipary,4));
return $result['long'];
}
private function getlong3(){
$result=unpack('Vlong',fread($this->ipary,3).chr(0));
return $result['long']; 
}
private function getstring($data='') {  
         $char = fread($this->ipary, 1);  
         while (ord($char) > 0) {
 $data .= $char;
             $char = fread($this->ipary, 1);
         }  
         return $data;
     }  
 private function getarea() {  
         $byte = fread($this->ipary, 1);    // 标志字节   
         switch (ord($byte)) {  
             case 0:                       // 没有区域信息  
                 $area = "";  
                 break;  
             case 1:
             case 2:                     // 标志字节为1或2,表示区域信息被重定向 
                 fseek($this->ipary, $this->getlong3());  
                 $area = $this->getstring();
                 break;  
             default:                    // 否则,表示区域信息没有被重定向  
                 $area = $this->getstring($byte);
                 break;  
         }  
         return $area;
     }  
private function ipToInt($ip){
if ( empty($ip) ) return;
if ( !strpos($ip,'.') ) return;
//$ip=explode('.',$ip);
//return ($ip[0]*256*256*256)+($ip[1]*256*256)+($ip[2]*256)+$ip[3]-256*256*256*256;
return pack('N', intval(ip2long($ip)));  
}
public static function getRemoteAddr(){
return $_SERVER['REMOTE_ADDR'];
}
}
$ip=$_GET['ip'];
if ( !isset($ip) ) $ip=qqwry::getRemoteAddr();
$q=new qqwry();
echo $q->get($ip);
?>