最近在做一个游戏数据统计后台,最基础的功能是通过分析注册登录日志来展示用户数据。在公司内部测试,用户量很少,所以就没有发现什么性能问题。但是这两天一起放到真实的测试环境,用户量噌噌地就涌进来了,从下午开始,在线人数的统计开始卡,几秒钟才返回数据;注册人数的查询速度还行。到了晚上,在线人数的统计基本上就加载超时打不开了。虽然不知他们游戏端那边什么BUG,玩家那边登录经常出问题,导致在线人数和注册人数并不是很多。但是就这一点数据量我这边查询的速度也不行,这就很尴尬了。

现在他们那边在查游戏的BUG,我这边也在看统计后台的代码到底性能出在哪里。首先说明一下,我统计用的数据是从库,他们游戏用的是主库,再说我这边管理员人数就几个,不可能会影响到游戏服的性能问题。

今天项目组长把数据库都导过来到公司内的服务器。我拷了一份到本机,看看统计平台的性能问题出在哪里。然后却发现,居然连注册统计都非常卡,服务器上是两秒左右返回,本机要二十几秒,还经常超时(PHP的默认配置是30秒超时);在线统计的就不用说了肯定打不开。看了一下数据库,当天的注册记录也就 3500 条左右(有假数据),每五分钟统计一次,一天就是统计 288 次。当然这里肯定不是循环查询数据库288次,那样会被骂死的吧。

统计时间段内的注册数,逻辑也非常简单,就是每个时间段遍历一次数据,比较时间大小,符合就+1。但是为什么这么简单的逻辑,也就一百万次循环,怎么会跑出了足足半分钟的时间那么久呢?

关键问题就出在于 时间比较这里了,我们都知道,时间戳是比较时间大小的一个比较科学的方法,而数据库里记录的时间一般都是以 YYYY-mm-dd HH:ii:ss 的形式,PHP里有strtotime的函数转换成时间戳。然而在288个for * 3500个foreach 的加持之后,这里的执行时间长达半分钟

$nowDayDT = strtotime( date('Y-m-d') );
$__startT = microtime(TRUE);
for($i=0; $i<$allTime; $i += $gapTime){$count = 0;//用于数据比较的$startDT = $nowDayDT+$i;$endDT = $nowDayDT+$i+$gapTime;//用于显示的$xAxis1 = date('H:i', $nowDayDT+$i);$xAxis2 = date('H:i', $nowDayDT+$i+$gapTime);foreach($rawData as $line){$time = strtotime($line['log_dt']);if( $startDT<=$time && $time<$endDT ){$count ++;}}$resArr[] = ['date'=>$xAxis1.'~'.$xAxis2,'number'=>$count];
}
echo microtime(TRUE)-$__startT;

那这样的话,基本上是没办法再用这个strtotime的函数的了,那还有什么办法比较时间大小呢?答案很简单粗暴,PHP里面可以直接比较两个日期时间字符串!所以改过后的代码如下。然后现在的运行时间大概是 0.3秒

$__startT = microtime(TRUE);
for($i=0; $i<$allTime; $i += $gapTime){$count = 0;//用于数据比较的$startDT = date('Y-m-d H:i:s', $nowDayDT+$i);$endDT = date('Y-m-d H:i:s', $nowDayDT+$i+$gapTime);//用于显示的$xAxis1 = date('H:i', $nowDayDT+$i);$xAxis2 = date('H:i', $nowDayDT+$i+$gapTime);foreach($rawData as $line){$time = $line['log_dt'];if( $startDT<=$time && $time<$endDT ){$count ++;}}$resArr[] = ['date'=>$xAxis1.'~'.$xAxis2,'number'=>$count];
}
echo microtime(TRUE)-$__startT;

去掉strtotime的比较

PHP里两个时间字符串只能比较大小,不能计算时间差,如果要做类似于 在线时长 的统计的话,可以在读取数据库的时候转换,mysql的用法是 SELECT xx, unix_timestamp(log_dt) AS log_dt_ts FROM xxx;

遍历再优化

大家可能发现一个问题,for 里面嵌套一个 foreach,这性能有点担忧,其中里面的 foreach 有必要完全遍历吗?其实是不必的。只要查SQL数据的时候,按时间排序排出来。优化后的时间比较算法如下:

for{ ...foreach($rawData as $line){$time = $line['log_dt'];//strtotime($line['log_dt']);//优化算法计算if($time<$startDT) continue;    //小于开始时间则跳过if($time>=$endDT) break;        //大于结束时间则结束$count ++;                        //否则为符合条件//原始的算法
//    if( $startDT<=$time && $time<$endDT ){
//        $count ++;
//    }
}...}

这里巧用了 continue 和 break 关键字,用于跳过一次循环和结束整个循环。这次的话,一天中刚开始的时间统计中,后面很大一部分数据的都可以直接跳过。最后总遍历时间缩短为约0.12秒

总结,在大型的数据处理中,应该尽量避免在遍历中进行数据的转换,避免用一些原理复杂的函数。如strtotime

