処理速度の高速化その1

2009/02/24 | 高速化

最近は処理速度の高速化をいろいろ考えることがある。

高速化といってもいろいろある。実際に速度自体が変わっていなくても、気分的に早く動いているように感じさせる場合もあれば、実際に処理速度を改善させる場合もある。前者でいえば、例えばクリックして次の画面が出るまでの間、「Now Loading」を表示させたりする。処理速度自体はまったく変化がないが(むしろ遅いか)、何らかの視覚的なアクションによってストレスを軽減させるのがいい例だ。最近はAJAXを使って、非同期通信かつインタラクティブな構成を検討することも多い。

後者は実際に処理速度向上を図る方法。わかりやすい例で言えば、プログラム内に無駄な処理があれば、それを削除することによって少し速くなるはずだ。あとSQL文の実行に時間がかかる場合がある。そんなときはSQL文を見直すだけで速度向上につながることがある。

今日は後者のお話。最近Web APIを使ったウェブアプリを各機会が多い。一つのPHPプログラムにアクセスした際に、複数のAPIをコールして処理することもあるわけだが、普通に記述するならfile_get_contentsを数回書けばいい(実際そうは書かないけれど)。でもこれだと、当たり前だけれどfile_get_contentsの回数分だけ処理に時間がかかる。でも、一度に複数のAPIコールを実現することができる、といわれるとちょっと興味をそそられる。PHP5からはそんな機能が実装されているらしいのだ。記事元はこちら

PHP5にはcURL関数群に新しくcurl_multi_を接頭辞に持つ関数がいくつか追加されている。まさしく「curlをmultiに実現する」ための関数群だ。PHPのマニュアルから引用すると、

// cURL リソースを作成します
$ch1 curl_init();
$ch2 curl_init();

// URL およびその他適切なオプションを設定します。
curl_setopt($ch1CURLOPT_URL“http://www.example.com/”);
curl_setopt($ch1CURLOPT_HEADER0);
curl_setopt($ch2CURLOPT_URL“http://www.php.net/”);
curl_setopt($ch2CURLOPT_HEADER0);

// マルチ cURL ハンドルを作成します
$mh curl_multi_init();

// ふたつのハンドルを追加します
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);

$running=null;
// ハンドルを実行します
do {
    
curl_multi_exec($mh,$running);
} while (
$running 0);

// ハンドルを閉じます
curl_multi_remove_handle($mh$ch1);
curl_multi_remove_handle($mh$ch2);
curl_multi_close($mh);

すごーい。こんなことが本当にできちゃうんだなぁ、驚いてしまった。こういう情報ってもっとどんどん世の中に出回ってくればいいのに・・・。最近PHPのMLもろくに読んでいないので、情報を見つけられないでいるだけかもしれない。やっぱり業務に追われるってのはよくない。マニュアルも定期的に目を通さないと、だな。

simpleXMLがすごく簡単

2009/02/22 | XML

PHP4の時代はXMLを扱うのが簡単ではなかった。必ず何かツールを使わないといけなかった。そんなPHP4も去年ついに開発を終了したので、ようやく重い腰を上げてPHP5に移行。超使いやすくなったといわれているPHP5のXML関連関数を今頃使い始めたのだが、これがまた簡単。

simplexml_load_fileとかするだけで、XMLツリーをオブジェクトに格納してくれる。

しかもオブジェクト内を書き換えてXMLを吐き出すこともできる。もっと早くに乗り換えていればよかったよ、PHP5。ただ唯一XMLのタグ名にコロン「:」があるとうまく扱えないことが気になった。最初、楽天ウェブサービスAPIからの戻り値を関数に放り込んでvar_dumpしたけど、オブジェクト内にぜんぜんメンバ変数が登録されていなくて、「手ごわい」と思ったんだけど。いろいろ実験して、ウェブ調べたらコロンが原因だってわかった。前向きな解決策はないようだけど、処理前に単にコロンを他の文字列に置き換えればOK。スマートではないけれど、これが確実っぽい。

時間に余裕ができたら、これを使って各種APIで遊んでみたい。


					

呼び出し元を取得

2009/01/26 | PHPの基本

最近は基本的にべたでプログラムを書くことはなくて、フレームワークを使ってクラスやら関数やらを書くことがほとんど。そのクラスとか関数から、さらにクラスや関数を呼び出すわけだが、呼び出された側で、呼び出し元の情報にアクセスする際、今までは引数で渡す処理にしていた。もちろんこれはこれで「必要以上の変数にはアクセスさせない」というフールプルーフ的なメリットが大きいが、その都度引数を渡す必要がある。いろいろ調べたら、PHPには呼び出し元のクラス(オブジェクト)にアクセスできる仕組みが用意されていた。

debug_backtrace関数だ。

読んで字のごとく、バックトレースしてくれるわけだ。呼び出し元クラス名やオブジェクト名、関数名やファイル名など、いろいろな情報にアクセスできる。しかし、まぁdebugとついているくらいだから、本来はデバッグ用で使用するためのものだろう。使うのには注意が必要かな。

関数emptyの引数

2009/01/16 | PHPの基本

値が空かどうかをチェックするのにempty関数をよく使っている。でも、あるとき、以下のようなエラーが出た。

Fatal error: Can’t use method return value in write context in /path/to/script

ぱっと見ただけでは意味がわからない・・・しばらく考える・・・「メソッドの戻り値は使えない」・・・。

プログラムの中では以下のように記述していた。

empty($hoge->fuga())

しかし、以下のように記述するとエラーにならない。

$value=$hoge->fuga();
empty($value); 

あ、ひょっとして・・・。

マニュアルを見たら書いてあった。「emptyの引数は関数であってはならない」そうだ。これは知らなかった。というよりも、よく今までこういう記述をしていなかったものだと思った。

重複行

2009/01/09 | MySQL

開発を始めて間もない頃に作ったサイトをリニューアル中。まだまだ駆け出しの頃だったので、プログラムもデータベースの構造もひどいものだ(だからサイトが重い)。そんなサイトでも月間数万ページビューあるのでリニューアルすることにしたのだ。

プログラムは全て新しく書き直すので、以前のプログラムはまったく気にならないけど、データベースの構造が大変。古いのをそのまま持ってくるのも重そうだし。新しく設計しなおしてデータをコンバートする過程で問題が起きた。テーブルに主キーを設定していなかったので、データの重複が起こっていた。そもそもプログラム側でも特に制御していなかったし、重複が起こっても当時のプログラムでは問題にならなかったのだが、今回はしっかりと主キーを設定したが故に、一筋縄では移行できなくなってしまったわけだ。

データの重複を削除する方法をウェブで探したら、ちゃんと見つかった。

CREATE TABLE temp as SELECT * FROM original GROUP BY column1, column2
DROP TABLE original
ALTER TABLE temp RENAME TO original

最初に、元のテーブルから全ての列をグループ化して、別名でテーブルを作る(この時点で重複行は一つにまとめられている)。次に元のテーブルを消して、最後にテーブル名を変更してそれで完了。ちょっとキツネにつままれたような感じだけどすごく簡単にできた。ほんとに大丈夫なのかどうかわからないんだけど、とりあえずこれでよしとした。


守谷市(まちの情報ポータル) 無料アンケートレンタルjpForm.net