複数のreadfile関数を使用してページが重い時の対処法
phpのreadfile関数を1ページに複数使うとページの読み込み速度がめちゃくちゃ遅くなりました。これを改善する方法を紹介します。
まえがき
先日、ある案件で
既に設置済みのWordPressがあるのにWordPressをもう一つインストールして更新箇所を2つに分けたいがヘッダーやフッターは同じものを使用したい
というふざけた要望を受けました。
共通のヘッダーやフッターを別のWordPressから読み込むためphpのreadfileを3つ程使用したところページ読み込み速度がめちゃくちゃ遅くそのままだと使い物にならないという事態が発生しました。
原因は3つのreadfile関数が直列に実行されていること。
これを並列に実行するようにして対応したので、その時のプログラムを覚え書きです。
複数のreadfile関数を並列に処理する
冒頭でも述べましたがreadfile関数を複数使うとページの読み込み速度が劇的に遅いです!!
例えばこんなコードですね。
別のWordPressのヘッダーとかフッターをreadfile関数で持ってくる場合。
<?php readfile("http://www.hoge.com/header"); ?> <?php readfile("http://www.hoge.com/sidebar"); ?> <div id="content"> ページ内容 </div> <?php readfile("http://www.hoge.com/footer"); ?>
readfile関数3つ使ってます。読み込むページのサイズにもよるかと思いますが、KoToRiの場合これで完全にページが読み込まれるのに10秒くらいかかりました。
これは3つのreadfile関数が一つずつ処理されていることが原因になります。
複数のreadfile関数を並列に処理するコードはこのようになります。
<?php $urls[] = 'http://www.hoge.com/header'; $urls[] = 'http://www.hoge.com/sidebar'; $urls[] = 'http://www.hoge.com/footer'; $results = getMultiContents($urls); foreach($results as $key => $value){ foreach($results[$key] as $key2 => $value2){ $html[$key][$key2] = $value2; } } function getMultiContents( $url_list ) { // マルチハンドルの用意 $mh = curl_multi_init(); // URLをキーとして、複数のCurlハンドルを入れて保持する配列 $ch_list = array(); // Curlハンドルの用意と、マルチハンドルへの登録 foreach( $url_list as $url ) { $ch_list[$url] = curl_init($url); curl_setopt($ch_list[$url], CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch_list[$url], CURLOPT_TIMEOUT, 1); // タイムアウト秒数を指定 curl_multi_add_handle($mh, $ch_list[$url]); } // 一括で通信実行、全て終わるのを待つ $running = null; do { curl_multi_exec($mh, $running); } while ( $running ); // 実行結果の取得 foreach( $url_list as $url ) { // ステータスとコンテンツ内容の取得 $results[$url] = curl_getinfo($ch_list[$url]); $results[$url]["content"] = curl_multi_getcontent($ch_list[$url]); // Curlハンドルの後始末 curl_multi_remove_handle($mh, $ch_list[$url]); curl_close($ch_list[$url]); } // マルチハンドルの後始末 curl_multi_close($mh); // 結果返却 return $results; } ?> <?php print $results['http://www.hoge.com/header']['content']; ?> <?php print $results['http://www.hoge.com/sidebar']['content']; ?> <div id="content"> ページ内容 </div> <?php print $results['http://www.hoge.com/footer']['content']; ?>
3~5行目にあらかじめ読み込みたいファイルのURLを「$urls」に配列で入れていきます。
例にあげたコードはURL3つだけですが、何個でもいけます。必要に応じて追加してください。
出力は下のタグになります。
<?php print $results['http://www.hoge.com/header']['content']; ?>
最初に必要なページを並列で一気に読み込んでおき、好きな場所にprint関数で出力する流れになっています。
まとめ
個人的にはすごく助かったので記事にしてみましたが、あまり需要はなさそうですかね。readfile関数たくさん使う場面なんて相当限られますから。
ほんとクライアントの無茶に付き合うと切りがないですね。
まぁ結果的に要望に応えてKoToRiもスキルアップできたのでHAPPYですが。
できることとできないことの見極めは非常に大切だと近頃痛感しております。
その辺の駆け引きがうまくなりたいです。それにはもう少し経験が必要なのでしょう。
今年は去年以上に自分のスキルを磨きたいと思います。
こんな記事で今年の抱負を語るつもりはありませんでしたが、まとめに書くことが余りにも無さ過ぎて迷走してしまいました。
BackSpaceキーを押せば後戻りできますが敢えてこのままでいきたいと思います。
みなさま!明けましておめでとうございます。
今年もよろしくお願いします。