PDT Project

pdt.jpg

The PDT project is working towards providing a PHP Development Tools framework for the Eclipse platform. This project will encompass all development components necessary to develop PHP and will facilitate extensibility. It will leverage the existing Web Tools Project in providing developers with PHP capabilities.

EclipseのPluginでPDTってあるんですね。名前からしてJDT並の機能を期待してしまいます!

OPML2Twitterをつくってみた – よくきたblog

まずplnet.最近で言うとaboutmeっぽいやつですけどずいぶん前からあります. ようするに自分のいろんなCGM系コンテンツがある人がそれらのRSSなどのフィードを用いて1箇所にまとめちゃいなYO!!ってサービスです.

(中略)

- OPMLを取得する - simplexmlで解析し,フィードURL群を束ねる - XML_Feed_Parserでエントリ群の題名,URL,日付を取得する - エントリをTwitterに送る,とりあえず複数エントリある場合の送信は2分間隔でおこなう.

よくきたblogで上鍵さんがPlnetを利用して最新エントリをTwitterに送るスクリプトを公開してくださってます。

OPMLのアイコンがかわいいという理由だけでOPML出力してたんですが(言い過ぎですが)初めて使われた気がして感動しました。それと同時にバグも見付かって上鍵さんには直でPlnetのTracにわざわざTicketを入れて貰いました。

なんでRSSじゃなくてOPMLなのかというとエントリのURLが元の記事じゃなくてPlnetのパーマリンクになるからなんですな。RSSにそれっぽい語彙があったらそのURLも忍ばせたいもんです。

それとさり気なくPHP5を使ってるのがショック。PlnetはPHP4なのでUbuntuでの開発が面倒になりつつあります。(家のDebianで開発してる)simplexmlとかXML_Feed_Parserとか便利そうですね・・・。

Martin Albisetti » Blog Archive » PHP4 not available in Feisty

PHP4 is not in Feisty Fawn’s repositories at all and has been completely replaces by PHP5.

Ubuntu 7.04で遂にPHP4が消えたーーーっっっ!!

まいったなこりゃ。

はてなブックマーク – ウノウラボ Unoh Labs: MySQL5からのインデックス結合で1テーブル複数インデックスを使う

kubi

うわぁ、ショックだし理由が気になるわあ。追記:

$php→rails (rails に憧れる phper のブログ) – 複合インデックスと複数インデックス

でも、上の構造で、name, age を元に抽出するつもりだとすると、

自分の感覚では複合インデックス付ける。

こちらを見てて気づいたんですが、「あの例なら複合インデックスを使う方が良い、もしくは複合インデックスの存在を知らないのか?うちらならクビ」ってことなのかな?

plnet.jpのサーバ移行が完了しましたー。

以前はレンタルサーバーで借りていたんですが、アクトインディ株式会社さんが社内サーバー設置をすることを機に社内の片隅にPlnetのサーバーも置かせてもらえることになりました。

ハードも好きに選んでということだったのでキャンペーン中につき半額で24,800円というお買い得なHP ProLiant ML110 G4にしました。

社内にお邪魔して、リリースされたばかりのDebian etchを速攻でインスコして外から接続できる状態にしてきました。その後、家からなんだかんだ設定して先日DNSの移行も完了したとこです。

一時期はやばかったCPU負荷もアプリケーションのチューニングでかなり良い状態。24800円のサーバ1台でどのくらいいけるのか、今後も全ての情報を晒しつつ頑張ってみようと思います。

大失敗という結果情報を晒すことになるかもしれませんが、どちらにしろ個人でWebサービスをやろうと思ってる方の参考になれば幸いです。

create_functionが気になったのでもうちょっと実験。

$ cat lambda.php
<?php
$lambda = create_function('', 'echo "foo\n";');
var_dump($lambda);
var_dump('lambda_1');
call_user_func($lambda);
call_user_func('lambda_1');
$ php lambda.php
string(9) "lambda_1" 
string(8) "lambda_1" 
foo

Warning: call_user_func(lambda_1): First argument is expected to be a valid callback in /home/komagata/works/example/php/lambda.php on line 6

