Feb - 20th

Christmas in February

Posted at 1:27 pm | Filed Under Music

VersionTrackerのフィードを見たら、クリスマスゲームが並んでいて奇妙だった。

Christmas In February
なんとなく連想したのが


“NEW YORK” (ルー・リード)

Read More>

Feb - 19th

Google独自ドメイン向けサービスの活用

Posted at 8:52 pm | Filed Under Google

前の記事Googleアプリ独自ドメイン向けサービスを使うようになったと書いたが、うちのISPが外部の25番ポートへの接続を禁止しているので、サーバから外にメールが出ない状態だった。もったいないのでPostfixの設定を変更。ここにとても参考になるページがある。設定が完了してメールも送信できたのだが、ログをみると、ちょっと気持ちが悪い。

Feb 19 18:51:01 localhost postfix/qmgr[28890]: 4E59018F57: from=<apache@localhost.localdomain>, size=1606, nrcpt=1 (queue active)
Feb 19 18:51:01 localhost postfix/smtpd[28943]: disconnect from localhost.localdomain[127.0.0.1]
Feb 19 18:51:02 localhost postfix/smtp[28947]: certificate verification failed for gmail-smtp.l.google.com: num=20:unable to get local issuer certificate
Feb 19 18:51:02 localhost postfix/smtp[28947]: certificate verification failed for gmail-smtp.l.google.com: num=27:certificate not trusted
Feb 19 18:51:02 localhost postfix/smtp[28947]: certificate verification failed for gmail-smtp.l.google.com: num=21:unable to verify the first certificate
Feb 19 18:51:02 localhost postfix/smtp[28947]: Server certificate could not be verified
Feb 19 18:51:04 localhost postfix/smtp[28947]: 4E59018F57: to=<admin@selfkleptomaniac.org>, relay=gmail-smtp.l.google.com[64.233.167.111], delay=3, status=sent (250 2.0.0 OK 1171878664 p57sm8208347pyb)
Feb 19 18:51:04 localhost postfix/qmgr[28890]: 4E59018F57: removed

ログが長いのも嫌なので、certificate verification failedの行を消したいのだが、方法が思いつかない。そのうち考えよう。←またもや先送り

Read More>

Feb - 19th

Redditの謎

Posted at 8:02 pm | Filed Under Uncategorized

ふとRedditのRSSを見ると

Reddit

こんなのがあった。クリックすると

Reddit2
localhostに繋がろうとする。

気の利いた攻撃、というわけでもないようだ。

Read More>

Feb - 19th

Wikipedia創始者来日

Posted at 9:31 am | Filed Under Wikipedia

Wikimedia財団のジンボ・ウェールズが来日。質問を受け付けている。

言い訳がましい歴史修正主義者みたいな連中がうようよしているWikipedia日本語版について質問してみよう。

Read More>

Feb - 18th

Subversionの準備

Posted at 5:28 pm | Filed Under Subversion

結局、理想的なウェブアプリの開発環境はこんな感じに。

Subversionのレポジトリのディレクトリ構成は、伝統的にこんな風になっている:

$ mkdir OurGreatApp
$ mkdir OurGreatApp/trunk
$ mkdir OurGreatApp/branch
$ mkdir OurGreatApp/tags

名前の通り、trunk(主幹)が現在まさに開発中のセット一式。開発が完了したら、svn copyでtagsディレクトリ以下に収まる。こうするとtagsにはリリース番号が割り当てられたセット一式が入る。OurGreatApp/tags/1.0/とか、OurGreatApp/tags/1.1/とか。branchは適時必要に応じて作られる。カスタマイズ案件があったときや、次期メジャーバージョンの開発など。

hooks用のスクリプトで実装するのは

pre-commit

  • コメントの書式チェック
  • コミットされたスクリプトの構文チェック
  • コーディング規約に則ったチェック

