Heim  >  Artikel  >  Backend-Entwicklung  >  Vertiefte Kenntnisse der PHP-Optimierung und Vorsichtsmaßnahmen

Vertiefte Kenntnisse der PHP-Optimierung und Vorsichtsmaßnahmen

黄舟
黄舟Original
2017-07-27 10:15:181082Durchsuche

Dieser Artikel ist eine detaillierte Analyse und Einführung in effiziente Schreibmethoden in PHP. Er ist sehr hilfreich für alle, die ihn benötigen.

1. Machen Sie es so statisch wie möglich:

Wenn eine Methode statisch sein kann, deklarieren Sie sie als statisch Geschwindigkeit kann um 1/4 verbessert werden, selbst als ich es getestet habe, hat sich diese um fast das Dreifache erhöht.

Natürlich muss diese Testmethode auf Stufe 100.000 oder höher ausgeführt werden, damit der Effekt offensichtlich ist.

Tatsächlich besteht der Hauptunterschied in der Effizienz zwischen statischen Methoden und nicht statischen Methoden im Speicher: Statische Methoden generieren Speicher, wenn das Programm gestartet wird, und Instanzmethoden generieren Speicher, während das Programm ausgeführt wird, sodass statische Methoden dies können Direkt aufgerufen, und Instanzmethoden müssen zuerst erstellt werden. Die statische Geschwindigkeit ist sehr hoch, aber zu viel belegt den Speicher.

Jede Sprache arbeitet auf Speicher und Festplatte. Ob sie objektorientiert ist oder nicht, ist nur eine Frage der Softwareschicht. Die unterste Ebene ist dieselbe, aber die Implementierungsmethode ist unterschiedlich. Der statische Speicher ist kontinuierlich, da er zu Beginn des Programms generiert wird, während die Instanz diskreten Speicherplatz beansprucht. Daher ist er natürlich nicht so schnell wie die statische Methode.

Statische Methoden rufen immer denselben Speicher auf. Der Nachteil besteht darin, dass sie nicht automatisch zerstört werden können, sondern durch Instanziierung.

2. Echo ist effizienter als print, da echo keinen Rückgabewert hat und print eine Ganzzahl zurückgibt.


Der Unterschied beträgt etwa 8 %. Im Allgemeinen ist Echo schneller.

Echo
0.000929 - 0.001255 s (平均 0.001092 seconds)
Print
0.000980 - 0.001396 seconds (平均 0.001188 seconds)
Beachten Sie, dass beim Echo großer Saiten die Leistung erheblich beeinträchtigt wird, wenn keine Anpassungen vorgenommen werden. Verwenden Sie mod_deflate, um Apached zur Komprimierung zu öffnen, oder öffnen Sie ob_start, um den Inhalt zuerst in den Puffer zu stellen.

3. Stellen Sie die maximale Anzahl von Schleifen vor der Schleife ein, nicht während der Schleife.

Das versteht jeder Narr.

4. Zerstören Sie Variablen, um Speicher freizugeben, insbesondere große Arrays. Dies liegt an der zugrunde liegenden Zend-Engine von PHP. Ursache:

Im Allgemeinen beträgt die Speicherauslastung von PHP-Arrays nur 1/10. Das heißt, ein Array mit 100 MB Speicher in der Sprache C erfordert 1 GB in PHP. Gerade in Systemen, in denen PHP als Backend-Server verwendet wird, tritt häufig das Problem eines übermäßigen Speicherverbrauchs auf.

5. Vermeiden Sie die Verwendung magischer Methoden wie __get, __set, __autoload usw.;

Benennen Sie diese Funktionen in „First“. Besuch unter bestimmten Bedingungen. Im Allgemeinen gibt es die folgenden magischen Funktionen

<strong>__construct(), __destruct(), __get(), __set(), __unset(), __call(), __callStatic(), __sleep (), __wakeup(), __toString(), __set_state(), __clone(), __autoload()</strong>

