一件事是公司给印名片,我报了的系统架构师的头衔。
架构是我现在在努力的目标,UML,系统开发思维,这些都是这一职位的知识范畴。但我现在还没有达到一个好的系统架构师的标准,甚至,还不能算作是准架构师。
努力,做自己想做的。
<documenttype id="HTML" internaltype="HTML" winfileextension="html,htm,shtml,shtm,stm,tpl,lasso,xhtml,page" macfileextension="html,htm,shtml,shtm,tpl,lasso,xhtml,ssi,page" file="Default.html" writebyteordermark="false">
| 英文 | 中文 | |||
Optimizing PHP Scripts By Leon Atkinson June 20, 2001 One reason I like PHP is that it allows the freedom to quickly create Web applications without worrying about following all the rules of proper design. When it comes to rapid prototyping, PHP shines. With this power comes the responsibility to write clean code when it's time to write longer-lasting code. Sticking to a style guide helps you write understandable programs, but eventually you will write code that doesn't execute fast enough. Optimization is the process of fine-tuning a program to increase speed or reduce memory usage. Memory usage is not as important as it once was, because memory is relatively inexpensive. However, shorter execution times are always desirable. There are many tips for writing efficient programs, and I can hardly discuss them all here. And anyway, that would be like giving you a fish instead of teaching you to catch your own. This month, I will review the techniques I use for speeding up my PHP scripts. When to optimize Before you write a program, commit yourself to writing clearly at the expense of performance. Follow coding conventions, such as using mysql_fetch_row instead of mysql_result. But keep in mind that programming time is expensive, especially when programmers must struggle to understand code. The simplest solution is usually best. When you finish a program, consider whether its performance is adequate. If your project benefits from a formal requirements specification, refer to any performance constraints. It's not unusual to include maximum page load times for Web applications. Many factors affect the time between clicking a link and viewing a complete page. Be sure to eliminate factors you cannot control, such as the speed of the network. If you determine that your program needs optimization, consider upgrading the hardware first. This may be the least expensive alternative. In 1965, Gordon Moore observed that computing power doubled every 18 months. It's called Moore's Law. Despite the steep increase in power, the cost of computing power drops with time. For example, despite CPU clock speeds doubling, their cost remains relatively stable. Upgrading your server is likely less expensive than hiring programmers to optimize the code. After upgrading hardware, consider upgrading the software supporting your program. Start with the operating system. Linux and BSD Unix have the reputation of squeezing more performance out of older hardware, and they may outperform commercial operating systems, especially if you factor in server crashes. If your program uses a database, consider the differences between relational databases. If you can do without stored procedures and sub-queries, MySQL may offer a significant performance enhancement over other database servers. Check out the benchmarks provided on their Web site. Also, consider giving your database server more memory. Two Zend products can help speed execution times of PHP programs. The first is the Zend Optimizer. This optimizes PHP code as it passes through the Zend Engine. It can run PHP programs 40% to 100% faster than without it. Like PHP, the Zend Optimizer is free. The next product to consider is the Zend Cache. It provides even more performance over the optimizer by keeping compiled code in memory. Some users have experienced 300% improvements. Contact Zend to purchase the Zend Cache. Measuring performance Before you can begin optimizing, you must be able to measure performance. The two tools I'll discuss are inserting HTML comments and using Apache's ApacheBench utility. PHP applications run on a Web server, but the overhead added by serving HTML documents over a network should be factored out of your measurements. You need to isolate the server from other activity, perhaps by barring other users or even disconnecting it from the network. Running tests on a server that's providing a public site may give varying results, as traffic changes during the day. Run your tests on a dedicated server even if the hardware doesn't match the production server. Optimizations made on slower hardware should translate into relative gains when put into production. The easiest method you can use is insertion of HTML comments into your script's output. This method adds to the overall weight of the page, but it doesn't disturb the display. I usually print the output of the microtime function. I insert a line like: print("\n"); I place these calls to microtime at the beginning, end and at key points inside my script. To measure performance, I request the page in a Web browser and view the source. This produces lines like this: The microtime function returns the number of seconds on the clock. The first figure is a fraction of seconds, and the other is the number of seconds since January 1, 1970. You can add the two numbers and put them in an array, but I prefer to minimize the affect on performance by doing the calculation outside of the script. In the example above, the first part of the script takes approximately 0.005 seconds, and the second part takes 0.03. If you decide to calculate time differences, consider the method used in the example below. Entries to the clock array contain a one-word description followed by the output of microtime. The explode function breaks up the three values so the script can display a table of timing values. The first column of the table holds the number of seconds elapsed since the last entry. //start clock $clock[] = 'Start ' . microtime(); //fake some long process sleep(2); $clock[] = 'Connected ' . microtime(); //end clock $clock[] = 'End ' . microtime(); //print clock $entry = explode(' ', $clock[0]); $lastVal = $entry[1] + $entry[2]; print(''); foreach($clock as $c) { $entry = explode(' ', $c); print(''); print(''); print(''); print(''); print(''); $lastVal = $entry[1] + $entry[2]; } print('
?> Inserting HTML comments is my favorite method, because it takes no preparation. But its big weakness is a small sample size. I always try three or four page loads to eliminate any variances due to caching or periodic server tasks. The Apache Web server includes a program that addresses this problem by measuring the number of requests your server can handle. It's called ApacheBench, but the executable is "ab". ApacheBench makes a number of requests to a given URL and reports on how long it took. Here's an example of running 1000 requests for a plain HTML document: ~> /usr/local/apache/bin/ab -n 1000 http://localhost/test.html This is ApacheBench, Version 1.3c <$Revision: 1.1.2.6 $> apache-1.3 Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Copyright (c) 1998-2000 The Apache Group, http://www.apache.org/ Server Software: Apache/1.3.19 Server Hostname: localhost Server Port: 80 Document Path: /test.html Document Length: 6 bytes Concurrency Level: 1 Time taken for tests: 5.817 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 262000 bytes HTML transferred: 6000 bytes Requests per second: 171.91 Transfer rate: 45.04 kb/s received Connnection Times (ms) min avg max Connect: 1 1 11 Processing: 3 3 16 Total: 4 4 27 I requested an HTML document to get an idea of the baseline performance of my server. Any PHP script ought to be slower than an HTML document. Comparing the figures gives me an idea of the room for improvement. If I found my server could serve a PHP script at 10 requests per second, I'd have a lot of room for improvement. Keep in mind that I'm running ApacheBench on the server. This eliminates the effects of moving data over the network, but ApacheBench uses some CPU time. I could test from another machine to let the Web server use all the system resources. By default, ApacheBench makes one connection at a time. If you use 100 for the -n option, it connects to the server one hundred times sequentially. In reality, Web servers handle many requests at once. Use the -c option to set the concurrency level. For example, -n 1000 -c 10 makes one thousand connections with 10 requests active at all times. This usually reduces the number of requests the server can handle, but at low levels the server is waiting for hardware, such as the hard disk. The ApacheBench program is a good way to measure overall change without inconsistencies, but it can't tell you which parts of a script are slower than others. It also includes the overhead involved with connecting to the server and negotiating for the document using HTTP. You can get around this limitation by altering your script. If you comment out parts and compare performance, you can gain an understanding of which parts are slowest. Alternatively, you may use ApacheBench together with microtime comments. Whichever method you use, be sure to test with a range of values. If your program uses input from the user, try both the easy cases and the difficult ones, but concentrate on the common cases. For example, when testing a program that analyzes text from a textarea tag, don't limit yourself to typing a few words into the form. Enter realistic data, including large values, but don't bother with values so large they fall out of normal usage. People rarely type a megabyte of text into a textarea, so if performance drops off sharply, it's probably not worth worrying about. Remember to measure again after each change to your program, and stop when you achieve your goal. If a change reduces performance, return to an earlier version. Let your measurements justify your changes. Attacking the slowest parts Although there are other motivations, such as personal satisfaction, most people optimize a program to save money. Don't lose sight of this as you spend time increasing the performance of your programs. There's no sense in spending more time optimizing than the optimization itself saves. Optimizing an application used by many people is usually worth the time, especially if you benefit from licensing fees. It's hard to judge the value of an open-source application you optimize, but I find work on open-source projects satisfying as recreation. To make the most of your time, try to optimize the slowest parts of your program where you stand to gain the most. Generally, you should try to improve algorithms by finding faster alternatives. Computer scientists use a special notation to describe the relative efficiency of an algorithm called big-O notation. An algorithm that must examine each input datum once is O(n). An algorithm that must examine each element twice is still called O(n) as linear factors are not interesting. A really slow algorithm might be O(n^2), or O of n-squared. A really fast algorithm might be O(n log n), or n times the logarithm of n. This subject is far too complex to cover here -- you will find lots of information on the Internet and in university courses. Understanding it may help you choose faster algorithms. Permanent storage, such as a hard disk, is much slower to use than volatile storage, such as RAM. Operating systems compensate somewhat by caching disk blocks to system memory, but you can't keep your entire system in RAM. Parts of your program that use permanent storage are good candidates for optimization. If you are using data stored in files, consider using a relational database instead. Database servers can do a better job of caching data than the operating system because they view the data with a finer granularity. Database servers may also cache open files, saving you the overhead in opening and closing files. Alternatively, you can try caching data within your own program, but consider the lifecycle of a PHP script. At the end of the request, PHP frees all memory. If during your program you need to refer to the same file many times, you may increase performance by reading the file into a variable. Consider optimizing your database queries, too. MySQL includes the EXPLAIN statement, which returns information about how the join engine uses indexes. MySQL's online manual includes information about the process of optimizing queries. Here are two tips for loops. If the number of iterations in a loop is low, you might get some performance gain from replacing the loop with a number of statements. For example, consider a for loop that sets 10 values in an array. You can replace the loop with 10 statements, which is a duplication of code, but may execute slightly faster. Also, don't recompute values inside a loop. Before the foreach statement appeared in PHP, I often wrote for($i=0; $i Function calls carry a high overhead. You can get a bump in performance if you eliminate a function. Compiled languages, such as C and Java, have the luxury of replacing function calls with inline code. You should avoid functions that you only call once. One technique for readable code is to use functions to hide details. This technique is expensive in PHP. If all else fails, you have the option of moving part of your code into C, wrapping it in a PHP function. This technique is not for the novice, but many of PHP's functions began as optimizations. Consider the in_array function. You can test for the presence of the value in an array by looping through it, but the function written in C is much faster. | 优化PHP脚本 作者:Leon Atkinson 2001年6月20日 我喜欢PHP的一个原因是我可以在很少的语言规则约束下进行快速的网络应用程序开发。当谈及快速原型时,PHP具有足够的优势。为了让代码具有长久有效性(译者注:是不是指可重用性),我们需要使代码简洁。遵循编码规范可以是你的代码易读,但并不能使你的代码效率提高。 优化是为了增加速度或减少内存使用的微调过程,内存使用量并不想以前那样重要了,应为现在内存很便宜。而更好的执行效率更让人关注。 这里有一些的编写高效率代码的提示,我很难在这里一条条列出。授人以鱼不如授人以渔,这个月我将回顾一下我的一直用来加快我的PHP脚本的技术。 何时优化 在写代码前,就要告诫自己要编写该效率程序,遵循代码编写惯例,如使用mysql_fetch_row替代mysql_result。紧记程序执行时间是很重要的,另外不要使你的代码很难读懂。越简单越好。 程序编写完毕时,充分考虑程序的性能. 如果你需要正式确定项目受益,参考一些性能规范。通常不要包含大量的文件,这将花费一些加载时间。排除诸如网速等补课控制的因素外,还有狠斗因素影响了用户点击链接和页面显示的这一过程时间。 如果你决定去优化你的程序,首先去优化。这是最廉价的方法。在1965年,Gordon Moore提出计算机运行速度每18个月就可以增加一倍。这被称为Moore规律。尽管计算机速度增快,但他的价格也在随时间降低。比如,CPU的主频不断在提升,二价格确一致保持在一定水平。升级服务器比雇佣一个程序员来优化代码要便宜得多。 升级硬件后,再考虑升级支持你运行的软件。从操作系统升级开始。Linux和BSD Unix在老式硬件的一行效率上比商业操作系统享有很高的声誉。 如果你的程序使用了数据库,考虑关系数据库将的差别。如果你不打算使用存储过程,MySQL是一个执行效率较高的数据库解决方案。参考一下其他的网站。当然,也要考虑给数据库更大的内存。 两个Zend产品可以帮助你提高程序的执行效率。一是Zend优化器,优化的代码和Zend引擎优化的结果相同,可以提高PHP40%~100%的执行效率。Zned优化器也是免费的。第二是Zend Cache(直译为高速缓冲存储器,对这个产品不知道是什么)。它将编译后的代码存储在内存中,以提高执行效率。一些有经验的程序员可以使效率提高300%。Zend Cache是Zend公司的商业商品。 在开始优化前,你需要前分析一下服务器性能。我想讨论的来年改革工具是插入HTML注释和使用Apache的ApacheBench效用。PHP应用程序是在WEB服务器上运行的,而在服务器头部输出传送的HTML文档将超出了的衡量因素。 你需要从其他应用中隔离你的服务器,可能包括其他用户或断开网络中。 翻译了这么长了,还没到PHP的优化 |
| 英文 | 中文 |
| There are a number of tricks that you can use to squeeze the last bit of performance from your scripts. These tricks won't make your applications much faster, but can give you that little edge in performance you may be looking for. More importantly it may give you insight into how PHP internals works allowing you to write code that can be executed in more optimal fashion by the Zend Engine. Please keep in mind that these are not the 1st optimization you should perform. There are some far easier and more performance advantageous tricks, however once those are exhausted and you don't feel like turning to C, these maybe tricks you would want to consider. So, without further ado... 1) When working with strings and you need to check that the string is either of a certain length you'd understandably would want to use the strlen() function. This function is pretty quick since it's operation does not perform any calculation but merely return the already known length of a string available in the zval structure (internal C struct used to store variables in PHP). However because strlen() is a function it is still somewhat slow because the function call requires several operations such as lowercase & hashtable lookup followed by the execution of said function. In some instance you can improve the speed of your code by using a isset() trick. Ex. if (strlen($foo) < 5) { echo "Foo is too short"; } vs. if (!isset($foo{5})) { echo "Foo is too short"; } Calling isset() happens to be faster then strlen() because unlike strlen(), isset() is a language construct and not a function meaning that it's execution does not require function lookups and lowercase. This means you have virtually no overhead on top of the actual code that determines the string's length. 2) When incrementing or decrementing the value of the variable $i++ happens to be a tad slower than ++$i. This is something PHP specific and does not apply to other languages, so don't go modifying your C or Java code thinking it'll suddenly become faster, it won't. ++$i happens to be faster in PHP because instead of 4 opcodes used for $i++ you only need 3. Post incrementation actually causes in the creation of a temporary var that is then incremented. While pre-incrementation increases the original value directly. This is one of the optimization that opcode optimized like Zend's PHP optimizer. It is a still a good idea to keep in mind since not all opcode optimizers perform this optimization and there are plenty of ISPs and servers running without an opcode optimizer. 3) When it comes to printing text to screen PHP has so many methodologies to do it, not many users even know all of them. This tends to result in people using output methods they are already familiar from other languages. While this is certainly an understandable approach it is often not best one as far as performance in concerned. print vs echo Even both of these output mechanism are language constructs, if you benchmark the two you will quickly discover that print() is slower than echo(). The reason for that is quite simple, print function will return a status indicating if it was successful or not, while echo simply print the text and nothing more. Since in most cases (haven't seen one yet) this status is not necessary and is almost never used it is pointless and simply adds unnecessary overhead. printf Using printf() is slow for multitude of reasons and I would strongly discourage it's usage unless you absolutely need to use the functionality this function offers. Unlike print and echo printf() is a function with associated function execution overhead. More over printf() is designed to support various formatting schemes that for the most part are not needed in a language that is typeless and will automatically do the necessary type conversions. To handle formatting printf() needs to scan the specified string for special formatting code that are to be replaced with variables. As you can probably imagine that is quite slow and rather inefficient. heredoc This output method comes to PHP from PERL and like most features adopted from other languages it's not very friendly as far as performance is concerned. While this method allows you to easily output large chunks of text while preserving things like newlines and even allow for variable handling inside the text block this is quite slow and there are better ways to do that. Performance wise this is just marginally faster then printf() however it does not offer nearly as much functionality. ?><? When you need to output a large or even a medium sized static bit of text it is faster and simpler to put it outside the of PHP. This will make the PHP's parser effectively skipover this bit of text and output it as is without any overhead. You should be careful however and not use this for many small strings in between PHP code as multiple context switches between PHP and plain text will ebb away at the performance gained by not having PHP print the text via one of it's functions or constructs. 4) Many scripts tend to reply on regular expression to validate the input specified by user. While validating input is a superb idea, doing so via regular expression can be quite slow. In many cases the process of validation merely involved checking the source string against a certain character list such as A-Z or 0-9, etc... Instead of using regex in many instances you can instead use the ctype extension (enabled by default since PHP 4.2.0) to do the same. The ctype extension offers a series of function wrappers around C's is*() function that check whether a particular character is within a certain range. Unlike the C function that can only work a character at a time, PHP function can operate on entire strings and are far faster then equivalent regular expressions. Ex. preg_match("![0-9]+!", $foo); vs ctype_digit($foo); 5) Another common operation in PHP scripts is array searching. This process can be quite slow as regular search mechanism such as in_array() or manuall implementation work by itterating through the entire array. This can be quite a performance hit if you are searching through a large array or need to perform the searches frequently. So what can you do? Well, you can do a trick that relies upon the way that Zend Engine stores array data. Internally arrays are stored inside hash tables when they array element (key) is the key of the hashtables used to find the data and result is the value associated with that key. Since hashtable lookups are quite fast, you can simplify array searching by making the data you intend to search through the key of the array, then searching for the data is as simple as $value = isset($foo[$bar])) ? $foo[$bar] : NULL;. This searching mechanism is way faster then manual array iteration, even though having string keys maybe more memory intensive then using simple numeric keys. Ex. $keys = array("apples", "oranges", "mangoes", "tomatoes", "pickles"); if (in_array('mangoes', $keys)) { ... } vs $keys = array("apples" => 1, "oranges" => 1, "mangoes" => 1, "tomatoes" => 1, "pickles" => 1); if (isset($keys['mangoes'])) { ... } The bottom search mechanism is roughly 3 times faster. If you know or have any additional optimization tricks let me know | 这里是几条优化技巧,你可以在你最终优化时用到它们。这些技巧并不是让你的代码变得更快,而只能使代码稍稍的优化一点。更重要的是它可以让你洞察到PHP内在的运行原理,使得ZEND引擎能够更好的对代码进行优化。提醒一下,这不是你在编码开始时就要执行的优化。有一些更简单更快的优化技巧,在使用后,however once those are exhausted and you don't feel like turning to C, these maybe tricks you would want to consider. So, without further ado... 1) 当对字符串进行操作时,如果你需要检查字符串是否超过某一长度,你很容易理解如何使用strlen()函数。这个函数执行较快,没有进行任何计算操作,而仅仅返回C结果字符串的长度(在PHP中的变量与C变量内部结构相同)。但是strlen()是一个函数,于其他函数一样,在使用时需要进行几个操作,如全部小写化,函数查找。在某些场合,不可以使用isset()来提高你的代码速度。 例子: if (strlen($foo) < 5) { echo "Foo is too short"; } vs. if (!isset($foo{5})) { echo "Foo is too short"; } 调用isset()比strlen()要快,因为isset(0是一种语法结构而不是以个函数。在执行时不需要进行小写化和函数查找。这意味着你并没有真正取得字符串的长度。 2)使用递增或递减时,$i++比++$i稍慢,和其他语言相比,在PHP是一个特例的,不要在C和JAVA中也使用这个技巧。在PHP中$++比++$i快的原因是$i++进行了四次计算,而++$i进行三次。后缀递加先申请了一个临时变量,然后增加。而前缀递加直接使用了原变量。这也是ZEND的PHP优化器优化的一部分,但这还是一个好的建议,因为并不是所有的优化器都优化了这一点,以及并不是所有ISP都支持优化器。 3)当需要输出文本时,PHP有很多的方法。很多PHPer并不知道所有的方法,结果PHPers使用了他们以前所习惯的语法。这是可以理解的,虽然这并不是达到所有程序运行的最佳效率。 print 对 echo 两者都是语法结构,但print比echo 还是稍稍慢一点。理由很简单,不管是否需要,print会返回一个状态标示,而echo只是简单的输出而不做其他任何事情。而在绝大多数情况下,这个状态标示是没有用到的不必要的花费。 printf 使用printf()很慢,我强烈建议不在万不得已的时候不要使用这个函数。printf()对花费函数消耗。printf()是给需要进行参数格式化的情况下使用的。php是类型无关语言,大部分时间用在类型的隐形转化上。调用printf()来格式化字符串需要在字符串中扫描需要被替换的特殊字符,你可以预计的到这样的速度和效率。 heredoc 这种输出方式继承自PERL,这也被其他语言所采用。 没时间翻译了,给个精要得了: ?><? 替代 ?> <? 这样,PHP在执行时就不需要退出去处理那些空白输出。 当然,我觉得这个可以直接删掉这一个?><? 4)很多脚本都喜欢使用正则表达式来验证用户输入数据,但正则匹配的速度是很慢的,在很多情况下,我们只是验证数据是不是象A-Z,0-9等等。我们可以使用ctype来替代正则。ctype扩展提供了一系列类C的is*()函数,不象C函数一次只能对一个字符进行验证,PHP的ctype函数可以对整个字符串操作,比正则的运行效率要高。 例子: preg_match("![0-9]+!", $foo); vs ctype_digit($foo); 5) 另一个PHP常用的操作是数组搜索,这个操作使用正则查找或完全遍历整个数组来实现,这在查找一个大数组或频繁查找时相当耗资源,我们该怎么做呢?你可以使用ZEND引擎技巧来优化它,关联数组元素实质上是以哈希表来存储的。哈希表查询速度是非常快的。所以查找数据可以简单的这样写:$value = isset($foo[$bar])) ? $foo[$bar] : NULL;这种查找模式比遍历查找要快,即便是字符关键字比数字关键字占用了更多内存。 例子: $keys = array("apples", "oranges", "mangoes", "tomatoes", "pickles"); if (in_array('mangoes', $keys)) { ... } vs $keys = array("apples" => 1, "oranges" => 1, "mangoes" => 1, "tomatoes" => 1, "pickles" => 1); if (isset($keys['mangoes'])) { ... } 下一个查找比上一个要快3倍。 如果你知道其他的优化技巧,请告诉我 |
目前已经有很多PHP的框架,Mojavi, WACT, PHP.MVC,
Phrame等等。它们主要是建立一套松散的PHP代码组织方式(比如
Model-view-controller)。其中一些更多的面向开发一个内容管理系统,并提供了诸如用户管理模块等更多的功能。(让我来理解MVC不是一件很简单的事情,一件很简单的事情为什么要分成3件呢?)
和这些框架相比,PRADO更专注于建立一个代码重用和事件驱动的编程标准。如果你曾经用Delphi或者Visual
Basic等这些RAD开发工具来开发Windows程序的话,那么你会发现使用PRADO来开发WEB应用是非常类似的,你可以很快就掌握PRADO来
进行WEB应用的开发。大多数情况下,你要做的仅仅是设置组件的属性和响应组件的事件。更高层次的代码重用,比如前面所说的用户管理模块,可以基于
PRADO组件来实现。
PRADO的思想最先我是从Apache Tapestry项目想到的。在设计和实现的时候, Borland Delphi
和Microsoft ASP.NET的设计思想起到了很重要的作用
。实际上,使用过ASP.NET的人可以发现PRADO中有很多地方和它是相似的。(呵呵,这一句知道,虽然我没有学会C#)。
安装就免笔记了,下载移动的过程而已。
例2. (2005年全国高考卷I)图1为亚洲两个国家略图,读图回答:

图1
据地理坐标判断,甲乙两地距离约为( )
A. 300千米 B. 550千米
解题依据
可以根据经纬度差量算两点之间的距离。由于地球表面的经线圈、赤道及所有圆心为地心的大圆长度都为4万千米,所以:
1. 同一经线上,全球各地纬度相差1°的间隔长度都相等(因为所有经线圈的长度为大圆,都相等),大约是111km;
2. 赤道上经度相差1°对应的弧长大约也是111km;
(Page 1 of 2, totaling 16 entries)