クロージャー

create_functionをつかっちまった。
クソやろーとか言ってごめんなさいごめんなさい。

こんな風に引数渡せるのね。

<?php
class myDoctrineCollection extends Doctrine_Collection
{
    public function sortBy($column, $order = 'asc')
    {
        $sortOrder = (strtolower($order) == 'desc') ? -1 : 1;
        usort($this->data,  function ($a, $b) use ($column, $sortOrder) {
            return strcmp($a->{$column}, $b->{$column}) * $sortOrder;
        });
        return $this;
    }
}

use++

ちなみにこれはsymfony1.4のDoctrineで、Doctrine_Collectionでソートをするための拡張

おっぱいとちくび

先輩の「ゲームはちくびに通じる」という名言にえらく感銘を受け、
ついうっかり女性も一緒の食事の席でちくびがいかにゲームに通じるか語りすぎてしまった。

帰り道、ふと、もうオレは三十路の直前で若くはなくなってきていることに気づき、インターンの子とか22とかの子にこんなに「ちくびちくび」言ってたら、セクハラで訴えられても反論のしようが無いということに気づいてしまった。

「あーやべ」


でも、今日ほど改めてちくびとおっぱいについて考えたことはなく、
「ちくびじゃなくて、おっぱいじゃダメなのか?」ときかれたら、「おっぱいじゃダメなんです!ちくびじゃなきゃダメなんです!」と声高に叫びたくなる気持ちはどこから湧き出てくるものなのか、必死に考えた。


で、答えがわかった。

”ちくびはおっぱいの必要十分条件である”が、”おっぱいはちくびの必要十分条件とはならない”のだ。

不思議である。必要十分条件であるならばその裏もまた真であるはずである。
数学で何度もそう習った。

だがしかし、「ちくびはおっぱいの必要十分条件である」という命題はこの公式を覆してしまうのだ。



わかりやすく説明しよう。

「ちくびのないおっぱい」と「おっぱいのないちくび」を想像して欲しい。


ちくびの無いおっぱいにはなにも興奮しないと思わないか?
が、しかし、たとえおっぱいがなかろうと、そこに凛と聳え立つ気丈なちくびさえがあれば僕達の欲望は満たされる。


そう、つまり僕たちの言う真のおっぱいはちくびなのだ。




ところで、なぜ、こんなにもちくびとおっぱいについて考えたかということを振り返ってみる。


「ゲームはちくびに通じる」とは


僕たちは生まれ出てちくびに出会った瞬間から、ちくびに夢中になりちくびが無いと落ち着かなくなり、ちくびに吸い付きたいとちくびを愛した。


そして、時がたち一度ちくびを離れると、「ちくび?はあ?えろーい」とちくびを敬遠しちくびと向き合うことをしなくなった。


しかし、さらに時がたち、いつの日か僕たちはまたちくびに興奮し、ちくびが大好きになっている。
そして、僕たちがちくびを愛するがゆえに、また新しい乳首を愛する命が生まれてくるのだ。


そう、これは僕たちとゲームとの付き合い方に似ている。

小学校に上がるかあがらないかの時、スーパーマリオにであい夢中になり、ドラクエをするために仮病を使おうとして母親に怒られ、学校でもゲームの話ばかり、みんながゲームに夢中になっていた。


しかし、やがて大きくなると、ゲームばかりやっているやつはオタクだ。引きこもりだとゲームと距離を置く。
ゲームばかりやってるやつとも距離を置く。


しかし、今ソーシャルゲームやDS、WiiPSPPS3Xboxネトゲといった人それぞれ関り方は違うもののみんな結局ゲームが大好きでみんなやっている。


そして、ゲームが好きな僕たちが作るゲームでまた、新たなゲーム好きが生まれてくれるといいなと思っているのである。

そう、そんな素敵な存在はちくびに他ならない。
おっぱいではないのだ。


もちろん僕はおっぱいが好きだ。
おっぱいより好きなものを、おっぱいに一切かすらないものからあげよという問題を出されたら、正直答える自信が無い。

というか、さっきから2時間以上考えているがそんなものはないといっていいくらいおっぱいが好きだ。

だが、しかしそんなおっぱいがすきなのも、ちくびがあってからこそであり、ちくびこそがおっぱいであり、ちくびあってのおっぱいなのだ。