怪しい。その1byteは何なんだと。

create_functionは関数名に使えない名前で関数定義してるだけってのはホントっぽいっすね。

PHPでクロージャ

$ cat closure.php
<?php
function get_adder() {
    static $count = 0;
    return create_function('', 'return ++$count;');
}

$adder = get_adder();
echo call_user_func($adder);
echo call_user_func($adder);
echo call_user_func($adder);
$ php closure.php
111

・・・に、失敗!

Plnetのコード整理とバグ潰し。

ダブっちゃいけないURLをtext型の255byteのINDEXで管理してたので長いやつはダブる状態になってた。しかもINDEX長いので速度も糞。

urlのmd5を作ってそちらを見るのが常識だということを知りました・・・。これならINDEXも32byteで雲泥の差。

t-kawaduが変換して重複も消してくれるバッチを書いてくれたのでスッキリ。

コードの方はあまりにもDRYじゃない部分を2つ変更。もはやオリジナルMojaviのコードにこだわってもしょうがないので本体に手を入れました。ひとつはViewが無くてもOKにしたのと、Railsのlayoutみたいにして大枠をひとつにまとめました。

<?php
class FooAction extends Action {
    var $layout = 'Public'
    (略)
}
?>

Public.html:

ヘッダー
{$partial}
フッター

実装はどうでもいいとして、重複コードを減らすとその分細部に時間をかけられて嬉しい。テンプレの共通化が進むと、適当なCSSとかHTMLだったのを、ちゃんと書こうかな!って気になります。

パフォーマンス改善を正しくやりたいとか言っておいて、Plnetがあまりに重く、使い物にならなくなっていたので焦ってまた勘で対応していまいました・・・。

lighter_graf.png

しかも効果がありまくりで・・・。

mysqlがslow-query出しまくりなのでページキャッシュを入れまくりました。Mojavi2なんでこういうSmartyプラグインを作った感じです。

<?php
if (!defined(CACHE_LITE_DIR)) define('CACHE_LITE_DIR', '/tmp/');
if (!defined(CACHE_LITE_AUTO_CLEANING)) define('CACHE_LITE_AUTO_CLEANING', 128);

function smarty_function_mojavi_action($params, &$smarty)
{
    $id = $params['module'].'_'.$params['action'];

    if (isset($params['lifetime'])) {
        include_once 'Cache/Lite.php';
        $cache =& new Cache_Lite(array(
            'cacheDir' => CACHE_LITE_DIR,
            'lifeTime' => $params['lifetime'],
            'automaticCleaningFactor' => CACHE_LITE_AUTO_CLEANING,
            'automaticSerialization' => true
        ));

        $cache_id = $id.'_'.
            (isset($params['cache_id']) ? $params['cache_id'] : '');
        if ($data = $cache->get($cache_id)) {
            return $data;
        }
    }

    $controller =& Controller::getInstance();
    $actionChain =& new ActionChain();
    $actionChain->register($id, $params['module'], $params['action']);
    $actionChain->execute($controller, $controller->request, $controller->user);
    $data = $actionChain->fetchResult($id);
    if (isset($params['lifetime'])) $cache->save($data, $cache_id);
    return $data;
}
?>

なんでDBが重いのにmysql serverがCPU食わないんだろう。clientの方ばっかり食ってることになってる。

とりあえずcocoitiさんにスケーラブルWebサイトを借りたので読んで悔い改めたいと思います。

スケーラブルWebサイト
  • スケーラブルWebサイト
  • オライリー・ジャパン(2006-12-26)
  • オライリー・ジャパン
  • (著)Cal Henderson
  • (翻訳)武舎 広幸
  • (翻訳)福地 太郎
  • (翻訳)武舎 るみ
  • 定価:¥ 3,570
  • 新品価格:¥ 3,570
  • 中古価格:¥ 2,913
  • ASIN:4873113113

そもそも“正しいパフォーマンス改善”とは何なのか。

要するに勘で良いとされることを手当たり次第やるんじゃなくて、原因に基づいて対策をしたい。

