热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

让网站飞起来,PHP程序加速探索

文章标题:让网站飞起来,PHP程序加速探索。Linux是中国IT实验室的一个技术频道。包含桌面应用,Linux系统管理,内核研究,嵌入式系统和开源等一些基本分类

  (一)简介
  本文尝试对PHP程序加速的各个方面进行探索,包括必要性以及从不同角度采取的具体措施。希望有助于读者了解PHP程序加速,并应用于实际。
  
  (二)是否需要加速?
  这个问题听起来有点愚蠢。在这个时代,很少有人会怀疑时间是最宝贵的财富,尤其是在商业市场上。程序执行越快,用户就节约越多的时间,这样你的程序就可以用更少的时间和服务器资源为用户服务,从而产生更多效益。
  我想对于大部份人(包括我自己)来说,很多WEB项目都是在很紧张的时间里完成的,通常没有经过缜密的思考和严格的测试。当开始一个新的WEB项目。很多人都在构建那种“快而乱”的应用,缺乏必要的时间来调整和改良代码,这时优化和加速就是我们必须采取的措施。
  然而需要特别指出的是,并不是所有程序都需要加速。
  优化已完成的代码是很浪费时间的,最好的方法是在写代码的时候就注意到效率,然后完成项目后只优化确实需要优化的那部份。一般一个程序只会有少数几个影响速度的瓶颈,将它们找出来并解决掉,程序就可以很好地运行。另外,当遇到执行效率低下的情况,首先要用大局的眼光来找出影响效率的主要因素,而不要拘泥于细节—例如数据量过大,服务器带宽不够,或硬件配置过低,在这样的情况下,优化代码于事无补。
  另外,在没有发现程序有明显的执行缓慢的迹象时,就不要太吹毛求疵,为了改进一些非常细节的代码而浪费时间。用这些时间,你可以完成另一个项目或为原来的项目完成一个扩展功能。当然你可以笑话我不够负责,没有把工作做得尽善尽好,我也可以说你是完美主义者:-)
  综上,在你决定为你的PHP程序提速之前,问问自己是否有必要。
  
  (三)如何加速?
  要回答“如何加速”这个问题前,需要先回答以下两个小问题:
  你的程序慢在哪一部份?
  PHP可以从哪几个方面考虑加速?
  第一个小问题显然我无法给你答案,但我建议你用“测试脚本执行速度”的方法来解决。只有找出限制速度的瓶颈,才能考虑如何去解决。
  第二个小问题我大概的答案是:代码优化,压缩输出,内容缓存输出,函数缓存输出,加速/缓存工具软件。如果你知道更多请告诉我:-)
  下面我们来详细地研究一下这几个方面的相关技术。当然实际上每个方面都有无数的细节可以讨论,下面的内容难免会有片面的地方,欢迎补充。
  
  <1> 测试
  ◆ 服务器负载测试
  
  服务器负载太大而影响程序效率也是很常见的,我们需要对此进行测试。这里我以目前最常用的Apache服务器为例。
  Apache服务器自带有一个叫AB(ApacheBench)的工具,在bin目录下。使用这个轻巧的工具我们可以对服务器进行负载测试,看看在重负荷之下服务器的表现如何。ApacheBench 可以针对某个特定的 URL 仿真出连续的联机请求,同时还可以仿真出同时间点数个相同的联机请求,因此利用 ApacheBench 可帮助我们在网站开发期间仿真实际上线可能的情况,利用仿真出来的数据作为调整服务器设定或程序的依据。
  在命令行下输出:
  
  ./ab -n number_of_total_requests -c number_of_simultaneous_requests http://your_web_server/your_php_app.php
  
  例如:
  
  ./ab -n 1000 -c 50 http://www.domain.com/myapp.php
  
  AB将同时向http://www.domain.com/myapp.php发出50个并发请求,共发出1000次。
  测试结果将可能是这样的:
  
  Server Software: Apache/2.0.16
  Server Hostname: localhost
  Server Port: 80
  Document Path: /myapp.php
  Document Length: 1311 bytes
  Concurrency Level: 50
  Time taken for tests: 8.794 seconds
  Complete requests: 1000
  Failed requests: 0
  Total transferred: 1754000 bytes
  HTML transferred: 1311000 bytes
  Requests per second: 113.71
  Transfer rate: 199.45 kb/s received
  Connection Times (ms)
  min avg max
  Connect: 0 0 5
  Processing: 111 427 550
  Total: 111 427 555
  
  myapp.php每秒钟可以处理的请求数为113.71个。将请求数增加,看看服务器能否处理更大的压力。你也需要调节Apache的MaxClients, ThreadsPerChild, MaxThreadsPerChild 等参数,基于你的 httpd.conf 中的 MPM 模块选择。
  如果你想得到更详细的信息,请到www.apache.org上查阅一些更深入的文档,包括模块和第三方的提高效率的工具。修改httpd.conf后,要重启Apache服务器,然后再用AB测试。你会看到每秒请求数增加或减少。
  记下每次的参数,最后选择最佳效率的那种配置。
  要指出的是,除了AB,还有许多优秀的服务器性能测试软件。另外,如果你的服务器不是 Apache,请自行寻找测试方法。
  
  ◆ 脚本执行速度测试
  
  前面有提到,只有找到影响速度的代码,我们才有可能进行优化。PEAR的benchmark包中的Benchmark_Timer类和Benchmark_Iterate类,可以用来很方便地测试脚本执行的速度。(关于PEAR的安装与配置请自行查看相关资料)
  首先用Benchmark_Iterate类来测试程序中某个函数或类的某个方法的执行时间。
  
  benchmark1.php
  
    
  require_once('Benchmark/Iterate.php');
  $benchmark = new Benchmark_Iterate();
  
  $benchmark->run(10, 'myFunction','test');
  $result = $benchmark->get();
  echo "
  
  "; print_r($result); echo "
  ";
  exit;
  
  function myFunction($var) {
  // do something
  echo 'Hello ';
  }
  
  ?>
  
  建立benchmark Iterate对象$benchmark,这个对象用来执行myFunction函数10次。
  $argument变量每次都传递给myFunction. 多次运行的分析结果存入$result,然后用benchmark对象的get()方法来获取。这个结果用print_r()输出到屏幕。通常会输出这样的结果:
  Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello
  Array(  [1] => 0.000427  [2] => 0.000079  [3] => 0.000072  [4] => 0.000071  [5] => 0.000076  [6] => 0.000070  [7] => 0.000073  [8] => 0.000070  [9] => 0.000074  [10] => 0.000072  [mean] => 0.000108  [iterations] => 10)  myFunction的每次执行,benchmark对象都会跟踪执行时间。并且会计算平均的执行时间([mean]那一行)。通过多次运行目标函数,你可以得到该函数的平均运行时间。
  在实际测试中,函数的次数应当至少1000次左右,这样可以得到较客观的结果。
  
  现在我们看看另一个测试脚本运行时间的方法--使用Benchmark_Timer类来测试一段代码执行所消耗的时间及这一段代码中每次调用与下一次调用间的时间。
  
  benchmark2.php
  
    require_once 'Benchmark/Timer.php';
  $timer = new Benchmark_Timer();
  $timer->start();
  $timer->setMarker('start_myFunction');
  
  for($i=0; $i<10; $i++){
  myFunction($argument);
  }
  $timer->setMarker('end_myFunction');
  $timer->stop();
  $profiling = $timer->getProfiling();
  
  echo '
  Time elapsed: ' .
  $timer->timeElapsed('start_myFunction','end_myFunction') .'
  ';
  echo '
  '; print_r($profiling); echo '
  ';
  exit;
  
  function myFunction($var) {
  static $counter = 0;
  // do something
  echo $counter++ . ' ';
  }
  ?>
  
  首先,建立一个benchmark timer对象$timer。然后调用start()方法,表示开始计时。 SetMaker()方法用来标记要测试的代码段。MyFunction()函数在循环中被调用,表示一段要执行的代码(当然实际中不会这么简单)。然后再用$timer对象的setMarker()方法标记程序执行终点。分析信息用getProfiling()来获取。在两个标记间程序执行消耗的时间用timeElapsed()方法计算出来(就像例子中的循环)。最后,用print_r()输出信息到屏幕:
  Time elapsed: 0.000594
  
  通过这种方法,你可以在代码中设置大量时间段标记,获取每段代码执行时消耗的时间,很容易可以看出到底是哪一部份的代码影响了整个程序的运行效率。然后开始着手对这部份代码进行改进。
  用以上两种方法,你可以找出代码中最影响速度的部份代码。另外还可以用来对优化后的代码进行测试,看看到底执行速度提高了多少。通过测试->优化->测试->优化 …这样不断循环,你可以最终确定提供最佳效率的代码。
  
  <2> 加速
  
  ◆ 代码优化
  掌握了PEAR::BenchMark,现在你已经知道如何测试你的代码,知道如何判断你的代码是快是慢,是哪一部份比较慢。那么接下来我要说的就是如何消灭或优化那部份慢的代码。
  这一点上我个人最主要的经验只有两点,一是消除错误的或低效的循环;二是优化数据库查询语句。其实还存在一些其它的优化细节,比如“str_replace比ereg_replace快”、“echo比print快”等等。这些我暂时都放在一边,稍后我会提到用缓存来对付过于频繁的IO。
  下面我们将三个功能相同,但程序写法不同的函数的效率(消耗的时间)进行对比。
  
  badloops.php
  
    require_once('Benchmark/Iterate.php');
  define('MAX_RUN',100);
  $data = arra