ちくびを隠してもおっぱいだ。でもその先にちくびがあるからおっぱいなのだ。
ちくびを隠したおっぱいを恥ずかしがる人はなかなかいない。
しかしちくびを恥ずかしがる人は星の数ほどいる。


ちくびは特別なのだ。


だから、それに通じるゲームも特別ですばらしい。


ちくびとおっぱいとゲームに感謝

phpの配列を文字列にするあれこれ

DoctrineでResultCacheを使うときに、timeを扱うフィールドがあると効果がないので、キャッシュキー生成の部分をオーバーライドしている。

元のコードは

<?php
// 〜略〜
    public function calculateQueryCacheHash()
    {
        $dql = $this->getDql();
        $hash = md5($dql . var_export($this->_pendingJoinConditions, true) . 'DOCTRINE_QUERY_CACHE_SALT');
        return $hash;
    }
// 〜略〜

こんなふうになってて、md5とvar_exportって重くね?ってふと気になった。

そこで、実際の所どうなのか、僕の思いつく配列を文字列に変換するあれこれの方法でパフォーマンスを調べてみた。

<?php
require_once 'Benchmark/Timer.php';
$array = array(
  'a'    => '1234567',
  'hoge' => 345,
  'time' => '12/21 00:30',
);
$b = new Benchmark_Timer();
$b->start();
for ($i = 0; $i < 10000; $i++) {
  $hash = serialize($array);
}
echo "serialize: $hash (".strlen($hash) .")\n";
$b->setMarker('serialize');

for ($i = 0; $i < 10000; $i++) {
  $hash = json_encode($array);
}
echo "json_encode: $hash (".strlen($hash) .")\n";
$b->setMarker('json_encode');

for ($i = 0; $i < 10000; $i++) {
  $hash = implode(":", $array);
}
echo "implode: $hash (".strlen($hash) .")\n";
$b->setMarker('implode');

for ($i = 0; $i < 10000; $i++) {
  $hash = implode(":", array_keys($array)) . "=>" . implode(":", $array);
}
echo "implode + array_keys: $hash (".strlen($hash) .")\n";
$b->setMarker('implode + array_keys');

for ($i = 0; $i < 10000; $i++) {
  $hash = var_export($array, true);
}
echo "var_export: $hash (".strlen($hash) .")\n";
$b->setMarker('var_export');

$b->stop();

$b->display();

結果

serialize: a:3:{s:1:"a";s:7:"1234567";s:4:"hoge";i:345;s:4:"time";s:11:"12/21 00:30";} (75)
json_encode: {"a":"1234567","hoge":345,"time":"12\/21 00:30"} (48)
implode: 1234567:345:12/21 00:30 (23)
implode + array_keys: a:hoge:time=>1234567:345:12/21 00:30 (36)
var_export: array (
  'a' => '1234567',
  'hoge' => 345,
  'time' => '12/21 00:30',
) (73)
                                                                                                                                    • -
marker time index ex time perct
                                                                                                                                    • -
serialize 1285050970.27137800 0.027326 7.44%
                                                                                                                                    • -
json_encode 1285050970.30083500 0.029457 8.02%
                                                                                                                                    • -
implode 1285050970.32389300 0.023058 6.28%
                                                                                                                                    • -
implode + array_keys 1285050970.39212300 0.068230 18.58%
                                                                                                                                    • -
var_export 1285050970.44748400 0.055361 15.07%
                                                                                                                                    • -

大方の予想通り,Doctrineの方法(var_export)は遅い!

ここで、あ!そうかDoctrineはオブジェクトにも対応してるんだな!ってことに気づいてオブジェクトにも対応するように修正

<?php
require_once 'Benchmark/Timer.php';
$array = array(
  'a'    => '1234567',
  'hoge' => 345,
  'time' => '12/21 00:30',
  'obj'  => new Test(5, 'abcd', '123'),
);
class Test
{
  public $a;
  protected $b;
  private $c;

  public function __construct($a, $b, $c)
  {
    $this->a = $a;
    $this->b = $b;
    $this->c = $c;
  }
}
//test
$b = new Benchmark_Timer();
$b->start();
for ($i = 0; $i < 10000; $i++) {
  $hash = serialize($array);
}
echo "serialize: $hash (".strlen($hash) .")\n";
$b->setMarker('serialize');