前回のとこのzionicさんのコメントとエントリが参考になりました。

zionicの日記

wa(I/O Wait)は0なので、とりあえず無視する。us(User Space)がやたら高い。基本的にはCPU食いすぎ、と考えてよいと思われる。

色々対策したい部分はあるけれど、兎に角CPUを食わないようにしなきゃいけない!

エントリにあるようにeAcceleratorが効きそう。構文解析しない分CPUの負荷は減るはず。

手元の環境で試してみました。

$ sudo apt-get install php4-dev
$ wget 'http://bart.eaccelerator.net/source/0.9.5/eaccelerator-0.9.5.tar.bz2'
$ tar jxf eaccelerator-0.9.5.tar.bz2
$ cd eaccelerator-0.9.5
$ phpize
Configuring for:
PHP Api Version:         20020918
Zend Module Api No:      20020429
Zend Extension Api No:   20050606
$ ./configure --enable-eaccelerator=shared --with-php-config=/usr/bin/php-config
$ make
$ sudo make install
Installing shared extensions:    /usr/lib/php4/20020429/ 
$ sudo vi /etc/php4/apache2/php.ini
[eaccelerator]
zend_extension="/usr/lib/php4/20020429/eaccelerator.so" 
eaccelerator.shm_size = "32" 
eaccelerator.enable = "1" 
$ mkdir /tmp/eaccelerator
$ chmod 0777 /tmp/eaccelerator

apache2-utilsのApache BenchでeAccelerator有り/無しで測ってみた。

eAccelerator無し:

$ sudo ab -c 5 -n 100 http://plnet/komagata/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking plnet (be patient).....done

Server Software:        Apache/2.2.3
Server Hostname:        plnet
Server Port:            80

Document Path:          /komagata/
Document Length:        21964 bytes

