ある程度までは、記事は「データベースへのコードの保存またはブリックでのコードの収集」というトピックの結果です。その後、パフォーマンスに関する複数の質問が発生しました(ちなみに、データベースにすべてのコードを保存するために指定された技術に基づいて構築された別のプロジェクトはそれほど前に開始されていませんでした) 。 検討されたアプローチの利点の1つは、「デッド」セクションと外部ファイル接続を含まない純粋なモノリシックコードを取得できることです(たとえば、 includeまたはrequireを使用します 。簡単にするために、単に「包含」と呼びます)。 そのトピックに慣れていない人のために、「デッド」は確かにページで実行されないコードであることを説明します。
ちょっとした科学。 ある権威ある叔父ヴィクトル・イヴァンニコフが、ロシア科学アカデミーのシステム設計研究所の所長がデッドコードについて語っていることは次のとおりです。
「デッドコードはプログラムや回路の一部であり、どんな状況でも、どんな入力データでも決してありません。これは、特にメモリが限られているシステムにとっては重大な問題です。 デッドコードはプログラムの最大30%を占める場合があります。特に、アプリケーションの開発中に多くのコードが取得されるため、多くのコードがプログラムに導入されます。 デッドコードの問題はアルゴリズム的に解決できません 。 これは、プログラムのデッドコードを見つけるようなツールを作成できないことを意味します。
彼らは50代前半にこの問題に興味を持つようになりました。 対応するライス定理とウスペンスキーの定理は、同時に独立して証明されましたが、ウラジミールアンドレヴィッチでのみ、より一般的に定式化されています。 定理は実際、アルゴリズムの重要な特性を認識することは不溶性の問題であると述べています。
ウェブプログラミングでは、デッドコードの量は通常1桁多いことを自分から付け加えます。 スワップ接続では、そのシェアは簡単にしきい値を80〜90%超えます。 つまり、実際に実行されるコードは20行ごとです。 これは、「重い」フレームワークを使用する場合に特に顕著です。
以下で使用するいくつかの定義をすぐに紹介します。
モノリス -外部ファイル接続を使用しないコード(包含)
純粋なモノリス -「デッド」コードがないモノリス。
前述のように、純粋なモノリシックコードは、アプリケーションの全体的なパフォーマンスを大幅に向上させ、コメントで多くの論争と疑念を引き起こしました。 「デッド」コードとインクルージョンが一般にアプリケーションの速度を低下させることについて、当然の質問がありましたか? また、コードのパフォーマンスとクリーンさに関する問題の解決策として、 オペコードキャッシュ 、クラスとメソッドを自動的に接続する「マジック」機能(以降、簡単にするために単にautoloadと呼びます)、およびfastCGIについて説明しました 。
さて、真実を求めて質問をより深く調べてみましょう。 行きましょう。
問題はありますか?
最初に、デッドコードとインクルードがパフォーマンスにどの程度影響するかを調べてみましょう。
デッドコードから始めましょう。 2000、5000、10000行のコードのページを作成し、それらにapacheBenchmarkを設定します。 次の結果が得られます。
行数 | リクエスト/秒 | リクエストごとの平均時間 | デッドコードシェア |
---|---|---|---|
2000年 | 72.24 | 0.013 | 0 |
5000 | 32.20 | 0.031 | 0.6 |
10,000 | 15.97 | 0.062 | 0.75 |
以下では、古いFS Amilo 1718ラップトップで得られた時間を示します。異なるOSおよびFSを備えた異なるシステムで実行された制御テストの結果は、比例して異なりませんでした。
ご覧のとおり、スクリプトの処理に費やされる時間は、実際にはその中の行数に正比例します(スクリプトでは何もしないので、ほとんどの時間は構文解析にのみ費やされるためです。より多くの行-対応する解析時間)。 今回はどれくらいですか? それは不可欠です。 理想的には、デッドコードが存在しない場合でも、13分の1/3が多いことに同意します(3番目のテストのように62は言うまでもありません)。 この間、データベースへの接続、クエリなどを完了することにより、完成したページを提供できます。 解析のみがあります...
それでは、インクルージョンに対処しましょう。 4つの状況をシミュレートします。
-「モノリス」(インクルードおよびデッドコードなし)
-"swap"(通常、大きなファイルに結合されるすべてのライブラリの無条件の接続をシミュレートします。大きなファイルを含める必要はほとんどありません 。多くのデッドコード)
-「autoload」(必要に応じてクラス/メソッド/関数の接続をシミュレートします(通常は存在しないクラス/メソッド/関数へのアクセス時)。 小さなファイルを多く含みます 。デッドコードはほとんどありません)
-スワップと自動ロードの間のいくつかの中間状態。
結果を次の表に(パフォーマンスの順に)示します。
行数 | 含む | リクエスト/秒 | リクエストごとの平均時間 | デッドコードシェア | シミュレーションタイプ |
---|---|---|---|---|---|
2000年 | 0 | 72.24 | 0.013 | 0 | 純粋なモノリス |
2000年 | 60 | 35.12 | 0.028 | 0 | オートロード |
5000 | 7 | 25.63 | 0.039 | 0.6 | - |
10500 | 14 | 13.2 | 0.076 | 0.81 | - |
15,000 | 5 | 9.78 | 0.1 | 0.87 | スワップ |
予想どおり、最初はモノリスで、2番目はほぼ2倍の遅延オートロードです。 さて、スワップは神経質にサイドラインで喫煙します:)(本当です、これは今のところだけです、それから彼はまだ自動ロードのお尻を蹴ります。さらに記事を読んでください)。 しかし、リクエストを処理する時間はまだ非常に長いです...
ちなみに、この表は、システムを純粋なモノリスに移行するときに600%のゲインで示した数値を確認するものです。
問題があります-解決策があります
ページ解析コストを削減して問題を解決し、アプリケーションのパフォーマンスを向上させる主な手段は、バイトコードキャッシュです。 最も有名なキャッシュシステム(たとえばPHP)は、 eAccelerator 、 xCache 、およびAPCです。 テストでは、eAcceleratorがタスクのコンテキストで最も一般的で高速なものとして選択されました。 キャッシュシステムの比較の詳細については、 こちらをご覧ください 。 オペコードキャッシュを使用した結果は次のとおりです(パフォーマンス順)。
行数 | 含む | リクエスト/秒
(オペコードキャッシュなし) | リクエスト/秒
オペコードキャッシュ付き | 加速係数 | シミュレーションタイプ |
---|---|---|---|---|---|
2000年 | 0 | 72.24 | 412.86 | 5.71 | 純粋なモノリス |
15,000 | 5 | 9.78 | 204.6 | 20.92 | スワップ |
10500 | 14 | 13.2 | 192.2 | 14.56 | - |
2000年 | 60 | 35.12 | 112.11 | 3.19 | オートロード |
そして、ここで非常に興味深い事実を観察します。 オペコードキャッシュを使用する場合、大量のデッドコードがあるにもかかわらず、 スワップ接続はautoloadのほぼ2倍の効率です! そして、すべてが非常に大きな21倍の加速係数のおかげです。 しかし、オートロードでは、加速係数が最も低くなりました-オペコードキャッシュにより、コストがわずか3倍削減されました。 ここから簡単な結論を導きます。オペコードキャッシュは、「デッド」コードの問題を実際に解決しますが、インクルードの問題は解決しません。キャッシュは、多数の小さなファイルが好きではなく、パフォーマンスゲインの最も低い係数を示します。
しかし、FastCGIはどうですか?
多くの人によると、スクリプトを高速化し、スクリプトの「ロード」のコストを削減する別の方法は、FastCGIモードでPHPを実行することです。 これはそうではありません! 。 ここで Koterovから読むことができるPHPをfastCGIが高速化しない理由。 ところで、彼のeAcceleratorテストは、例としてZend Frameworkを使用して行われました。 Dmitry Koterovによって得られた結果は、このトピックで示された結果に非常に近いものです。
おわりに
この記事の目的は、デッドコードの影響と、コード内の外部ファイルの最終的なアプリケーションパフォーマンスへの接続を詳細に調べることでした。 ご覧のとおり、これらの要因の影響は非常に重要です。
この記事はNapolskyによって書かれましたが 、よく知られた理由により、彼はそれを公開できませんでした。 カルマで彼にすべて+;)