for ($i = 0; $i < 10000; $i++) {
  $hash = json_encode($array);
}
echo "json_encode: $hash (".strlen($hash) .")\n";
$b->setMarker('json_encode');

for ($i = 0; $i < 10000; $i++) {
  $hash = var_export($array, true);
}
echo "var_export: $hash (".strlen($hash) .")\n";
$b->setMarker('var_export');

$b->stop();

$b->display();

結果

serialize: a:4:{s:1:"a";s:7:"1234567";s:4:"hoge";i:345;s:4:"time";s:11:"12/21 00:30";s:3:"obj";O:4:"Test":3:{s:1:"a";i:5;s:4:"*b";s:4:"abcd";s:7:"Testc";s:3:"123";}} (158)
json_encode: {"a":"1234567","hoge":345,"time":"12\/21 00:30","obj":{"a":5}} (62)
var_export: array (
  'a' => '1234567',
  'hoge' => 345,
  'time' => '12/21 00:30',
  'obj' => 
  Test::__set_state(array(
     'a' => 5,
     'b' => 'abcd',
     'c' => '123',
  )),
) (172)
                                                                                                                            • -
marker time index ex time perct
                                                                                                                            • -
serialize 1285052647.37092000 0.041734 10.71%
                                                                                                                            • -
json_encode 1285052647.40332300 0.032403 8.31%
                                                                                                                            • -
var_export 1285052647.49001500 0.086692 22.25%
                                                                                                                            • -

なんと、、、全然遅い。

僕の結論

serializeのほうがjsonより少し早いけど、データの小ささ、多言語との互換性を考慮すると、jsonを使うのがよさそうな気がする。
ただし、Objectを含み、privateメンバの値も重要だよってときは、serializeが良い。
というか結局本気で取り組むなら、inplode, json, 無変換を臨機応変に使い分けるべしって感じ



おまけmd5を付けた場合

                                                                                                                          • -
marker time index ex time perct
                                                                                                                          • -
serialize 1285054112.44181000 0.041134 10.52%
                                                                                                                          • -
serialize+md5 1285054112.50591500 0.064105 16.40%
                                                                                                                          • -
json_encode 1285054112.53768200 0.031767 8.13%
                                                                                                                          • -
json_encode+md5 1285054112.59036000 0.052678 13.47%
                                                                                                                          • -
var_export 1285054112.68119600 0.090836 23.23%
                                                                                                                          • -
var_export + md5 1285054112.79160600 0.110410 28.24%
                                                                                                                          • -

var_exportを使っちゃうより全然早いので、復元しない限りは使ったほうがよいきがする



こんな感じで、結構アクセスが多くなりそうなサービスの開発にDoctrineを選択したことを今は正直後悔している。

Doctrineはイニシャルの開発工数は慣れれば減りそうだが、パフォーマンスを気にし始めるとチューニングで死ぬ。
だったら、いろはを知っているPropelを選べばよかった。。。

phpのinstanceofとis_subclass_of()の違い

is_subclass_ofつうのを発見した

<?php                                      
                                           
$super = new Super();                      
$sub   = new Sub();                        
                                           
var_dump($super instanceof Super);         
var_dump($sub instanceof Super);           
var_dump($super instanceof Sub);           
var_dump($sub instanceof Sub);             
var_dump(is_subclass_of($super, 'Super')); 
var_dump(is_subclass_of($sub, 'Super'));   
                                           
class Super                                
{                                          
  public $a;                               
}                                          
class Sub extends Super                    
{                                          
  public $b;                               
}

bool(true)
bool(true)
bool(false)
bool(true)
bool(false)
bool(true)

名前のまんま is_subclass_of はそいつ自身は含まない

初めてのロングライド(準備)

来週1週間休みなので、早速明日初めてのロングライドにいくつもり。

at 三浦一周

いつも鎌倉まで通ってるので帰りは江ノ島から湘南台を迂回する遠回りコース。
疲れてたらそのまま鎌倉から帰ろうかな


大きな地図で見る

早速、涼し気なドイターのバックパックやら、ドリンクホルダーやらサドルにつけるバックやら購入してきて、今日はチェーンクリーンも完了。

ではおやすみなさい。