推荐阅读
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
  • Docker的安全基准
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 使用Vultr云服务器和Namesilo域名搭建个人网站
    本文详细介绍了如何通过Vultr云服务器和Namesilo域名搭建一个功能齐全的个人网站,包括购买、配置服务器以及绑定域名的具体步骤。文章还提供了详细的命令行操作指南,帮助读者顺利完成建站过程。 ... [详细]
  • 网络运维工程师负责确保企业IT基础设施的稳定运行,保障业务连续性和数据安全。他们需要具备多种技能,包括搭建和维护网络环境、监控系统性能、处理突发事件等。本文将探讨网络运维工程师的职业前景及其平均薪酬水平。 ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 本文探讨了如何通过最小生成树(MST)来计算严格次小生成树。在处理过程中,需特别注意所有边权重相等的情况,以避免错误。我们首先构建最小生成树,然后枚举每条非树边,检查其是否能形成更优的次小生成树。 ... [详细]
  • 使用Numpy实现无外部库依赖的双线性插值图像缩放
    本文介绍如何仅使用Numpy库,通过双线性插值方法实现图像的高效缩放,避免了对OpenCV等图像处理库的依赖。文中详细解释了算法原理,并提供了完整的代码示例。 ... [详细]
  • This guide provides a comprehensive step-by-step approach to successfully installing the MongoDB PHP driver on XAMPP for macOS, ensuring a smooth and efficient setup process. ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • 本文探讨了在不使用服务器控件的情况下,如何通过多种方法获取并修改页面中的HTML元素值。除了常见的AJAX方式,还介绍了其他可行的技术方案。 ... [详细]
  • 本文探讨了如何优化和正确配置Kafka Streams应用程序以确保准确的状态存储查询。通过调整配置参数和代码逻辑,可以有效解决数据不一致的问题。 ... [详细]
author-avatar
可乐16311
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有