Tatsächlich kann __autoload den Klassennamen nicht effizient mit dem tatsächlichen Vergleichen auf die Festplattendatei (beachten Sie, dass sich dies auf die tatsächliche Festplattendatei bezieht, nicht nur auf den Dateinamen), muss das System eine große Anzahl von Urteilen darüber fällen, ob die Datei vorhanden ist (sie muss in dem in jeder Datei enthaltenen Pfad durchsucht werden). Um festzustellen, ob eine Datei vorhanden ist, sind Festplatten-E/A-Vorgänge erforderlich. Wie wir alle wissen, ist die Effizienz von Festplatten-E/A-Vorgängen sehr gering. Dies ist der Grund, warum die Effizienz des Autoload-Mechanismus verringert ist.

Daher müssen wir beim Entwurf des Systems einen klaren Mechanismus für die Zuordnung von Klassennamen zu tatsächlichen Festplattendateien definieren. Je einfacher und klarer diese Regel ist, desto effizienter ist der Autoload-Mechanismus. <strong>__construct(),__destruct(),__get(),__set(),__unset(),__call(),__callStatic(),__sleep(),__wakeup(),__toString(),__set_state(),__clone(),__autoload()</strong>

Fazit: Der Autoload-Mechanismus ist nicht von Natur aus ineffizient. Nur der Missbrauch von Autoload und schlecht konzipierte Autoload-Funktionen führen zu einer Verringerung seiner Effizienz.

Vermeiden Sie daher die Verwendung der __autoload-Magie ist fraglich.

6.requiere_once() ist relativ ressourcenintensiv;

Dies liegt daran, dass requirere_once feststellen muss, ob auf die Datei verwiesen wurde). möglichst wenig genutzt. Häufig verwendete „require/include“-Methoden sollten vermieden werden.
7. Verwenden Sie absolute Pfade in Includes und Requires.

Wenn ein relativer Pfad enthalten ist, durchläuft PHP den include_path, um die Datei zu finden.
Durch die Verwendung absoluter Pfade werden solche Probleme vermieden, sodass die Auflösung des Betriebssystempfads weniger Zeit in Anspruch nimmt.


8. Wenn Sie die Zeit benötigen, zu der das Skript ausgeführt wird, ist $_SERVER['REQUSET_TIME'] besser als time();

Wie Sie sich vorstellen können. Einer ist fertig und kann direkt verwendet werden, der andere erfordert das von der Funktion erhaltene Ergebnis. 9. Wenn Sie die internen String-Manipulationsfunktionen verwenden können, versuchen Sie, diese anstelle regulärer Ausdrücke zu verwenden.
Das ist nicht nötig. Regelmäßigkeit verbraucht die meiste Leistung.

Gibt es nützliche Funktionen, die Sie vermisst haben? Beispiel: strpbrk()strncasecmp()strpos()/strrpos()/stripos()/strripos() beschleunigen strtr. Wenn Sie nur ein einzelnes Zeichen konvertieren müssen, Verwenden Sie einen String anstelle eines Arrays do strtr:



Effizienzverbesserung: 10-mal.


