文档章节

解决Notice错误,性能竟然提升了1000多倍!

OneAPM蓝海讯通
 OneAPM蓝海讯通
发布于 2015/06/09 20:22
字数 2036
阅读 263
收藏 20

##先说PHP的deprecated错误的性能问题

最近刚刚完成了一个项目,在测试完基本功能后,我们就发布到线上。结果上线不久就发现产生了大量的错误,如下图:

一看都是PHP的Deprecated错误,是级别最低的那种。PHP官方手册对错误级别的解释如下:

参看:PHP官方说明

查找问题:

我们查看了第一条的详细信息, 发现问题是在common.ini.php 中使用了eregi函数,造成了Deprecated错误。问题代码在common.ini.php的52行。 下面我们去查看代码:发现是一个获取文件后缀名函数产生的错误: eregi('.([^.]*$)', $fileName, $ extension);

分析问题: 错误的原因是PHP不推荐使用eregi函数处理正则表达式。引用PHP官方5.3兼容文档,其表述如下:

链接地址是:http://php.net/manual/zh/migration53.deprecated.php PHP官方指出,PHP5.3不推荐使用eregi函数,建议使用preg_match函数代替。

解决问题: 接下来把eregi换成perg_match,然后对正则表达式进行修改。采用perg_match的代码如下:

preg_match('/.([^.]*$)/', $fileName, $ extension);

这样Deprecated错误就没有了。由此,Deprecated也引起了我的兴趣,这个错误到底会对性能有什么影响?一般情况下,Deprecated 错误即使不修复也不影响运行的,但是对性能是否会有影响呢?我们先做一个用error_reporting(0)关闭deprecated错误输出的对比试验。代码如下:

<?php $loop=10000; $date='2015-06-04'; 
$startTime = microtime(true); 
for($i=0;$i<$loop;$i++)
{
   if (ereg ("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $date, $regs)) 
   {         	
      echo "$regs[3].$regs[2].$regs[1]";     
   }   
   else
   {         
     	echo "Invalid date format: $date";     
   } 
} 
echo 'processing time: ', (microtime(true) - $startTime), "\r\n"; 

结果是

  • [有Deprecated] processing time: 0.51678085327148
  • [无Deprecated] processing time: 0.31887912750244

这是关闭error_reportingdisplay_error的对比结果。 数据表明,开启Deprecatederror_reporting后,性能比关闭下降了一倍。具体原因与接下来要阐述的Notice一样。我们可以再做个试验,分别写了两个PHP程序,一个是有deprecated错误的代码,一个是修复了deprecated的代码,代码如下:

<?php 
$loop=10000; 
$date='2015-06-04'; 
$startTime = microtime(true); 
for($i=0;$i<$loop;$i++){     
if (ereg ("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $date, $regs)) {
      echo "$regs[3].$regs[2].$regs[1]";     
} else {         
	echo "Invalid date format: $date";     
	} 
} 
echo 'ereg trigger deprecated: ', (microtime(true) - $startTime), "\r\n";
$startTime = microtime(true); 
for($i=0;$i<$loop;$i++){     
	if (preg_match("/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})/i", $date, $regs)) {         
	echo "$regs[3].$regs[2].$regs[1]";     
	} else {         
	echo "Invalid date format: $date";     
	} 
} 
echo 'trigger no deprecated: ', (microtime(true) - $startTime), "\r\n"; ?> 

跑起来看看结果:

trigger deprecated: 0.33528900146484
trigger no deprecated: 0.019602060317993

两的性能相差17.63倍!用preg_match 替换掉ereg后,不仅Deprecated错误没了,而且性能也大大提高了。性能提高的原因是PerlPOSIX处理正则表达式速度更快。Deprecated错误有潜在的兼容性问题,要引起大家的重视。所有提示Deprecated的函数都是官方不推荐使用的函数,今后新版的PHP有可能对其不兼容。最典型的案例是PHP5.5.0以后已经不再兼容mysql_querymysql_connect。要保证升级PHP版本后,程序正常运行,需要使用mysqliPDO来访问数据库。


上面我们讲了Deprecated错误对程序的性能影响和存在的潜在问题,那么Notice错误呢?是否也有类似问题?下面再给大家举个例子。

Notice错误对性能的影响

先看如下代码:

<?php 
$loop = 10000; 
$a = array(); 
$start_time = microtime(true); 
for ($i = 0; $i < $loop; ++$i) {     
	$a[$i]; 
    } 
echo 'processing time: ', (microtime(true) - $start_time), "\r\n"; 

结果如下:

  1. 对比开启与关闭display的性能 设置error_reporting(E_NOTICE)display_errors=on/off
  • [开启display] processing time: 5.4385099411011
  • [关闭display] processing time: 0.35786819458008 开启display,程序性能下降10多倍。 因为前端输出数据是比较耗费时间的。
  1. 对比开启与关闭error_reporting的性能(关闭display_errors) 设置error_reporting(0)或在表达式前加@
  • [开启Notice] processing time: : 0.35786819458008
  • [关闭Notice] processing time: : 0.2298538684845

开启Notice错误报告,程序性能下降近60%。为什么开启Notice错误报告,性能会下降如此之多呢?打开Notice错误报告后,当出现Notice错误时,程序会写日志,日志是文件IO操作,文件IO操作是比程序执行慢很多的,所以IO操作是造成性能下降的罪魁祸首。

Stackoverflow 也有人做过类似的研究,见下图。

链接地址:http://stackoverflow.com/questions/1868874/does-php-run-faster-without 如果修复了Notice后,性能提升多少呢?

<?php 
$loop = 10000; 
$a = array(); 
$start_time = microtime(true); 
for ($i = 0; $i < $loop; ++$i) {     
	$a[$i]; 
    } 
echo 'trigger notice: ', (microtime(true) - $start_time), "\r\n"; $start_time = microtime(true); 
for ($i = 0; $i < $loop; ++$i) {     
	isset($a[$i]) && $a[$i]; 
    } 
echo 'trigger no notice: ', (microtime(true) - $start_time), "\r\n"; 

与开启Notice报告和display, 设置error_reporting(E_NOTICE)display_errors=on, 结果如下:

trigger notice: 5.4385099411011
trigger no notice: 0.00056695938110352

两者的性能相差1000多倍!

##分析Notice错误 Notice: Undefined offset: 2 in xxx.php on line 8 Undefined xxxNotice中常见的错误,其表示没有定义该xxx变量就使用了。 大家对待该问题,通常是用关闭报告来解决,如error_reporting(0),此方法是治标不治本,Notice问题还是会出现。 我给出的解决办法是isset($a[ND$i])&&$a[$i]。解决了Notice错误后,性能立马提升1000多倍,**duang,duang,duang!**很爽吧。

从上面DeprecatedNotice的例子看,NoticeDeprecated造成的性能损耗要引起大家的重视,必须着手解决PHP应用中这些不起眼的错误了。


在着手解决问题前,我们都是怎么找DeprecatedNotice这些错误的呢?

开发、运维等童鞋都会说**“去抓log”**,像这个样子

首先,在线上系统中,DeprecatedNotice错误都是关闭的。日志中根本找不到DeprecatedNotice错误信息; 其次,有时log都非常大,有的能达到好几十G甚至上百G时,找错误是非常难的,而且不直观。

最近找到了一个比较好的工具**OneAPM**,大家可以尝试一下。

一、错误归类统计

它的错误信息功能用起来非常方便,DeprecatedNotice也都能抓取到,比查log方便多了。 在列表里能够看到所有的错误,以及发生次数,让我一下子就能知道各个错误造成的影响。

二、定位问题准确

针对每一个具体的问题,从错误详细信息中,能够精确定位到错误所在文件和行数,直接就看到bug的位置,不错。

三、管理项目方便

因为管理项目较多,一直想找比较好的工具统一管理各个项目,OneAPM帮我解决了这个问题。 从上图中能观察不同项目的运行情况,当某些项目的错误率升高了,不仅能收到短信和邮件报警,而且直接能找到项目的错误信息,查找问题方便许多。

##同时有些问题也想跟OneAPM说一下

一、没有按照错误原因归类功能,如下图

这里的所有Notice都是一个php文件的同一行代码造成的,如果能有归类,这样我能够统计该错误发生的次数。

二、增加搜索功能

有时我就想先查找关心的错误,如errorwarning的错误,但是整个列表里大部分是NoticeDeprecated,现在让我找重要错误比较困难。

三、报表中也希望增加对错误信息的报告

到这里我们对NoticeDeprecated有了更深刻的认识,以往我们都不关心这类错误,存在没想到有这么大的影响。 过去从错误日志查问题的方式已经过去。现在借助OneAPM实现错误信息的实时美观地反馈,并能得到错误分析报表。

OneAPM是中国基础软件领域的新兴领军企业,能帮助企业用户和开发者轻松实现:缓慢的程序代码和SQL语句的实时抓取。想阅读更多技术文章,请访问OneAPM官方技术博客

© 著作权归作者所有

OneAPM蓝海讯通
粉丝 94
博文 631
码字总数 1266889
作品 0
海淀
私信 提问
MySQL 百万级分页优化(Mysql千万级快速分页)

一般刚开始学SQL的时候,会这样写复制代码 代码如下: 但在数据达到百万级的时候,这样写会慢死复制代码 代码如下: 也许耗费几十秒 网上很多优化的方法是这样的复制代码 代码如下: 是的,速度...

yiqifendou
2016/10/11
185
0
Greenplum 6已合并到PostgreSQL 9.3版本 - 比上一代GP提升:8倍读,195倍更新、删除 - 另有大量PG新特性

标签 PostgreSQL , Greenplum , 6 , gin , 异步事务 背景 Greenplum 6已合并到PostgreSQL 9.3版本 - 相比5性能提升:读8倍,更新、删除195倍 - 另有大量PG新特性,详见PostgreSQL release no...

德哥
04/14
0
0
异数OS闭源社区邀请C++大牛加入一同建设闭源生态

异数OS闭源社区邀请C++大牛加入一同建设,异数OS使用大量C++元编程静态优化等技术来实作操作系统以及上层应用,解除操作系统IO性能瓶颈,释放IO型应用性能,为IO型应用提速10到100倍,是未来...

心海1
2018/08/09
0
0
C# EF6 更新对象

该文件主要是在记录C#过程中级联更新问题。该问题主要是在对数据库中的对象中的关联进行更新,导致出现了极大的性能问题,希望有这方面的专家能给出建设性的意见和方向。 class Student{ int...

RainyZou
2016/01/11
242
0
如何优化Mysql千万级快速分页

看例子: 数 据表 collect ( id, title ,info ,vtype) 就这4个字段,其中 title 用定长,info 用text, id 是逐渐,vtype是tinyint,vtype是索引。这是一个基本的新闻系统的简单模型。现在往里...

上品好礼生活馆
2014/09/18
356
1

没有更多内容

加载失败,请刷新页面

加载更多

计算机实现原理专题--二进制减法器(二)

在计算机实现原理专题--二进制减法器(一)中说明了基本原理,现准备说明如何来实现。 首先第一步255-b运算相当于对b进行按位取反,因此可将8个非门组成如下图的形式: 由于每次做减法时,我...

FAT_mt
昨天
6
0
好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
昨天
7
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
昨天
6
0
【技术分享】TestFlight测试的流程文档

上架基本需求资料 1、苹果开发者账号(如还没账号先申请-苹果开发者账号申请教程) 2、开发好的APP 通过本篇教程,可以学习到ios证书申请和打包ipa上传到appstoreconnect.apple.com进行TestF...

qtb999
昨天
10
0
再见 Spring Boot 1.X,Spring Boot 2.X 走向舞台中心

2019年8月6日,Spring 官方在其博客宣布,Spring Boot 1.x 停止维护,Spring Boot 1.x 生命周期正式结束。 其实早在2018年7月30号,Spring 官方就已经在博客进行过预告,Spring Boot 1.X 将维...

Java技术剑
昨天
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部