PHP の遅延読み込みと Iterator
の使用
最近転職し、ホームページ作成ソフトに切り替えました。弊社のホームページ作成ソフトのテンプレートシステムに問題があり、メモリが最大値を超えるメッセージが表示されます。メモリの問題を解決する最も簡単な方法は、php.ini を変更してmemory_limitを増やすことです。しかし、テンプレートの数が増え続けると、必要なメモリが上限を超えるため、上司からこの問題を検討するように頼まれました。何か良い解決策があるかどうかを確認してください。
この問題が発生したとき、私は最初に元のコードのアイデアを理解し、問題の主な原因を分析しました。それは、各ページに 16 個のテンプレートが表示され、ページ分割されていました。バックグラウンド処理は単純ではありません。まず、テンプレート データをデータベースから読み取るのではなく、サーバーからシリアル化された文字列を取得し、その情報をキャッシュします (読み取ります)。将来的には最初にキャッシュ)、配列内でフィルタリングとページング操作を実行し、表示用に 16 個のテンプレートを取り出します。
次に、問題を分析します。ここでの問題は、すべてのテンプレートの情報配列が取り出されるということですが、実際には各ページに必要なテンプレートの数は 16 つだけであることがわかります。すべて記憶に追加されました。
問題が見つかりました。解決するにはどうすればよいですか?そこで元社員に意見を聞いてみました。彼らは、処理のためにテンプレートをデータベースに置くことや、すべてのページングやその他の操作をサーバーに置くことなど、多くの意見を出しました。しかし、これらの解決策はすべて、バックエンド サーバーの大幅な処理改善を必要とし、導入するには大きすぎる変更でした。問題がたくさんあるのですが、どうすればいいでしょうか?
1. 遅延読み込み
後で考えたのですが、シリアル化するとすべてのデータが取り出されてしまうので、必要なデータだけをファイルから取り出すことができればいいのにと思いました。 Java の経験があるので、最初に思いつきました。はXML SAXの処理方法だったのですが、PHPでのXML処理に詳しくなくてわかりません。
しかし、それは私に正しい考えを与えてくれました。多くの PHP メモリの問題は、PHP 開発者が利便性のために必要なデータをすべてメモリ (配列) にプリロードし、それを処理するために必要なメモリが膨大であることが原因です。実際に必要な量を超えるため、メモリが過剰になります。解決策は遅延読み込みです。これにより、データは使用されるときにのみ処理のためにメモリに読み込まれます。
ここでの問題は明らかにシリアル化の問題です。PHP のシリアル化メカニズムはプリロード戦略であり、遅延ロードをサポートしていません。遅延読み込みをサポートし、一度に 1 つのテンプレートのコンテンツのみを読み取ることができるシリアル化方法を見つける必要があります。すぐに CSV 形式がこの読み取り方法を行単位でサポートするようになり、元のシステムではメジャーを必要としません。変更されるため、元のシステムを CSV シリアル化に変更する必要があります。
2.Iterator インターフェースの使用法
CSV の読み取りでは while を使用して走査しますが、元のシステムでは配列を使用して走査します。システム コードには多くのフィルター条件があるため、以前の配列は key=>value ペアを使用して実装されていましたが、csv では多くのコード変更が必要です。番号 0、1、2 を使用してのみアクセスできます。元のコードの修正を極力減らすため、まず1行目に配列のキー値を表示し、2行目以降にテンプレートの実際の数値を表示するようにcsvを加工しました。位置はキーと 1 対 1 に対応しており、将来の拡張性も満たします。
元のコードの foreach スタイルにできるだけ一致させるために、Iterator を使用して csv 操作をカプセル化し、その中で csv のキーと値のマージを完了しました。この方法では、コードの移行はほとんど無視できます。さらに大きな利点は、CSV ファイルのサイズがシリアル化されたファイルのサイズよりもはるかに小さいことです。パフォーマンスの問題を心配する人もいるかもしれません。
テストの結果、現在 2,000 のテンプレートがあり、速度は 1 秒を超えません。将来的には、テンプレートの数は 20,000 に増加し、走査速度も 2 秒を超えません。許容範囲。それで問題は解決しました。
最近、簡易自作ORMフレームワークのメモリが上限値を超えたのも原因で、データベースの値が全てメモリ配列に入れられてしまったので、片手に遅延ロードの槍と盾を持ちました。もう一方の反復子、そして再び問題解決戦争に突入します。