10.str_replace Zeichenersetzung ist schneller als normale Ersetzung preg_replace, aber strtr ist 1/4 schneller als str_replace;
<?php
$addr = strtr($addr, "abcd", "efgh"); // good
$addr = strtr($addr, array(&#39;a&#39; => &#39;e&#39;, )); // bad
?>

另外不要做无谓的替换即使没有替换,str_replace 也会为其参数分配内存。很慢!解决办法:
用 strpos 先查找(非常快),看是否需要替换,如果需要,再替换效率:- 如果需要替换:效率几乎相等,差别在 0.1% 左右。
如果不需要替换:用 strpos 快 200%。

11.参数为字符串

如果一个函数既能接受数组又能接受简单字符做为参数,例如字符替换函数,并且参数列表不是太长,可以考虑额外写一段替换代码,使得每次传递参数都是一 个字符,而不是接受数组做为查找和替换参数。大事化小,1+1>2;

12.最好不用@,用@掩盖错误会降低脚本运行速度;

用@实际上后台有很多操作。用@比起不用@,效率差距:3 倍。特别不要在循环中使用@,在 5 次循环的测试中,即使是先用 error_reporting(0) 关掉错误,在循环完成后再打开,都比用@快。

13.$row['id']比$row[id]速度快7倍

建议养成数组键加引号的习惯;

14.在循环里别用函数

例如For($x=0; $x 48501fad7ec9f8ada671c1a739f00b12prop++)比局部变量要慢3倍;

19.建立一个未声明的局部变量要比一个已经定义过的局部变量慢9-10倍

20.声明一个未被任何一个函数使用过的全局变量也会使性能降低(和声明相同数量的局部变量一样)。
PHP可能去检查这个全局变量是否存在;

21.方法的性能和在一个类里面定义的方法的数目没有关系

因为我添加10个或多个方法到测试的类里面(这些方法在测试方法的前后)后性能没什么差异;

22.在子类里方法的性能优于在基类中;

23.只调用一个参数并且函数体为空的函数运行花费的时间等于7-8次$localvar++运算,而一个类似的方法(类里的函数)运行等于大约15次$localvar++运算;

24 用单引号代替双引号来包含字符串,这样做会更快一些。
因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会。

PHP 引擎允许使用单引号和双引号来封装字符串变量,但是这个是有很大的差别的!使用双引号的字符串告诉 PHP 引擎首先去读取字符串内容,查找其中的变 量,并改为变量对应的值。一般来说字符串是没有变量的,所以使用双引号会导致性能不佳。最好是使用字

符串连接而不是双引号字符串。


BAD:
$output = "This is a plain string";
GOOD:
$output = &#39;This is a plain string&#39;;
BAD:
$type = "mixed";
$output = "This is a $type string";
GOOD:
$type = &#39;mixed&#39;;
$output = &#39;This is a &#39; . $type .&#39; string&#39;;

25.当echo字符串时用逗号代替点连接符更快些。

echo一种可以把多个字符串当作参数的“函数”(译注:PHP手册中说echo是语言结构,不是真正的函数,故把函数加上了双引号)。
例如echo $str1,$str2。

26.Apache解析一个PHP脚本的时间要比解析一个静态HTML页面慢2至10倍。

尽量多用静态HTML页面,少用脚本。

28.尽量使用缓存,建议用memcached。

高性能的分布式内存对象缓存系统,提高动态网络应用程序性能,减轻数据库的负担;
也对运算码 (OP code)的缓存很有用,使得脚本不必为每个请求做重新编译。

29.使用ip2long()和long2ip()函数把IP地址转成整型存放进数据库而非字符型。

这几乎能降低1/4的存储空间。同时可以很容易对地址进行排序和快速查找;

30.使用checkdnsrr()通过域名存在性来确认部分email地址的有效性

这个内置函数能保证每一个的域名对应一个IP地址;

31.使用mysql_*的改良函数mysqli_*;

32.试着喜欢使用三元运算符(?:);

33.是否需要PEAR

在你想在彻底重做你的项目前,看看PEAR有没有你需要的。PEAR是个巨大的资源库,很多php开发者都知道;

35.使用error_reporting(0)函数来预防潜在的敏感信息显示给用户。

理想的错误报告应该被完全禁用在php.ini文件里。可是如果你在用一个共享的虚拟主机,php.ini你不能修改,那么你最好添加error_reporting(0)函数,放在每个脚本文件的第一行(或用
require_once()来加载)这能有效的保护敏感的SQL查询和路径在出错时不被显示;

36.使用 gzcompress() 和gzuncompress()对容量大的字符串进行压缩(解压)在存进(取出)数据库时。

这种内置的函数使用gzip算法能压缩到90%;

37.通过参数变量地址得引用来使一个函数有多个返回值。

你可以在变量前加个“&”来表示按地址传递而非按值传递;

38. 完全理解魔术引用和SQL注入的危险。

Fully understand “magic quotes” and the dangers of SQL injection. I'm hoping that most developers reading this are already familiar with SQL injection. However, I list it here because it's absolutely critical to understand. If you've never heard the term before, spend the entire rest of the day googling and reading.

39.某些地方使用isset代替strlen

当操作字符串并需要检验其长度是否满足某种要求时,你想当然地会使用strlen()函数。此函数执行起来相当快,因为它不做任何计算,只返回在zval 结构(C的内置数据结构,用于存储PHP变量)中存储的已知字符串长度。但是,由于strlen()是函数,多多少少会有些慢,因为函数调用会经过诸多步骤,如字母小写化(译注:指函数名小写化,PHP不区分函数名大小写)、哈希查找,会跟随被调用的函数一起执行。在某些情况下,你可以使用isset() 技巧加速执行你的代码。
(举例如下)

if (strlen($foo) < 5) { echo “Foo is too short”$$ }

(与下面的技巧做比较)

if (!isset($foo{5})) { echo “Foo is too short”$$ }

调用isset()恰巧比strlen()快,因为与后者不同的是,isset()作为一种语言结构,意味着它的执行不需要函数查找和字母小写化。也就是说,实际上在检验字符串长度的顶层代码中你没有花太多开销。

40.使用++$i递增


When incrementing or decrementing the value of the variable $i++ happens to be a tad slower then ++$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 preincrementation 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.

当执行变量$i的递增或递减时,$i++会比++$i慢一些。这种差异是PHP特有的,并不适用于其他语言,所以请不要修改你的C或Java代码并指望它们能立即变快,没用的。++$i更快是因为它只需要3条指令(opcodes),$i++则需要4条指令。后置递增实际上会产生一个临时变量,这个临时变量随后被递增。而前置递增直接在原值上递增。这是最优化处理的一种,正如Zend的PHP优化器所作的那样。牢记这个优化处理不失为一个好主意,因为并不是所有的指令优化器都会做同样的优化处理,并且存在大量没有装配指令优化器的互联网服务
提供商(ISPs)和服务器。

40. 不要随便就复制变量

有时候为了使 PHP 代码更加整洁,一些 PHP 新手(包括我)会把预定义好的变量复制到一个名字更简短的变量中,其实这样做的结果是增加了一倍的内存消耗,只会使程序更加慢。试想一下,在下面的例子中,如果用户恶意插入 512KB 字节的文字到文本输入框中,这样就会导致 1MB 的内存被消耗!


BAD:
$description = $_POST[&#39;description&#39;];

echo $description;
GOOD:
echo $_POST[&#39;description&#39;];

41 使用选择分支语句

switch case好于使用多个if,else if语句,并且代码更加容易阅读和维护。

42.在可以用file_get_contents替代file、fopen、feof、fgets

在可以用file_get_contents替代file、fopen、feof、fgets等系列方法的情况下,尽量用file_get_contents,因为他的效率高得多!但是要注意file_get_contents在打开一个URL文件时候的PHP版本问题;

43.尽量的少进行文件操作,虽然PHP的文件操作效率也不低的;

44.优化Select SQL语句,在可能的情况下尽量少的进行Insert、Update操作(在update上,我被恶批过);

45.尽可能的使用PHP内部函数

46.循环内部不要声明变量,尤其是大变量:对象

(这好像不只是PHP里面要注意的问题吧?);

47.多维数组尽量不要循环嵌套赋值;

48.foreach效率更高,尽量用foreach代替while和for循环;

49.“用i+=1代替i=i+1。符合c/c++的习惯,效率还高”;

50.对global变量,应该用完就unset()掉;

51 并不是事必面向对象(OOP),面向对象往往开销很大,每个方法和对象调用都会消耗很多内存。

52 不要把方法细分得过多,仔细想想你真正打算重用的是哪些代码?

53 如果在代码中存在大量耗时的函数,你可以考虑用C扩展的方式实现它们。

54、打开apache的mod_deflate模块,可以提高网页的浏览速度。
(提到过echo 大变量的问题)

55、数据库连接当使用完毕时应关掉,不要用长连接。

56、split比exploade快


split()
0.001813 - 0.002271 seconds (avg 0.002042 seconds)
explode()
0.001678 - 0.003626 seconds (avg 0.002652 seconds)
Split can take regular expressions as delimiters, and runs faster too. ~23% on average.

Das obige ist der detaillierte Inhalt vonVertiefte Kenntnisse der PHP-Optimierung und Vorsichtsmaßnahmen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn