PHPコードを最適化するための一連の50以上のヒント。 このような最適化の長所と短所。 最初の10のヒント。

これは、PHPコードの最適化に関する記事の最初の10のヒントの翻訳です。 Habréには、記事の古いバージョンの翻訳があります-PHP コードを最適化するための40のヒント



既存の翻訳に追加のヒントを追加するだけでなく、なぜそれが速くなるのかを説明し、異なるチームでの開発と作業の経験に基づいて、そのような最適化の意味についての考えを追加しました。



私は部品を書きます、さもなければ、それはすぐに多くの材料になります。



これがハブに関する私の最初の記事であり、興味深いことがわかったと思います。





通知:

この記事では、元の記事のアドバイスにしばしば反対します。 私の挿入物は斜体です。 そして、私が最適化のヒントに賛成または反対する理由を議論しようとします。



私はテストの正確性について責任を負いません。私自身はテストを実施しませんでした。 ほとんどのヒントについて、ほとんどの場合、その差は非常に小さく、他の要因が重要な役割を果たす-可読性、スケーラビリティ、柔軟性が理由である場合。 そして財政的正当化。



私は専門家のふりをしません。また、ヒントに関する私のコメントを行動の直接的な指示とは見なしません。 さらに、元の記事のヒントを使用することをお勧めしません。



私が座ってこの記事を書くことにした主な理由は、最適化の必要性に関する議論を解決しようとする試みであり、「マッチを節約する」ことです。



私は自分自身のために(経験などに基づいてどこかで読んだから)、リストの形で与えたいと思います:



1.開発段階で、事前に最適化を行わないでください

2.マッチを保存しない

3.最初にボトルネックに注意を払い、最適化が最も効果的な場所

4.コードは、読みやすく、スケーラブルで、柔軟でなければなりません。 (ただし、タスクによって要件は異なる場合があります)。



注:

-作成者はすべてのリンクの名前に「[引用]」というテキストを使用しますが、リンクの一部は、たとえば1つまたは別のデザインのパフォーマンスに関するステートメントを証明するテストにつながります。 テスト[test]につながるリンクと、有用なリソース "[役に立つ情報]"につながるリンクと、それぞれ記事[article]を参照します。



-追加した部分を斜体で強調します。



重要! 元の記事の最適化のヒントを使用することはお勧めしません。 それどころか、斜体の行でこれらのヒントの意味を検討したり、ヒントに反論したり、使用が理にかなっているケースを検討したりします。 読む前に、時期尚早の最適化は開発プロセスとコードを悪化させるだけであるという古い真実をもう一度思い出したいと思います。 そして、ペニーを節約しないでください。



オリジナルに追加したのは、経験と知識だけです。



読者:この記事は、主にWeb開発の達人ではなく、経験を積んだばかりの人を対象としています。 しかし、それが専門家にとって興味深いものになることを願っています。



行こう:)



1. echoは printよりも高速です。 [テスト]



そして、1文字少なく書きます。 むしろ、このアドバイスは一般的な開発のためのものです。 ほとんどのプログラマーはechoを使用します。 パフォーマンスの向上は最小限です。 また、深刻なエコープロジェクトでは、まれな構造です。 通常、出力は最初に収集されてから破棄されるためです。



2. PHPは、二重引用符で囲まれた文字列内の変数を検索するため、二重引用符ではなく、単一引用符で囲まれた文字列の方が高速です。変数がない場合は、文字列を単一引用符で囲みます。



視覚的に一重引用符で囲まれた文字列は、読みやすくなります。 しかし、連結で接続された可変文字列ではなく、単なる文字列である場合。 この場合、二重引用符で囲まれた文字列に変数を挿入するだけでパフォーマンスが向上します。 さらに、連結の魅力は読めないように見えます。



3.二重引用符で囲まれた変数の代わりにsprintfを使用します。 これは約10倍高速です。 [テスト]



これはおそらく、sprintfを使用する場合、PHPがC関数sprintfを呼び出すためです。 これは、文字列の解析がCで記述されたPHP自体で行われる場合よりも高速です。しかし、このようなコードは簡単に認識できるとは思いません。 おそらくこれは、文字列で多くの作業が行われる非常に負荷の高いプロジェクトで意味があり、sprintfを使用すると、目に見えるパフォーマンスの向上が得られます。 しかし、私はそのようなプロジェクトを想像していません。 通常、すべてが他の場所に落ちます。



4.文字列連結を使用する代わりに、いくつかのパラメーターをエコーに渡します。 [記事]



連結がなく、時間がかかるという事実により、これがより速く動作することは論理的です。 そして、パラメーターは出力ストリームに次々にスローされます。 可読性に関しては、個人的には連結よりも複数のパラメーターを読む方が便利ですが、誰もがこれを実行できるわけではありません。



echo $a, 'text', $b, 'more text'; //

echo $a . 'text' . $b . 'text'; //









目のメモによると、 phpbench.comテストの結果によると、エコー用の定数文字列の連結は、複数のパラメーターで渡すよりも高速に動作します



5.ループ自体のループの最後の反復を決定するために、配列要素の数、文字列の長さなどの計算を使用しないでください。 forループの前に最大値を設定します。 例: for($ x = 0; $ x <count($ array); $ x) 、各反復でcount()を呼び出し、 $ max = count($ array);を使用 サイクルの前に。 リンク[テスト]



これは長い間知られている事実です。 テストでは、10倍のパフォーマンスの違いが示されています。 データの配列がかなり大きい場合、または同様の計算が頻繁に発生する場合は、検討する価値があります。 可読性はいかなる影響も受けません。



6.特に大きな配列の場合は、変数を逆参照または無効化してメモリを解放します。 [お役立ち情報]



これは、たとえば、バッファからデータベースクエリを削除する場合にも適用されます。 ただし、未使用の変数をすべて削除すると、コードの可読性が大幅に低下します。 可能な限り変数を使用することも、優れたプログラミングスタイルの兆候ではありません。

//

$time = time();

$login = $_SESSION['login'];

$hash = md5($login . $time);



//

$hash = md5( $_SESSION['login'] . time() );









このデザインが一度使用された場合。 したがって、目はコードをよりよく認識します。 それは一行だからです。 ただし、ここで関与しないでください。読みにくくなる可能性があります。 しかし、これはつまずきです。

リソース(変数、データベースへのクエリの結果など)からメモリを解放する最適化は、負荷のかかった完成したアプリケーションで既に実行する必要があります。 次に、そのような最適化の利点を評価できます。



7. __get、__ set、__ autoloadなどの魔法のメソッドを避ける[有用な情報]



...また、__ call、__ toString ...正当化されません。 たとえば、オーバーロードは開発を大幅に簡素化し、コードの量を減らします。 __autoloadに関しては、これが重要なポイントです。 私自身の経験から、これは便利です。 しかし同時に、新しい人がプロジェクトに来た場合、__ autoload()を使用するよりも直接のインクルードのほうが目に見えるので、プロジェクトに参加するのに必要な時間が短くなります。



8.可能であれば、 require_once()の代わりにrequire()を使用します[記事]



非常に不当な節約。 require_onceの代わりにrequireを使用すると 、既にロードされたファイルがロードされる可能性が高くなりますが、コード実行時間は明らかに短縮されません。 はい、それはこのファイルが既にどこかで友人であるかどうかを心配しすぎます。これはチームワークで特に重要であり、開発を遅くします



9. include(_once)およびrequire(_once)フルパスを使用して、OSパスの解決にかかる時間を短縮します。 [記事]



これは別の理由で合理的です。 document_rootのルートにないスクリプトからの場合は、上位または下位にある別のスクリプトをロードする必要があります。 これにより、プロジェクト内のスクリプトが接続されているとき、それらのスクリプトの相対的な位置を心配する必要がなくなります。 ただし、パスの場合は、$ _SERVER ['DOCUMENT_ROOT']またはgetcwd()を使用して定数を定義することをお勧めします。 また、php.iniの設定に、PHPがdocument_root内のスクリプトを単純に検索しないというパスエラーが発生する場合があります。この手法により、これからユーザーを保護することができます。 また、フォルダごとに異なる定数を使用すると、コードが読みやすくなります。 例:

TEMPLATES_DIR

CORE_DIR

MODULES_DIR







10. require()include()は 、includeファイルが見つからない場合にrequireがスクリプトの実行を停止することを除いて、すべての点で同一です。 速度の違いはごくわずかです。



include()ファイルが見つからない場合、警告を発行し、requireはアプリケーションを終了します。 ほとんどの場合、特に本番サーバーではエラー出力が無効になっていること、ファイルを接続しないことが重要であることを考慮すると、さまざまなリソースとこのファイルの機能を必要とする他のコンポーネント(クラス、定数、関数など)



require経由で接続されたファイルには、実行フェーズの開始時にインクルードファイルが含まれ、解釈中にインクルードされます。 また、includeがifブロック内にあり、条件が満たされない場合、ファイルは含まれません。



残りの40以上のヒントは、近い将来に提供される予定です。




All Articles