邢栋博客
邢栋博客,Action博客,记录工作和生活中的点点滴滴
php xhprof扩展的安装和测试使用
安装
wegt http://pecl.php.net/get/xhprof-0.9.4.tgz
tar zxvf xhprof-0.9.4.tgz
cd xhprof-0.9.4/extension/
/alidata/server/php/bin/phpize //我的php的安装目录是/alidata/server/php
./configure --with-php-config=/alidata/server/php/bin/php-config
make && make install
然后打开php的配置文件
vim /alidata/server/php/etc/php.ini
加入以下代码
extension=xhprof.so
xhprof.output_dir=/tmp/xhprof
重启php
killall php-fpm
php-fpm
然后执行php -m 就可以看到xhprof 这个模块
或者执行 php --ri xhprof 也可以
会看到
xhprof
xhprof => 0.9.2
CPU num => 1
xhprof 自带了一个测试的例子
把expmple/simple.php(只复制simple.php文件),xhprof_html/,xhprof_lib/ 拷贝到你的程序目录下
打开simple.php
将xhprof_enable()改为
xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY)
让它也显示cpu和内存信息
将最后一段echo一行修改为:
echo '<a href="/xhprof_html/index.php?run='.$run_id.'&source=xhprof_foo" target="_blank">count</a>';
然后运行此php文件
XHProf输出说明
1. Inclusive Time : 包括子函数所有执行时间。
2. Exclusive Time/Self Time : 函数执行本身花费的时间,不包括子树执行时间。
3. Wall Time : 花去了的时间或挂钟时间。
4. CPU Time : 用户耗的时间+ 内核耗的时间
5. Inclusive CPU : 包括子函数一起所占用的CPU
6. Exclusive CPU : 函数自身所占用的CPU
php vld扩展测试抑制符@性能
vld php Opcode查看扩展
安装vld扩展
下载 http://pecl.php.net/package/vld
# tar zxvf vld-0.13.0.tgz
# cd ./vld-0.11.1
# /alidata/server/php/bin/phpize
# ./configure --with-php-config=/alidata/server/php/bin/php-config --enable-vld
# make && make install
修改php.ini加入
extension=vld.so
重启php-fpm nginx
新建php文件
<?php
phpinfo();
?>
可以看到vld扩展
新建一个ceshi.php
<?php
file_get_contents('xingdong365');
//@file_get_contents('xingdong365');
?>
执行php -dvld.active=1 -dvld.execute=0 ceshi.php
<?php
//file_get_contents('xingdong365');
@file_get_contents('xingdong365');
?>
如图所示
可见使用@抑制符会产生额外开销
linux编译php7后找不到php.ini
最后解决办法
执行
/server/php7/bin/php --ini
显示
Configuration File (php.ini) Path: /server/php7/lib/
Loaded Configuration File: (none)
Scan for additional .ini files in: (none)
Additional .ini files parsed: (none)
php.ini位置修改方法如下:
编辑php时
./configure --prefix=/server/php7/ --with-config-file-path=/etc --disable-fileinfo
就是加上 --with-config-file-path=/etc
然后在源码中找到php.ini-development 和 php.ini-production
拷贝php.ini-development 到etc 目录下为 php.ini
cp php.ini-development /etc/php.ini
php二分法查找键值
1.递归,也可用来做插值查找
<?php //search函数 其中$array为数组,$k为要找的值,$low为查找范围的最小键值,$high为查找范围的最大键值 function seekKey($array, $k, $low=0, $high=0){ //判断是否为第一次调用 if(count($array)!=0 && $high == 0){ $high = count($array); } if($low <= $high){//如果还存在剩余的数组元素 $mid = intval(($low+$high)/2);//取$low和$high的中间值 if ($array[$mid] == $k){//如果找到则返回 return $mid; }elseif ($k < $array[$mid]){//如果没有找到,则继续查找 return seekKey($array, $k, $low, $mid-1); }else{ return seekKey($array, $k, $mid+1, $high); } } return -1; } $array = array(4,5,7,8,9,10);//测试search函数 echo seekKey($array, 9);//调用search函数并输出查找结果2.while
<?php $arr = array(1,2,3,4,5,6,7,8,9,10); function search($data,$num){ $count = count($data); $high = $count-1; $low = 0; while($high >= $low){ $mid = intval(($high+$low)/2); if($data[$mid] > $num){ $high = $mid-1; }elseif($data[$mid] < $num){ $low = $mid+1; }else{ return $mid; } } return -1; } $res = search($arr,4); var_dump($res);
php几个常用的关于路径的函数
<?php
$a = getcwd();
var_dump($a);//string 'D:\wamp\www\ceshi' (length=17)
?>
__FILE__
<?php
echo __FILE__;//'D:\wamp\www\ceshi\ceshi.php'
?>
pathinfo — 返回文件路径的信息
<?php
$a = pathinfo(__FILE__);
var_dump($a);
/*array (size=4)
'dirname' => string 'D:\wamp\www\ceshi' (length=17)
'basename' => string 'ceshi.php' (length=9)
'extension' => string 'php' (length=3)
'filename' => string 'ceshi' (length=5)*/
?>
dirname — 返回路径中的目录部分
<?php
$a = dirname(__FILE__);
var_dump($a);//string 'D:\wamp\www\ceshi' (length=17)
?>
basename — 返回路径中的文件名部分
<?php
$a = basename(__FILE__);
var_dump($a);//string 'ceshi.php' (length=9)
?>
realpath — 返回规范化的绝对路径名
//在 Windows 上, realpath() 会将 unix 风格的路径改成 Windows 风格的
<?php
echo realpath ( '/windows/system32' );//C:\WINDOWS\System32
?>
php内存管理之引用计数
$a = 'Hello World';
$b = $a;
unset($a);
?>
第一条语句执行后,PHP创建了$a这个变量,并为它申请了12B的内存来存放"hello world"这个字符串. 紧接着把$a赋给了$b,并释放掉$a;
PHP变量的名称和值在内核中是保存在两个不同的地方的,值是通过一个与名字毫无关系的zval结构来保存,而这个变量的名字a则保存在符号表里,两者之间通过指针联系着.
现在我们检查$a和$b两个变量,他们的值指向了"hello world"这个字符串在内存中的位置. zval的四个成员value、type、is_ref__gc、refcount__gc,
当一个变量被第一次创建的时候,它对应的zval结构体的refcount__gc成员的值会被初始化为1,理由很简单,因为只有这个变量自己在用它。但是当你把这个变量赋值给别的变量时,refcount__gc属性便会加1变成2,因为现在有两个变量在用这个zval结构了!
这个时候当我们再用unset删除$a的时候,它删除符号表里的$a的信息,然后清理它的值部分,这时它发现$a的值对应的zval结构的refcount值是2,也就是有另外一个变量在一起用着这个zval,所以unset只需把这个zval的refcount减去1就行了!
写时复制机制
<?php
$a = 1;
$b = $a;
$b += 5;
?>
从代码逻辑来看,我们希望语句执行后$a仍然是1,而$b则需要变成6。我们知道在第二句完成后内核通过让$a和$b共享一个zval结构来达到节省内存的目的,但是现在第三句来了,这时$b的改变应该怎样在内核中实现呢? 答案非常简单,内核首先查看refcount__gc属性,如果它大于1则为这个变化的变量从原zval结构中复制出一份新的专属与$b的zval来,并改变其值。
现在$b变量拥有了自己的zval,并且可以自由的修改它的值了。
Change on Write
<?php
$a = 1;
$b = &$a;
$b += 5;
?>
我们都知道$a的值也变成6了。当我们更改$b的值时,内核发现$b是$a的一个用户端引用,也就是所它可以直接改变$b对应的zval的值,而无需再为它生成一个新的不同与$a的zval。因为他知道$a和$b都想得到这次变化! 但是内核是怎么知道这一切的呢?简单的讲,它是通过zval的is_ref__gc成员来获取这些信息的。这个成员只有两个值,就像开关的开与关一样。它的这两个状态代表着它是否是一个用户在PHP语言中定义的引用。在第一条语句($a = 1;)执行完毕后,$a对应的zval的refcount__gc等于1,is_ref__gc等于0;。 当第二条语句执行后($b = &$a;),refcount__gc属性向往常一样增长为2,而且is_ref__gc属性也同时变为了1! 最后,在执行第三条语句的时候,内核再次检查$b的zval以确定是否需要复制出一份新的zval结构来,这次不需要复制,因为我们刚才上面的get_var_and_separate函数其实是个简化版,并且少写了一个条件:
/* 如果这个zval在php语言中是通过引用的形式存在的,或者它的refcount小于2,则不许要复制。*/
if ((*varval)->is_ref || (*varval)->refcount < 2) {
return *varval;
}
这一次,尽管它的refcount等于2,但是因为它的is_ref等于1,所以也不会被复制。内核会直接的修改这个zval的值
Separation Anxiety
<?php
$a = 1;
$b = $a;
$c = &$a;
?>

