PHPで動作させたスクリプトが徐々に重くなっていった

PHPで動作させたスクリプトが徐々に重くなっていった。

本番環境から切り出した5000件あまりのデータを処理してたら途中からどんどん重くなっていってた。コレはまずいなーとか思ってメモリ使用量を調べてみると増えていってる。

8GBを積んだFreeBSDなマシンだったんだけど、memory_get_usage()で調べたところ300MBを超えるあたりから急激に重くなっていった。

8GBのメモリに対しての300MBであればまだまだ高速に動きそうなもんなんだけど、その辺の追求はPHP&OSに起因する問題っぽいのであきらめる。

ちなみにテストコードを書いてみてもやっぱり300MBあたりで遅くなった。

以下テストコード


<?php

main();

function main(){
$test = new test();
for($i=0; $i<1000000; $i++){
$hoge = array('test'=>'tete', 'hoge'=>$i);
$test->test($hoge);
var_dump($i.':'.(memory_get_usage()/1024/1024));
}
}

class test{
private $hoge = array();
public function test($str){
$this->hoge[] = $str;
}
}


そのときのtopの様子。気づいたらutimeが19になっとるじゃん。いつ再起動したんだっけ。


last pid: 62467;  load averages:  0.45,  0.38,  0.47   up 19+03:19:24  11:35:32
123 processes: 2 running, 119 sleeping, 1 stopped, 1 zombie
CPU: 23.7% user,  0.0% nice,  6.3% system,  0.0% interrupt, 70.0% idle
Mem: 1292M Active, 1310M Inact, 869M Wired, 806M Buf, 4322M Free
Swap: 4096M Total, 4096M Free

PID USERNAME       THR PRI NICE   SIZE    RES STATE   C   TIME   WCPU COMMAND
62447 yousan           1 113    0   664M   514M CPU3    3   0:16 76.95% php

wordpressのsingle.phpとかでquery_postsを自前で実行した後に元のpostを参照したかった

wordpressのsingle.phpとかでquery_postsを自前で実行した後に元のpostを参照したかった。

どういうことかというと、single.phpの中で以下のような順序で上から順にpost(ID=123)にアクセスしてた。

  1. post ID=123のタイトル
  2. post ID=123の内容
  3. 関連記事の表示のため、query_posts(array(‘post__in’)); を実行
  4. while(have_posts()) the_post(); をして関連記事のタイトルを表示
  5. post ID=123のコメントを表示したい!! <– ココ重要

最後のコメントを表示しようとするとうまくいかない。というのもその前段階の関連記事表示でthe_postをしてしまっているのでグローバル変数の$postが関連記事のものになっている。なのでコメントを表示しようとしたときに利用されるpostは関連記事の一番最後のpost、while(have_posts())が回りきった最後のpostとなってしまうのだ。

試しに echo $post->ID; すると確かにIDは123でなく関連記事の最後のpost_IDになっている。

さて困ったぞ、ということでググってたらコレを解決してくれるような関数を発見。

Function Reference/wp reset postdata » WordPress Codex

以前は$post->IDを変数に保存しておいてquery_postをかまして・・・、ってやってたんだけど、このwp_reset_postdataを使えばその手間が省ける・・・、かどうかは微妙かもしれない。結局同じような手立てに。

でも標準で用意されてるってことは今後に期待もしていいってことで利用してみる。

仕組みは単純でその使用方法で示唆されている。使い方はグローバルの$wp_queryを一時待避させておいて必要になったら戻す,というもの。


$original_query = $wp_query;

 query_posts(‘hogehoge’);

$wp_query = $original_query;

 wp_reset_postdata();

the_title(); comment_template();

コレでうまくいくようになった。

PHPで定数をメンバ変数の名前に使いたかった

PHPで定数をメンバ変数の名前に使いたかった。

stdClassでメンバ変数の名前に対して定義済み定数を利用しようとしたら怒られた。


<?php

define('HOGECONST', 'ehehe');
$hoge = new stdClass();
$hoge->hoge = 'value';
//$hoge->constant('HOGECONST') = ‘'value';  // raises an error -- Can't use method return value in write context
//$hoge->$constant(HOGECONST) = ‘'value'; // raises an error -- Can't use method return value in write context
//$hoge->HOGECONST = ‘'value'; // raises an error -- syntax error, unexpected T_CONSTANT_ENCAPSED_STRING
$attr = constant('HOGECONST');
$hoge->$attr = 'value';
var_dump($hoge);

?>


object(stdClass)#1 (2) {
["hoge"]=>
string(5) "value"
["ehehe"]=>
string(5) "value"
}


どうやら一度定数を変数に格納した後、 $hoge->$attr というふうにアクセスしないとダメらしい。