post-commit

  • レポジトリのパスに応じてバグトラッカーに変更内容を投稿
  • テスト管理プログラムのDBに変更されたスクリプトの内容を投稿
  • リリース用ファイルリストに必要に応じて追記

PHPで記述するとこんな感じ。

#!/bin/env php
<?php

$rev = $argv[2]; //リビジョン
$path = $argv[1]; //コミットされたファイルのパス

$log = `svnlook log $rev $path`; //コメント(UTF-8)
$author = `svnlook author $rev $path`; //コミットした人
$date = `svnlook date $rev $path`; //日時

//do something

?>

post-commitのところは、もっとシンプルにBTSに統合されるといいのだろうけれども、そこまでは手が回っていない。

これで、変更があった場合には記録が全部BTSに入るので、BTSのステータスが完了になるまでリリース出来なくなり、テストが漏れることを防いでくれる。

BTSには影舞を使っている。メンテナンスを考えると、PHPで書かれたフリーのBTSで優秀なのがあればいいのだが、なかなか見当たらない。

Read More>

Feb - 17th

WordPressのパフォーマンス向上

Posted at 11:24 pm | Filed Under PHP, WordPress

Digg経由で「4+1 Ways To Speed Up WordPress With Caching」という記事を読んだので、さっそく実行してみた。

MySQLの設定はデフォルトのままだったので、/etc/my.confに以下の行を追加。

[cache]
query_cache_type=1
query_cache_size=20M
query_cache_wlock_invalidate=1

それから、eAcceleratorとAPCも迷ったが、どうせなら使ったことがないのにしようとXCacheをインストール。家に置いてあるマシンをサーバにしているので、うるさくないように少しでもロードアベレージを下げるために。

PHP-5.2.1であれば現在の安定板である1.2.0で問題ないようなので、

./configure --enable-xcache --enable-xcache-coverager
make
make install

でビルドとインストールまで完了したら、デフォルトの設定ファイル(xcache.ini)を編集。PHPのビルド時に何も指定しなかったので、php.iniの末尾に編集後のファイルをリダイレクトで追記したが、問題が起きたときの切り分け用にこれはなんとかした方がいいかもしれない。共有メモリではなくmmapを使う方がいいよ、とのことなので、質問された項目も全部yesに。

こちらのサイトで紹介されている通り、確かにzend_extensionでは動かないようなので普通のextensionと同様にextension = xcache.soにして、xcache.sizeも真似て4Mにした他は、ほとんどの値は推奨値のまま。WordPressを使う際の速度向上と負荷軽減にしか使わないのでカバレッジ機能はOffに。

[xcache-common]
extension = xcache.so

[xcache.admin]
xcache.admin.user = "mOo"
xcache.admin.pass = "ここはmd5したパスワード"

[xcache]
xcache.shm_scheme =        "mmap"

xcache.size  =                4M
xcache.count =                 0
xcache.slots =                8K
xcache.ttl   =                 0
xcache.gc_interval =           300

xcache.var_size  =            0M
xcache.var_count =             1
xcache.var_slots =            8K

xcache.var_ttl   =             0
xcache.var_maxttl   =          0
xcache.var_gc_interval =     300

xcache.test =                Off
xcache.readonly_protection = Off

xcache.mmap_path =    "/dev/zero"

xcache.coredump_directory =   ""

xcache.cacher =               On
xcache.stat   =               On
xcache.optimizer =           Off

[xcache.coverager]
xcache.coverager =          Off

xcache.coveragedump_directory = ""

ここでabでちょっと負荷テスト。今は家族で実家に帰っているので家のマシンが多少うるさかろうと誰も文句はいわない。Apacheのチューニングは全然していない(神よ…)ので、サイトのアクセス状況に合わせて(つまりあんまり誰も見てないので)、同時接続が10で接続数が10という、実に手加減気味の負荷テストになった。

ab -n 10 -c 10 http://selfkleptomaniac.org/index.php

結果、こんな感じ。

対策前:

