解决Notice错误,性能竟然提升了1000多倍!
先说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_reporting
和display_error
的对比结果。
数据表明,开启Deprecated
的error_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
错误没了,而且性能也大大提高了。性能提高的原因是Perl
比POSIX
处理正则表达式速度更快。Deprecated
错误有潜在的兼容性问题,要引起大家的重视。所有提示Deprecated
的函数都是官方不推荐使用的函数,今后新版的PHP有可能对其不兼容。最典型的案例是PHP5.5.0以后已经不再兼容mysql_query
和mysql_connect
。要保证升级PHP版本后,程序正常运行,需要使用mysqli
和PDO
来访问数据库。
上面我们讲了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";
结果如下:
- 对比开启与关闭display的性能
设置error_reporting(E_NOTICE)
,display_errors=on/off
,
- [开启display] processing time: 5.4385099411011
- [关闭display] processing time: 0.35786819458008
开启display,程序性能下降10多倍。
因为前端输出数据是比较耗费时间的。
- 对比开启与关闭
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 xxx
是Notice
中常见的错误,其表示没有定义该xxx变量就使用了。
大家对待该问题,通常是用关闭报告来解决,如error_reporting(0)
,此方法是治标不治本,Notice
问题还是会出现。
我给出的解决办法是isset($a[ND$i])&&$a[$i]
。解决了Notice
错误后,性能立马提升1000多倍,duang,duang,duang!很爽吧。
从上面Deprecated
和Notice
的例子看,Notice
和Deprecated
造成的性能损耗要引起大家的重视,必须着手解决PHP应用中这些不起眼的错误了。
在着手解决问题前,我们都是怎么找Deprecated
和Notice
这些错误的呢?
开发、运维等童鞋都会说“去抓log”,像这个样子
首先,在线上系统中,Deprecated
和Notice
错误都是关闭的。日志中根本找不到Deprecated
和Notice
错误信息;
其次,有时log
都非常大,有的能达到好几十G甚至上百G时,找错误是非常难的,而且不直观。
最近找到了一个比较好的工具OneAPM,大家可以尝试一下。
一、错误归类统计
它的错误信息功能用起来非常方便,Deprecated
和Notice
也都能抓取到,比查log
方便多了。
在列表里能够看到所有的错误,以及发生次数,让我一下子就能知道各个错误造成的影响。
二、定位问题准确
针对每一个具体的问题,从错误详细信息中,能够精确定位到错误所在文件和行数,直接就看到bug的位置,不错。
三、管理项目方便
因为管理项目较多,一直想找比较好的工具统一管理各个项目,OneAPM帮我解决了这个问题。
从上图中能观察不同项目的运行情况,当某些项目的错误率升高了,不仅能收到短信和邮件报警,而且直接能找到项目的错误信息,查找问题方便许多。
同时有些问题也想跟OneAPM说一下
一、没有按照错误原因归类功能,如下图
这里的所有Notice都是一个php文件的同一行代码造成的,如果能有归类,这样我能够统计该错误发生的次数。
二、增加搜索功能
有时我就想先查找关心的错误,如error
和warning
的错误,但是整个列表里大部分是Notice
和Deprecated
,现在让我找重要错误比较困难。
三、报表中也希望增加对错误信息的报告
到这里我们对Notice
和Deprecated
有了更深刻的认识,以往我们都不关心这类错误,存在没想到有这么大的影响。
过去从错误日志查问题的方式已经过去。现在借助OneAPM实现错误信息的实时美观地反馈,并能得到错误分析报表。
OneAPM是中国基础软件领域的新兴领军企业,能帮助企业用户和开发者轻松实现:缓慢的程序代码和SQL语句的实时抓取。想阅读更多技术文章,请访问OneAPM官方技术博客。
解决Notice错误,性能竟然提升了1000多倍!的更多相关文章
- PHP中NOTICE错误常见解决方法
对于初学者,肯定会遇到不同的错误提示,比如:警告,致命,等等,其中NOTICE错误等级最低,页面中,好多类似 Notice: Use of undefined constant title - ass ...
- LinkedList竟然比ArrayList慢了1000多倍?(动图+性能评测)
数组和链表是程序中常用的两种数据结构,也是面试中常考的面试题之一.然而对于很多人来说,只是模糊的记得二者的区别,可能还记得不一定对,并且每次到了面试的时候,都得把这些的概念拿出来背一遍才行,未免有些麻 ...
- 如何解决Ora-04031错误(转)
诊断并解决ORA-04031 错误 当我们在共享池中试图分配大片的连续内存失败的时候,Oracle首先清除池中当前没使用的所有对象,使空闲内存块合并.如果仍然没有足够大单个的大块内存满足请求,就会产生 ...
- 诊断并解决 ORA-4030 错误 (Doc ID 1548826.1)
适用于: Oracle Database - Enterprise Edition - 版本号 8.1.7.4 和更高版本号 本文档所含信息适用于全部平台 用途 怎样诊断 ORA-4030 错误 排错 ...
- PHP关闭Notice错误提示
原文出处 本文章介绍在php中关闭notice错误的一些做法,但是不得不说的是在关掉错误提示时,那么程序代码中大量的notice级别错误是否会造成PHP性能下降 PHP Notice: Undefin ...
- MySQL 8.0复制性能的提升(翻译)
What’s New With MySQL Replication in MySQL 8.0 MySQL复制从问世到现在已经经历了多个年头,它的稳定性和可靠性也在稳步的提高.这是一个不停进化的过程,由 ...
- 解决ORA-00020错误
解决ORA-00020错误 分类: Oracle2009-05-13 17:26 3398人阅读 评论(0) 收藏 举报 数据库sessionoraclesql服务器object 项目上使用的Orac ...
- 解决:错误的语法:”XXXX“必须是批处理中仅有的语句
原文:解决:错误的语法:”XXXX“必须是批处理中仅有的语句 SQL Server 数据库提示“错误的语法:”XXXX“必须是批处理中仅有的语句”报错的原因分析 解析:批处理必须以 CREATE ...
- Maven解决NoPluginFoundForPrefixException错误
Maven解决NoPluginFoundForPrefixException错误方法 错误出现的原因 你指的是一个不存在的插件,如由于错误的前缀. 您使用的是第三方的Maven插件没有部署到中央Mav ...
随机推荐
- PAT乙级真题1001. 害死人不偿命的(3n+1)猜想 (15)(解题)
卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反复砍下去,最后一定在某一步得到n=1.卡拉兹在1950年的世界数 ...
- 在Windows下使用BAT调度存储在资源库中的KTR
描述: 在Windows下使用BAT调度存储在资源库中的KTR 准备环境: 1.ktr文件(该KTR必须是存储在资源管库中的) 2.bat文件 @echo off D: cd D:\software\ ...
- oracle分区表(整理)
Oracle 表分区 早在8.0.5版本中,Oracle就将范围分区技术引入,现在分区功能已经越来越强大,包括支持扩展分区功能.Interval分区.外键分区.模拟列分区.以及分区建议器等.那么,分区 ...
- AppCan4.0:开发者要做有价值的APP
在当今的移动盛世,谈论APP“生存”话题未免太过沉重.但面对百万级移动应用大军所产生的激烈竞争,且保证“立而不倒”,这样的探讨就显得格外重要了. 主打“价值牌”才能“一条龙” 有这样一组数据,在我国, ...
- ToolBar存档
上图是将本阶段要完成的结果画面做了标示,结合下面的描述希望大家能明白. colorPrimaryDark(状态栏底色):在风格 (styles) 或是主题 (themes) 里进行设定. App ba ...
- [转]ubuntu(12.04)下, 命令 ,内核 源代码的获取
[转]ubuntu(12.04)下, 命令 ,内核 源代码的获取 http://blog.chinaunix.net/uid-18905703-id-3446099.html 1.命令:例如:要查看l ...
- scrapy 错误
1. 安装win32时候 Unable to find vcvarsall.bat 解决方法: 1.如果你没有安装vc,去微软下个 VS2008 的免费版就能解决此问题. 2.如果你安装的是VS201 ...
- Python实现NN(神经网络)
Python实现NN(神经网络) 参考自Github开源代码:https://github.com/dennybritz/nn-from-scratch 运行环境 Pyhton3 numpy(科学计算 ...
- 28335 sci fifo send
#include "DSP2833x_Device.h"#include "DSP2833x_Examples.h"char buf[]={0x30,0x32, ...
- Struts1+JQuery的例子
Struts1+JQuery的例子 2014年2月10日 11:25 Struts1+JQuery+JSON/XML的例子 1.Struts+JQuery+XML struts-config.xml如 ...