<?php
$a = 1;
$b = &$a;
$c = $a;
?>
PS:http://www.walu.cc/phpbook/3.2.md
php获取网页头部信息相关
php设置头部
<?php
header("HTTP/1.0 404 Not Found");
//header("HTTP/1.0 204 No Response");
?>
php通过内置函数获取头部信息
<?php
//$header = get_headers('http://xingdong365.com');
$header = get_headers('http://xingdong365.com',1);//会解析相应的信息并设定数组的键名
echo "<pre>";
print_r($header);
echo "</pre>";
?>
php通过curl获取头部信息
<?php
var_dump(get_header('http://xingdong365.com'));
function get_header($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY,true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true);
curl_setopt($ch, CURLOPT_AUTOREFERER,true);
$header = curl_exec($ch);
return $header;
}
?>
php curl并发测试
test.php
<?php
function multiCurl($res, $options=""){
if(count($res)<=0) return False;
$handles = array();
if(!$options) // add default options
$options = array(
CURLOPT_HEADER=>0,
CURLOPT_RETURNTRANSFER=>1,
CURLOPT_TIMEOUT=>1,//超时时间
);
// add curl options to each handle
foreach($res as $k=>$row){
$ch{$k} = curl_init();
$options[CURLOPT_URL] = $row['url'];
$opt = curl_setopt_array($ch{$k}, $options);
var_dump($opt);
$handles[$k] = $ch{$k};
}
$mh = curl_multi_init();
// add handles
foreach($handles as $k => $handle){
$err = curl_multi_add_handle($mh, $handle);
}
$running_handles = null;
do {
curl_multi_exec($mh, $running_handles);
curl_multi_select($mh);
} while ($running_handles > 0);
foreach($res as $k=>$row){
$res[$k]['error'] = curl_error($handles[$k]);
if(!empty($res[$k]['error']))
$res[$k]['data'] = '';
else
$res[$k]['data'] = curl_multi_getcontent( $handles[$k] ); // get results
// close current handler
curl_multi_remove_handle($mh, $handles[$k] );
}
curl_multi_close($mh);
return $res; // return response
}
$res = array(
"0"=>array("url"=>"http://localhost/curl/test1.php"),
"1"=>array("url"=>"http://localhost/curl/test2.php"),
"2"=>array("url"=>"http://localhost/curl/test3.php"),
);
echo "<pre>";
print_r( multiCurl($res));
echo "</pre>";
?>
---------------------------------------------------------------------------
test1.php
<?php
sleep(1);
echo test1;
?>
test2.php
<?php
sleep(2);
echo test2;
?>
test3.php
<?php
sleep(3);
echo test3;
?>