
記事は、ライブプロジェクトがスローダウン(またはスローダウン)しなかったり、サードパーティ製品を調査するための出発点にならないようにするのに役立ちます。
たとえば、あなたの仕事は、「Samopisnayaシステム3.14」の内部で何が起こっているのかを理解し、クライアントごとに100メガバイトのRAMを消費しないようにすることです。
研究プログラムについて
WebAsyst Shop-Script- LLC Artikusのメンバーによる2回目の試み。 最初の試みは穴でいっぱいで、今日のShop-Script Premiumに多くの問題をもたらしました。
厳密に言えば、WebAsystはメモ帳、カレンダー、プロジェクトマネージャーなどのプログラムの複合体ですが、インターネット開発やビジネスの初日ではない人にとっては、これらのソリューションは興味深いものではありません(ベースキャンプ)。
彼らの試みが成功を収めたかどうかにかかわらず、私はそう言うことができます、私たちはちょうど最近、代替ブランチの666回目の改訂を祝いました、これは終わりではありません。
目標
目標は、最もリソースを消費する操作を特定し、重要なデータボリュームを持つシステムの状態を判断することです。 データとは、カテゴリと製品の数を意味します。 場合によっては、最適化に関する推奨事項が作成されますが、問題の原因を突き止めてそれを中和することはそれほど難しくありません。
準備:ディレクトリ構造と依存関係
最近、habravoprosyでファイル間の依存関係を自動的に生成するコンポーネントについて質問し、Graphvizと友達で
ある拡張機能を自分で発見しました。それ以外の場合は、プログラムのほとんどの最も重要なコンポーネントが
\ published \ SC \ html \ scripts \ modules \ test \ class.test.phpそして、なぜあなたが必要なの
published \ SC \ html \ scripts \ modules \ test \ _methods \ search_simple.phpは退屈で面白くないでしょう。
時間と本質を知る必要があったので、私はgrepの道をたどりましたが、もうそれは欲しくなく、アドバイスもしません。
特にコールバックに関する彼らの実験を考慮して、そこから私はまだ吐き気を感じます。
準備:コンテンツの充填
少量のデータのテスト(アルファ開発段階でない限り)が意味をなさないと主張するのは愚かでしょう。 したがって、まず最初に、CMSを目玉の内容で満たします。 実際のデータがない場合は、できるだけ長くデータベースに書き込むスパマーを作成します。
WebAsyst SSは、450番目と4500番目の製品を含むカタログ上でまったく異なる動作をします。
準備:標準関数のオーバーロード
OOPの観点からオーバーロードについては説明しませんが、額のオーバーロードについては説明しません。 この方法は簡単です。標準関数を探してすべてのファイルを調べ、ov_ {original_name}に置き換えます。ここですべてのカードが開いています。 すべてのデータベースクエリを記録し、fopen、fwrite、file_get_contentsをノックしたり、evalのようなブラックマジックを使用しようとしたりするタイミングを確認します。 パフォーマンスは通常バックエンドに依存するため、最も便利なロギングはmysql_queryです。
私はこのようなものを使用しています:
function ov_mysql_query($text) {
$debug= false ;
if ($debug){
$source=debug_backtrace();
$src_array_count=count($source);
$what=array( '\r\n' , '=' , ',' , '?' , '&' , '+' , ')' , '(' , '/' );
$to=array( '\r\n' , '_' , '_' , '_' , '_' , '_' , '_' , '_' , '_' );
$filename=str_replace($what,$to,$_SERVER[ 'REDIRECT_URL' ]);
static $function_counter_m = 0;
$function_counter_m++;
$oldDir=getcwd();
chdir($_SERVER[ 'DOCUMENT_ROOT' ]);
$fp = fopen( 'logs/' .$filename. '.log' , 'a' );
fwrite($fp, $function_counter_m. ') ' .str_replace( '\r\n' , '' ,trim($text)). "\r\n" );
for ($i=0;$i<$src_array_count;$i++) {
fwrite($fp, 'DEBUG INFO:' .$source[$i][ 'file' ]. ' | ' .$source[$i][ 'line' ]. "\r\n" );
}
fwrite($fp, "\r\n" );
fclose($fp);
chdir($oldDir);
}
$q=mysql_query($text);
return $q;
}
作業の結果、リクエストに関するデバッグ情報(コールスタック)を含むファイルとリクエスト自体がwww / logsフォルダーに保存されます。
準備:xDebug
正直に言うと、他の誰かのメカニズムを解明する試みをデバッグと呼ぶのは難しいです。 むしろ、それは準備です。 ただし、デバッガを直接使用できるかどうかは、ボトルネックを特定してシステムを最適化できるかどうかによって決まります。 phpでプログラムを作成する場合は、xDebugが必要です。xDebugは無料で、少なくとも少しの自尊心のあるphpコードエディターによってサポートされています。
デバッガは、設定したディレクトリに特別なダンプを生成し、そこにさまざまなデータが保存されます(オプション)。 私が持っている主なOSはWindowsであるため、Linux kovcachegrindはwincachegrindよりもはるかに便利であるため、このステップで利点があります(両方のプログラムでこれらのダンプを表示できますが、実際にはこれらはメモ帳で読むことができる通常のtxtファイルです重大度)。
ゾンビを遅くし始めましょう。
テストスタンド
- WebAsystの使用バージョン :287(クリーン、パッチおよびmodなし)*
- データベース内の製品の数 :4461
- データベース内の特性のタイプの数 :144
- データベース内の特性値の数 :44170
- データベース内のカテゴリ数 :354
- データベース内の写真の数 :3516
*しかし、とにかく変更ログを追う人には、250からは管理ウィンドウのサブウィンドウのボタンの色のみが異なるため
初期構成について少し
1つの製品と1つのカテゴリのデフォルトでのクリーンエンジンの結果。 プログラムには通常のキャッシングメカニズムがありますが、どれだけ正当化できるかを判断できます。
ページ* | デフォルトキャッシュを使用したデータベースクエリ | デフォルトキャッシュなしのデータベースクエリ | デフォルトのキャッシュでのダウンロード速度** | デフォルトキャッシュなしのダウンロード速度** |
ホーム | 64 | 73 | 10,304 | 17,011 |
カテゴリー | 83 | 90 | 10,616 | 19,457 |
製品 | 100 | 107 | 15,010 | 28,731 |
検索(成功) | 69 | 76 | 10,507 | 18,209 |
*リンクはページのスクリーンショットにつながるため、要求されたデータ量が表示されたものに比例しているかどうかが明確になります。
** Wincachegrindからの累積時間
髪の毛が立っていない場合は、読み進めて、1つの製品と1つのカテゴリしかないことを忘れないでください。
データ構成
数千の製品と強力なカタログ階層でテストベンチを使用するときが来ました。
ページ | デフォルトキャッシュを使用したデータベースクエリ | デフォルトキャッシュなしのデータベースクエリ | デフォルトのキャッシュでのダウンロード速度 | デフォルトキャッシュなしのダウンロード速度 |
ホーム | 64 | 73 | 12,323 | 19,404 |
カテゴリー | 186 | 193 | 20,333 | 29,881 |
製品 | 108 | 115 | 16,156 | 30,100 |
検索(成功) | 69 | 76 | 20,733 | 25,162 |
機能の選択(高度な検索) | 900 | 907 | 43,216 | 50,242 |
メインページに64個のクエリ(INステートメント(a、b、c、d、...、z))がまだ残っている場合、カテゴリは少しソーセージであり、特性による選択は通常のホスティングだけでなく破壊しますまた、VPS。 しかし、高度な検索を無効にすると役立つとは思わないでしょうか? このソフトウェア製品には、競合他社の手に負けて生活を困難にする可能性があるいくつかの文書化されていない機能があります。
これらの機能については、URlを処理するクラス(class.furl.php)を掘り下げることで学習できます。 たとえば、store.ru / category / category_with_lot_products /
all /のノンストップハンマーリクエストを実行できます。 トップレベルでこのカテゴリに113ページあります。
銘板:
ページ | デフォルトキャッシュを使用したデータベースクエリ | デフォルトキャッシュなしのデータベースクエリ | デフォルトのキャッシュでのダウンロード速度 | デフォルトキャッシュなしのダウンロード速度 |
カテゴリ(/すべて/) | 241 | 248 | 430,049 | 439,102 |
小小計
研究の現在の段階では、次のことがわかっています。
- 潜在的に高い負荷を作成することが可能です
- キャッシュありとキャッシュなしのデータベースクエリの数が多すぎます
また、store.ru / category / category_with_lot_productsページを読み込むときにデバッガーによって作成されたダンプを見ると、2つの最も大食いの操作を自信を持って区別できます。
foreach ($Interfaces as $_Interface){
ModulesFabric::callInterface($_Interface);
}
そして
print $smarty->fetch($CurrDivision->MainTemplate);
それらに加えて、カテゴリツリーの取得に多くのリソースが費やされ、is_objectが95千回以上呼び出され、プログラムはLanguagesManager :: getInstanceを70千回要求し、文字列の長さを28千以上と見なし、LanguagesManager :: ml_isEmpty呼び出しは最も遅い2/3です操作-getExtraParametrs。
問題解決オプション
かんたん
多くの訪問者がいないが、プログラムの速度が低下する場合は、最小限の統合時間でファイルキャッシュを使用できます。
次のスキームをお勧めします。
- 重い機能を見つける
- グローバル変数に依存するかどうかを判断する
- 名前を{original_function} _cachedなどに変更します
- {original_function}を作成し、その本文で特別な関数{original_function} _cachedを介して呼び出します
最適化の初期段階で、プログラムが迅速に機能する必要があり、時間がなかったときに、このソリューションを使用しました。
function cache_function($buildCallback, array $args = array(), $timeoutHours = 5){
$oldDir=getcwd();
chdir($_SERVER[ 'DOCUMENT_ROOT' ]);
// -
if (is_array($buildCallback)){
$cacheKey = get_class($buildCallback[0]) . '::' . $buildCallback[1];
}
else {
$cacheKey = $buildCallback . ':' . serialize($args);
}
$cacheKey .= ':' . serialize($args);
if (!file_exists( 'functions_cache/' .$buildCallback. '/' )) {
@mkdir( 'functions_cache/' .$buildCallback. '/' );
}
$file_path = 'system_cache/' .$buildCallback. '/' . sha1($cacheKey);
if (!file_exists($file_path) OR filemtime($file_path) < (time() - $timeoutHours*60)){
$result = call_user_func_array($buildCallback, $args);
file_put_contents($file_path, serialize($result), LOCK_EX);
} else {
$result = unserialize(file_get_contents($file_path));
}
chdir($oldDir);
return $result;
}
取得するもの:
function original_function($arg1,$arg2){
return cache_function( 'original_function_cached' ,array($arg1,$arg2),10);
}
その結果、original_function_cached関数の実行のシリアル化された結果がwww / functions_cache / original_function_cachedディレクトリに表示され、10時間使用されます。
難しい
関数の実行結果をどのようにキャッシュするかに関係なく、多数のコントローラーとプラグインを使用して多数のテンプレートを1つのページに収集するリソース集約型のフェッチが残っています。
ここでは、テンプレートの数を最適化して、テンプレートの通常の階層を作成し(デフォルトでは、すべてのテンプレートが一括して保存されます)、ブロックキャッシュに移行し始めることをお勧めします。 したがって、最も訪問されたページでは、かなり大きな速度の増加が見られます。
とても難しい
しかし、私と同じように、WAで作業する以外に選択肢がなく、長期にわたって使用する場合、これらはすべて半分の尺度です。
最適化、アルゴリズムの書き換えが必要であり(ページネーションを実装する方法を自由に見てください)、キャッシュをハッキングすることはできません。 一般的に、この点に関しては、特定の時間に新しいコンテンツが自動的に追加され、この時点でキャッシュ全体をリセットする余裕があることを知っているため、この点で簡単です。 価格と特性の無効化に対処するには、キャッシュグループを構成し、多くを変更する必要があります(URLの生成から皮膚の再構築まで)。 もちろん、ほとんどの問題ではスマートに対処できます。WebAsystSS自体はキャッシングメカニズムを使用するつもりはないようですので、プログラムを再構築する必要があります。
たとえば、製品でページ全体をキャッシュし、有効期間を5時間に設定します。 価格は以前に変更される可能性があると想定されていますが、キャッシュをリセットする必要はありません。 目的のモデルの目的のメソッド($ productModel-> getPrice($ pID)など)を有効にして価格を返すsmarty-pluginを作成できます。 商品のあるページで、データベースへの1つのクエリを受け取ります。 ビューキャッシュは再構築されません。
おわりに
どういうわけかそれは長い間判明しましたが、すべてが本質的にあるようです。
この記事の既製のソリューションと推奨事項が、新しいもの(含まれているかxDebugか、データベースからのすべての呼び出しがクラスを通過するという開発者向けの言葉を受け取らないルール)につながるか、古い開発に役立つことを願っていますアイデア。