Concurrency Level:      10
Time taken for tests:   7.227 seconds
Complete requests:      10
Failed requests:        0
Broken pipe errors:     0
Total transferred:      395161 bytes
HTML transferred:       391381 bytes
Requests per second:    1.38 [#/sec] (mean)
Time per request:       7227.00 [ms] (mean)
Time per request:       722.70 [ms] (mean, across all concurrent requests)
Transfer rate:          54.68 [Kbytes/sec] received

対策後:

Concurrency Level:      10
Time taken for tests:   4.351 seconds
Complete requests:      10
Failed requests:        0
Broken pipe errors:     0
Total transferred:      378059 bytes
HTML transferred:       374279 bytes
Requests per second:    2.30 [#/sec] (mean)
Time per request:       4351.00 [ms] (mean)
Time per request:       435.10 [ms] (mean, across all concurrent requests)
Transfer rate:          86.89 [Kbytes/sec] received

秒間2.3アクセスかよ!と叫びたいところだが、対策前の1.3と比べたら全然ましだ。直後のロードアベレージは対策前が1.5程度で、対策後が0.8くらい。まあいっか。

Read More>

Feb - 17th

ユーザからの入力は全て疑え

Posted at 8:07 pm | Filed Under PHP

ウェブアプリ開発者としては、当然これくらいの意識がないといけない。

taintedモードのあるPerlやRubyのユーザなら理解しているはずだ。

register_globalsをOnにしているPHPの開発者は、この抗体の早期実装を要望しよう。

Read More>

Feb - 16th

PHPのパフォーマンス改善(3)

Posted at 1:25 pm | Filed Under PHP

Zend / PHP Conference & Expo 2006でのIlia Alshanetsky氏プレゼン資料(PDF)

やや旧聞に属するが、一次保存場所に漂っているファイルを見つけたのでまとめてみた。Apacheやサーバのチューニングも含まれていてなかなか面白かったが、ここではPHPのプログラマがスクリプトを記述する際に注意する点を取り上げる。

(6)その他いろいろ。

■エラーを出力しないオペレータ「@」はコストがかかる

まあ、その通り。

■配列のキーの指定の仕方

$array[foo] = 1;
$array['foo'] = 1;

この2行を比較すると、シングルクォートで明示的に文字列とする方が700%速い。

■文字列比較の比較

最速:

if(!strncmp(PHP_OS, 'WIN', 3)){
if(!strncasecmp(PHP_OS, 'WIN', 3)){

ちょっとダメ

if(substr(PHP_OS, 0, 3) == 'WIN'){
if(strtolower(substr(PHP_OS, 0, 3)) == 'win'){

ぜんぜんダメ

if(preg_match('!^WIN!', PHP_OS)){
if(preg_match('!^WIN!i', PHP_OS)){

最速パターンだと、大文字小文字の区別をしてもしなくてもパフォーマンスに影響がなく、1.5倍くら速い。

そもそもPHP5からはsubstr_cmpare関数があるので、substrを比較で使うことはない。

■無意味なエラー出力をなくす

エラー出力をすると

  • 複雑なエラー出力を生成する
  • 標準出力や標準エラーに出力する
  • ファイルやsyslogに書き出すこともある
  • 5.2以前のリリースではまれにメモリリークする

ため、無闇にエラーを出力しない方がいい。

■forループの評価式の中で関数を使わない

for($i = 0; $i <= strlen($str); $i++){
    // do something
}

これを

$length = strlen($str);
for($i = 0; $i <= $length; $i++){
    // do something
}

これにすることで2〜3倍の速度改善が。

■フルパスの記述はパフォーマンスにやさしい

include_pathを検索するよりはいいよ、ということ。

■多次元配列の処理に参照渡しを使う

$array['foo']['bar'] = array();
for($i = 0; $i <= 5; $i++){
    $array['foo']['bar'][$i] = $i;
}

これよりも

$ref =& $array['foo']['bar'];
for($i = 0; $i <= 5; $i++){
    $ref[$i] = $i;
}

こっちの方がシンプルでわかりやすく、しかも速い。

■最適化にまつわる神話

  1. コメントをなくすと速くなる
  2. ダブルクォート(”)はシングルクォート(’)より速い
  3. 参照渡しの方がコードが速くなる
  4. オブジェクトを使う方が速くなる
  5. タナリ($a = 1 ? $b = $a : $b = 0;)はif(){}else{より速い

これらは全部嘘です。

Read More>

Feb - 16th

PHPのパフォーマンス改善(2)

Posted at 1:19 pm | Filed Under PHP

Zend / PHP Conference & Expo 2006でのIlia Alshanetsky氏プレゼン資料(PDF)

やや旧聞に属するが、一次保存場所に漂っているファイルを見つけたのでまとめてみた。Apacheやサーバのチューニングも含まれていてなかなか面白かったが、ここではPHPのプログラマがスクリプトを記述する際に注意する点を取り上げる。

(4)PCREの正しい使い方

PHPでPCREを利用した正規表現で、マッチした文字列をキャプチャしない場合、例えばpreg_replaceなどを使う場合は、明示的にキャプチャしないことを宣言するとパフォーマンス改善になる。キャプチャした文字列を保持する分のメモリを確保しないで済むからだ。

$str = preg_replace("/(\\n|\\r|\\t|\\r\n|\\s)/", ' ', $orig_str);

$str = preg_replace("/(?:\\n|\\r|\\t|\\r\\n|\\s)/", ' ', $orig_str);
//?:を追加

これで15%ほどの速度改善が見込まれる。

(5)正規表現の使い方を考える

可能な限り正規表現を使わない処理を考えた方がいい。メモリの消費でいうと、

preg_match > strstr > strpos

になるが、strposは0を返すことがあるので、

if(strpos($str)){
    //do something
}

というコードは期待通りに動かないことがある。==ではなく、===を使って返り値の型まで面倒を見る必要があるからだ。

if(strpos($str) !== FALSE){
    // do something
}

こうするか、PHP5ならもっと素直に

if(strpbrk($str)){
    // do something
}

にした方が確実。

Read More>

Feb - 16th

PHPのパフォーマンス改善(1)

Posted at 12:21 pm | Filed Under PHP

Zend / PHP Conference & Expo 2006でのIlia Alshanetsky氏プレゼン資料(PDF)

やや旧聞に属するが、一次保存場所に漂っているファイルを見つけたのでまとめてみた。Apacheやサーバのチューニングも含まれていてなかなか面白かったが、ここではPHPのプログラマがスクリプトを記述する際に注意する点を取り上げる。

(0)クラスメソッドをスタティックに宣言する

class bench{
    public function a(){
        return 1;
    }
    public static function b(){
        return 1;
    }
}

これを100,000回まわすとstaticの方が4倍くらい速い。

(1)マジックメソッドは使わない

__get()や__set()、__autoload()、__call()などの利用はパフォーマンス的にあまりよろしくない。

(2)require_onceはやっぱり呼び出しすぎる

require_onceで呼び出されるファイルは、複数回呼ばれても問題がないだけで、呼び出し自体は複数回実行されている。

どうしても使わなければいけない場合はフルパスを記述するとよい。

PHP5.2以上では、呼び出し回数も1回だけになった。

(3)無意味な関数コールをなくす

わざわざ関数を呼ばなくても、定数が用意されているものはそちらを使おう。

php_version => PHP_VERSION

php_uname(’s’) => PHP_OS

php_sapi_name() => PHP_SAPI

だいたい50倍くらい速い。

ちなみにWindows上で動いているかを確認する場合は、「DIRECTORY_SEPARATOR == ‘\\’」で判定する方がいい。

それから、現在時刻をUNIX時間で返してほしい場合はこれ。

time() => $_SERVER['REQUEST_TIME']

つづく

Read More>

« go backkeep looking »