转载于:https://www.cnblogs.com/batsing/p/6078800.html

PHP的性能大坑--strtotime函数相关推荐

  1. php strtotime,PHP strtotime函数详解

    PHP strtotime函数详解 更新时间:2009年12月18日 22:04:41   作者: strtotime函数是一个很好的函数,灵活的运用它,会给你的工作带来不少方便.但PHP的手册中却对 ...

  2. php中strtotime的意思,php中strtotime函数用法详解

    本文实例讲述了php中strtotime函数用法.分享给大家供大家参考.具体如下: strtotime(字符串$时间[,诠释$现在])int strtotime(string $time [,int ...

  3. PHP中strtotime函数有范围吗,PHP中使用strtotime函数注意事项

    strtotime函数在是大家常用的一个时间日期转换成单位S的一个函数了,但是这个函数有一个细节大家可能没有注意到,就是 使用的时候需要考虑 有31天和 2月份的情况,所以,如果没有考虑这个特殊的情况 ...

  4. strtotime php,php strtotime函数怎么用

    PHP strtotime()函数用于接受表示日期时间的字符串参数,将任何英文文本的日期或时间描述解析为Unix时间戳,语法为"strtotime (time,now)",若成功则 ...

  5. 算法学习四:算法性能分析理论基础——函数增长与渐进分析

    算法学习四:算法性能分析理论基础--函数增长与渐进分析 在算法性能分析过程中,特别是在算法运行效率分析中,我们经常使用渐渐分析法,它使我们在分析算法性能时不必纠结于不同硬件平台的差异性,着重考虑算法的 ...

  6. PHP strtotime函数详解

    先看手册介绍: strtotime - 将任何英文文本的日期时间描述解析为 Unix 时间戳 格式:int strtotime ( string $time [, int $now ] ) 本函数预期 ...

  7. PHP中strtotime函数的坑

    坑的生命周期 怎么入的坑 strtotime的介绍 实例 定义和用法 语法 技术细节 找出逻辑规律 怎么从坑里爬出来呢? 那耄耋老人,怎么出坑呢? 参考链接 怎么入的坑 我在使用strtotime 获 ...

  8. c++当中strtotime函数

    把字符串转换为时间戳 unsigned long strtotime(char *date) {struct tm t;unsigned long time;sscanf(date,"%d- ...

  9. PHP strtotime() 函数将任何英文文本的日期或时间描述解析为 Unix 时间戳(自 January 1 1970 00:00:00 GMT 起的秒数)。

    PHP strtotime() 函数将任何英文文本的日期或时间描述解析为 Unix 时间戳(自 January 1 1970 00:00:00 GMT 起的秒数). <!DOCTYPE html ...

  10. c# php 时间戳,C#时间转整型(时间戳),模仿php strtotime函数的部分功能

    标签:今天需要将一个基于MS SQL数据库的新闻系统数据导入phpcms v9,源系统新闻日期格式为"2014-01-15 10:45:49", 而phpcms中使用的是整型时间戳 ...

最新文章

  1. nginx+keepalived高可用web架构
  2. API 分页设计与实现探讨
  3. GIt代码托管、Github Desktop和 Pycharm中代码的管理
  4. 悲观锁和乐观锁_乐观锁和悲观锁 以及 乐观锁的一种实现方式-CAS
  5. 前端学习(1902)vue之电商管理系统电商系统之渲实现添加用户前的预先校验
  6. boot整合redis
  7. 没有串口,如何打印单片机调试信息?
  8. Python实现给指定的微信朋友发信息
  9. EXCEL2010经典用法全集(3)
  10. HTML5网站大观:分享8个精美的 HTML5 网站案例
  11. Axios中无法运行 json-server【已解决】
  12. Vijos P1596 加法表【迭代】
  13. jdbc如何使用oracle数据库连接池,使用JDBC连接池技术连接Oracle数据库
  14. Effective_STL 学习笔记(三) 使容器里对象的拷贝操作轻量而正确
  15. struts入门实例
  16. oracle连接plsqldev
  17. 英特尔凌动处理器_教你看懂英特尔处理器:什么是Core i3,i5,i7 和Pentium?
  18. eclipse常用快捷方式
  19. 靖哥哥教你如何用java做爬虫抓取网站美女图片(详解步骤)
  20. 新书预告:Xilix FPGA数字信号处理设计——基础版

热门文章

  1. 【三】Jmeter:测试片段
  2. python列表和数组区别java_Python列表与Java数组效率
  3. cut out数据增强_被多种离散化场景困扰?8种python技巧!让数据处理更简单
  4. mysql变量包括什么意思_什么是mysql变量?
  5. pdf增强锐化软件_安卓软件—CamScanner 扫描全能王
  6. c#执行多句oracle,C#一次执行多条SQL语句,Oracle11g数据库
  7. 第2章[2.4] Ext JS的类与类体系
  8. Java 性能优化系列之4[Java性能调优工具]
  9. MYSQL 字符集问题
  10. html百度地图秘钥,自己网页调用百度地图API 附API密钥