Concurrency Level:      5
Time taken for tests:   35.508370 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      2235600 bytes
HTML transferred:       2196400 bytes
Requests per second:    2.82 [#/sec] (mean)
Time per request:       1775.418 [ms] (mean)
Time per request:       355.084 [ms] (mean, across all concurrent requests)
Transfer rate:          61.48 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   79 281.9      0    1781
Processing:   318 1669 2986.9    680   20417
Waiting:        0  750 1461.3    366    8742
Total:        318 1748 3033.9    701   20417

Percentage of the requests served within a certain time (ms)
  50%    701
  66%    899
  75%   1125
  80%   1651
  90%   5874
  95%   8144
  98%  12675
  99%  20417
 100%  20417 (longest request)

eAccelerator有り:

$ sudo ab -c 5 -n 100 http://plnet/komagata/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking plnet (be patient).....done

Server Software:        Apache/2.2.3
Server Hostname:        plnet
Server Port:            80

Document Path:          /komagata/
Document Length:        21964 bytes

Concurrency Level:      5
Time taken for tests:   18.760849 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      2236800 bytes
HTML transferred:       2196400 bytes
Requests per second:    5.33 [#/sec] (mean)
Time per request:       938.042 [ms] (mean)
Time per request:       187.608 [ms] (mean, across all concurrent requests)
Transfer rate:          116.41 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       1
Processing:   520  928 596.4    859    6521
Waiting:      241  637 590.1    553    6212
Total:        520  928 596.5    859    6522

Percentage of the requests served within a certain time (ms)
  50%    859
  66%    925
  75%    978
  80%    996
  90%   1122
  95%   1227
  98%   1832
  99%   6522
 100%   6522 (longest request)

Requests per secondが2.82 [#/sec] → 5.33 [#/sec]で倍近くに増えてる。これは良さそうだ。

昨日の1時頃、Plnet.jpに入れてみました。

graph_image.png

あんまり変ってないな・・・。

あと気になる点はmysqlのslow-queryがバリバリ出てるとこ。しかしtopでmysqlは全然あがってこないのでCPUに関係無いと思う。それともmysqlが遅いとそれに関係したapacheがCPUを使うってことがあるのかな?

いちおうtop:

top - 11:51:08 up 190 days,  3:46,  1 user,  load average: 9.55, 7.71, 5.17
Tasks:  67 total,   2 running,  65 sleeping,   0 stopped,   0 zombie
Cpu(s): 85.1% us, 14.9% sy,  0.0% ni,  0.0% id,  0.0% wa,  0.0% hi,  0.0% si
Mem:    971496k total,   757916k used,   213580k free,    52888k buffers
Swap:  2000084k total,    51384k used,  1948700k free,   536868k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
24948 www-data  15   0 53868  15m  47m S  1.0  1.7   0:00.49 apache2
24883 www-data  15   0 56740  17m  47m S  0.6  1.9   0:01.81 apache2
24815 www-data  16   0 54360  18m  47m S  0.3  1.9   0:01.22 apache2
    1 root      16   0  1504  420 1352 S  0.0  0.0   0:13.74 init
    2 root      34  19     0    0    0 S  0.0  0.0   0:00.14 ksoftirqd/0
    3 root       5 -10     0    0    0 S  0.0  0.0   0:00.00 events/0
    4 root       5 -10     0    0    0 S  0.0  0.0   0:00.00 khelper
   15 root       5 -10     0    0    0 S  0.0  0.0   3:40.75 kblockd/0
   51 root       5 -10     0    0    0 S  0.0  0.0   0:00.00 aio/0
   50 root      15   0     0    0    0 S  0.0  0.0   6:45.89 kswapd0
  187 root      25   0     0    0    0 S  0.0  0.0   0:00.00 kseriod
  293 root      15   0     0    0    0 S  0.0  0.0  17:48.87 kjournald
  554 root      15   0     0    0    0 S  0.0  0.0   0:00.03 kjournald
  555 root      15   0     0    0    0 S  0.0  0.0   9:14.08 kjournald
  556 root      15   0     0    0    0 S  0.0  0.0   3:44.86 kjournald
  557 root      15   0     0    0    0 S  0.0  0.0   5:29.24 kjournald
  711 root       6 -10     0    0    0 S  0.0  0.0   0:00.00 ata/0
  712 root      23   0     0    0    0 S  0.0  0.0   0:00.00 scsi_eh_0
  713 root      23   0     0    0    0 S  0.0  0.0   0:00.00 scsi_eh_1
  761 root      15   0     0    0    0 S  0.0  0.0   0:00.00 khubd
 1819 daemon    15   0  1612    4 1440 S  0.0  0.0   0:00.00 portmap
 2182 root      16   0  2260  432 2092 S  0.0  0.0   1:13.34 syslogd
 2185 root      17   0  2444    4 1344 S  0.0  0.0   0:00.07 klogd
 2193 root      16   0  2628  232 2192 S  0.0  0.0   0:00.08 rpc.dracd
 2223 Debian-e  16   0  5128  312 4752 S  0.0  0.0   0:00.85 exim4
 2229 root      15   0  2240    4 2084 S  0.0  0.0   0:00.00 inetd
 2246 daemon    16   0  1684   48 1520 S  0.0  0.0   0:00.00 atd
 2249 root      16   0  1764  228 1576 S  0.0  0.0   0:01.59 cron
 2260 root      17   0  1500    4 1336 S  0.0  0.0   0:00.00 getty
 2261 root      17   0  1500    4 1336 S  0.0  0.0   0:00.00 getty
 2262 root      16   0  1500    4 1336 S  0.0  0.0   0:00.00 getty
 2263 root      16   0  1500    4 1336 S  0.0  0.0   0:00.00 getty
 2264 root      16   0  1500    4 1336 S  0.0  0.0   0:00.00 getty
 2265 root      16   0  1500    4 1336 S  0.0  0.0   0:00.00 getty
21946 root      16   0 11728  912 7792 S  0.0  0.1   0:02.78 miniserv.pl
 1952 root      16   0 11872  216 7792 S  0.0  0.0   0:00.00 miniserv.pl
17964 root      16   0  3468  336 3092 S  0.0  0.0   0:43.35 sshd

関連: