Image 01 Image 02

0
Posted on 14th 4月 2010 by y

折しも核安全サミットが閉幕したばかりですが。

Popularity: 2% [?]

0
Posted on 23rd 1月 2010 by y

ウェブ開発の世界で、コードや設計の見直しが必要なのに、あまり時間や労力を割いてもらえないのが、速度の問題である。セキュリティなら見直しどころかとにかく素早く確実に対処する必要があるわけで、これは有無をいわさず誰もが取り掛かるであろうが(そうでなければ転職するべき)、遅いソフトウェアについては、まあ動いてはいるわけだし、もっと優れたハードウェアに載せ替えることで対応できるならそちらを選択するのも現実的だと考えられがちだ。高速化なんて、実際やってみても成果が上がるとは限らず、また開発者も無理な日程でリリースしてきたコードを今更また眺めるのは苦痛でしかない。いっそ書き直してやるならまだしも、あれやこれやと最適化するのは考えるだけでも面倒くさい。

しかし、実際には遅いウェブサイトは機会損失であり、いくら昔と比べてハードウェアが安価になり、仮想化技術が発達したとはいえ、それだって無料だったり無限に増設可能なわけではない。PCサーバ1台の増設をサービスのプロデューサに納得してもらうのは結構難しいことだ。仮想環境だってたくさん立ち上げるにはそれなりの実環境が必要になる。不景気の中で運用コストが上がる解決方法しか提示できないのは競争力に問題があるといわざるをえない。よって、スケールアウトは常に正しい解決ではない。

もちろん、最初から最大限に速度を追求してシステムを組むのは素晴らしいことで、誰もが実践するべきだ。しかし、そんなに簡単なことなら速度が問題になることなどあり得ないわけで、実際にはこの点を追求し過ぎるとリリースしなければいけない期日を守るのがとても難しくなってしまう。遅いのも機会損失だが、リリースできなければ機会が存在さえしなくなってしまうので、エンジニアリング過多は根治されるべき疾患だ。

期末が近づいてきたので、この2年くらいの自分の仕事をざっと整理してみたのだが、一昨年の暮れから今年の始まりにかけて、よく考えたらずっと既存のソフトウェアの高速化ばかりやってきた気がする。最初の立ち上げから1年以上経過したサービスがとうとう音を上げてしまったこともあれば、作ったばかりなのに社内の別チームから要求された速度が到底達成不可能だったので急遽なんとかしなければいけなくなったケースもある。恨み言をいわせてもらえば、ハードウェアやシステム構成の選定は当の検品屋連中だったりするので、そいつらの見積りが甘いのが原因なのだが、お客さんの求めるものがあってのソフトウェアであるわけで、理不尽だと叫んでもプログラムは速くはなってくれない。

そんなとき、誰もが思いつくのは、出力データや処理結果をキャッシュして速度を稼ぐ方法だろう。ご多分に漏れず自分もだいたいいつもそうやってきた。ウェブ上のプログラムには、大変ありがたいことにエントリーポイントがひとつしかない。そう、リクエストを受け付ける場所だ。出所の同じHTTPのリクエストは同時に一ヶ所にしか届かない。そこから、中間の処理があって、出力先は最終的にはリクエストを送ってきたクライアントになる。

前提条件 => 処理実行 => 処理結果

ネットワークの遅延や巨大なレスポンスによるクライアント側の負担といった問題は、普通はそんなには起きない。単純に考えると、結局はウェブ上のサービスはリクエストという前提条件があり、ソフトウェアによる処理があり、レスポンスという処理結果があるだけだ。

ということは、前提条件と処理結果の関係を把握して、その近道を探すのが高速化の第一歩ということになる。ここでのチェックポイントは

「前提条件(リクエスト)と処理結果(レスポンス)の関係」

の検討だ。自分で作業する場合は、まず

(1)リクエストをグループ化することができるか

を考える。メソッド(GETや、POSTときどきDELETEやPUTみたいな動詞)、リクエストURI、クエリで処理結果が同じになるグループを作成することができれば近道は見えたようなものだ。

例:GETのみ、docomoのゲートウェイを通過、FOMA端末、/listsへのアクセス、クエリは「type=used&maker=toyota」であればレスポンスは共通

この場合、リクエストを受け付けた際に既に同じレスポンスを返したかどうか判定して、していなければ通常の処理を実行してキャッシュを作成、キャッシュが作成済みであれば処理をすっ飛ばしてキャッシュからデータを返す、という単純な対応が可能かもしれない。キャッシュの実装内容はシステムのI/O負荷により異なるだろうが、そこは後で検討すればいい。ストラテジーパターンで変更できるようにするとか、まあいろいろ手はある。

そこで問題になるのが、動的コンテンツを提供する場合、まあ当然ながら静的なコンテンツで速度が問題になるのはほとんどあり得ないだろうから当たり前だが、レスポンスとして返されるコンテンツの内容の更新頻度だ。リクエスト毎に内容が変わるのであれば、単純なキャッシュでは対応できない。そこで

(2)更新頻度のグループ化

について検討することになる。いまどきカウンタなんか載せているサイトは絶滅しているだろうが、それでも刻一刻と在庫状況が変化したり、コメント数が増えていくようなコンテンツはたくさんある。

ページ全体が同じ頻度で更新されることは稀だろう。同じリクエストとみなしていいグループに常に新しいContent-typeを返すことはあり得ないが、オークションの入札状況のようにサーバ側のリソースに変化があればそれを常に反映する必要のある部分もあれば、人気の検索語のように1時間くらいに1回更新しても誰も気づかないようなものもある。

例:更新頻度最大 = 入札状況、更新頻度中程度 = 残り3時間以内の商品、更新頻度低 = ホットな検索語

更新頻度のグループがあまりに細分化されている場合は、運用者とよく話し合って、可能な限り単純化していくことが必要になる。サービスの品質に影響がない程度に、できれば3パターンくらいになるとちょうどいい。

3パターンくらいであれば、キャッシュした全体のデータに部分的なキャッシュを組み合わせてレスポンスを作り上げるだけのプログラムをリクエストを受けた場所で処理して済ませることができる。

それから、もっとサーバに楽をさせてあげたいときは

(3)クライアント側に処理を肩代わりできるか

を検討する。PC向けサービスであればクッキーに格納できるデータもあるだろう。JavaScriptにあらかじめ呼び出されそうなデータを格納してしまってもいい。検索候補を表示するのに正直にデータを毎回取得したりせず、サーバ側からは定期的に更新するだけのデータをブラウザ側に先に送っておけば、毎回非同期通信が走ることもない。

もちろん、第三者からアクセスされてはいけないデータもあるので、なんでもかんでもこのやり方が正しいわけではないが、なんでもかんでもサーバ側で処理するのも同様に正しくはない。でも、推測不可能なハッシュ値を格納しておいてそれをキーとしてmemcachedにデータを探しに行って、なければDBに問い合わせるといった対応も可能だ。

3はちょっと話が逸れたが、1と2は「前提条件(リクエスト)と処理結果(レスポンス)の関係」の検討だ。これらがクリアになれば、途中の処理をどれだけ端折ってレスポンスを作成することができるか考えるのはそんなに難しいことではなくなる。

そうなると次にやるべきことは

「処理実行の副作用への対処」

ということになる。アクセスログのように勝手にサーバ側で実行される副作用なら深く考えることもないだろうが(カスタム形式に必要な処理があれば別だ)、検索履歴の保存やアフィリエイトからのアクセスの記録など、サーバ側に直接レスポンスとは関係のない副作用が生じるケースがあれば、それに対応しておかないとサービスには深刻な影響がある。関数型言語をかじったことのある人なら、ある関数が副作用を持つことで前提条件と結果の関係だけで安心することができないことを充分教育されているだろうから、この副作用というものについては手続型言語しかやったことのない人に比べれば敏感かもしれない。

というわけで、単純な考察に相応しい単純な結論として、高速化が可能なプログラムを作るには、上の手続きの反対をまず心がけることだ。リクエストがグループ化可能なレベルになるように要件を定義して、出力するコンテンツの更新頻度をなるべく単純なグループに分類可能に保ち、それから副作用に慎重になる。RESTfulなサービスにする意味はリクエストのグループ化に貢献することにある。更新頻度の単純化と副作用を最小限にすることはキャッシュ戦略を容易にしてくれる。アルゴリズムやプログラミング手法で高速化することも非常に重要であり、キャッシュは万能ではないが、ウェブサイトを100倍速くしたいなら、まずはこんなところから手をつけてみるといいのではないかと思われる。

当然ながら、RAMが128MBでCPUがCeleronの500MHzというサーバで1秒間に100もの動的コンテンツへのリクエストを受けるといった無謀な環境で大冒険している人は、こんなことを検討する必要はこれっぽっちもない。手元の中古のデスクトップを抱えてデータセンタに駆けつけてケーブルを引っこ抜いて差し替えて、全部のリクエストに「ごめんね」と返すだけの設定が完了したら、あとはなるべく遠くまで逃げることだ。追いかけてくる連中も、そんなに賢いことはあり得ないので、深刻に気に病むこともない。

Popularity: 2% [?]

1
Posted on 15th 12月 2009 by y

「ダースまめ」は考えました。

ぼくもライトセーバーがほしいな。

思い立ったらすぐ行動、それが暗黒卿の生きる道です。

しめしめ、お母ちゃんは見当たらないぞ。

これはライトセーバーかな?

やったあ、ライトセーバーをゲット(たぶん)だ!

ご満悦の暗黒卿。

こうして、宇宙を征服するはずの暗黒卿「ダースまめ」は、すっかり野球選手になってしまいましたとさ。

Popularity: 3% [?]

0
Posted on 13th 7月 2009 by y

問題1:下の三行のうち、コピーしてエクスプローラのアドレスバーに貼り付けてそのまま利用できるのはどちらか?

(1) c:¥windows
(2) c:\windows
(3) c:\windows

問題2:上のディレクトリセパレータの見分け方を述べよ。

問題3:意味もなく親切なプログラマが、ファイルの保存場所を管理画面に出力するために上のようなディレクトリを画面上に表示させた。そのままコピペして利用しようとしたユーザに彼は半殺しにされたが、理由を述べよ。ただし普段から忌み嫌われていたというのは不正解。

Popularity: 38% [?]

0
Posted on 11th 7月 2009 by y

かみさんが実家に出かけているのだが、置き手紙に家族の似顔絵があった。かみさんは手先が器用でよくこまかな絵を描いているのだが、確かによく似ている。

IMG_0127.JPG

眠そうな顔がよく特徴を捉えている。

次は下の子と猫。赤ん坊はちゃんと暴虐なアナーキストの顔をしている。猫は、まあこんなもんだろう。

IMG_0128.JPG

上の子はもっとよく似ている。

IMG_0129.JPG

前歯がかあちゃんそっくりだ。

こんな風にイラストをさくっと描いてくれるお母さんがいると置き手紙もなかなか楽しい。

しかし、残念ながらこれは完全に偽装事件だ。

IMG_0130.JPG

Popularity: 33% [?]

1
Posted on 26th 6月 2009 by y

教育における体罰を考える」という、体罰の復活を唱える人々による拡大版の新世紀歓談のような集会があったようで、そこで田久保忠衛が生き恥を晒していたらしい。tsudaられているのをつらつら読んでいたらのけぞってしまった。以下に引用する。

田久保「オバマは大統領選で恥を知れと言われた。本来ならそういうこと言われたら真っ赤になって怒るところだが、彼はどす黒いから怒ってるかどうかわからない(会場笑)」

笑っている会場もまた不気味である。誰か怒ってそれこそ体罰でもって教えてあげるべきなんじゃないか。

Popularity: 49% [?]

0
Posted on 26th 6月 2009 by y

MacPeopleの人がtsudaさんにTwitter上で原稿を催促した(投稿が削除されたようなのでリンクなし)のを受けて、さっそくTwitterで入稿が遅れているライターを追跡するボットの仕様が公開されていた。仕様があるなら実装が必要なので、さっそくやってみた。

といっても、個人的に催促する相手もいないので、実際にはTwitterには発言せず、標準出力に出してテストした。別にむずかしいことは何もしていない。追加仕様として、短時間に何件もタイムラインの更新が続いていた場合は「@yomoyomo tsudaってる場合じゃないんじゃ…」というセリフに変わるのと、原稿がちゃんと届いたときは実行者が自分のアカウントで「@tsudaさん、ありがとうございました」と発言すれば止まるようになっている。それから、設定された時間を過ぎると6時間おきに「どこへ行ってもうたんや…」と3回つぶやき、それから罵倒して終了する。テストには仕様の発案者を利用した。以下が出力結果。

$ ruby twit_bot.rb

締切は2009-06-26 01:55:00です

追跡を開始します

————–

@yomoyomo ××編集部の○○です。yomoyomoさん、原稿まだでしょうか。締め切りすぎてます。よろしくおねがいします。

botより:残り0日0時間2分を切りました。

@yomoyomo いいからMacPeopleの原稿書け #うまい具合に何か投稿されていたらしい

botより:残り0日0時間1分を切りました。

@yomoyomo いいからMacPeopleの原稿書け #またうまい具合に

botより:時間切れです。

@yomoyomo どこへ行ってもうたんや…

どうやら動いているようだ。なにぶん、ぜんぜんテストしていないのでどうなるかわからないが、時間を守らないライターに苦労されている印刷関係の方や編集関係の方はぜひお試しあれ。実際にやってくれる人は@yagi_までご連絡ください。Ruby 1.9で作っているので実行時になんか警告が出ますが大胆カツカレーに無視。

Popularity: 52% [?]

3
Posted on 23rd 4月 2009 by y

なんか、他人とは思えないほど似ている気がする。

20090423-00000514-sanspo-ent-view-000

髪の毛の量の話ではない。

Popularity: 3% [?]

0
Posted on 22nd 4月 2009 by y

Windows Liveからシュールなメールが。

Windows Live および MSN のお知らせメールの受け取り設定について
(中略)
現在、お客様の [お知らせメールの受信設定] におきまして、「Windows Live 製品または MSN 製品に関する情報をメールで受け取らない」設定になっております。今後、マイクロソフトより重要な製品更新情報についていち早くお客様にご連絡を差し上げたいと存じます。よろしければ、大変お手数ではございますが、お客様のアカウントのプロフィール (こちら) から、設定変更をお願いいたします。チェックボックスを外している状態が、「受け取る」の設定になります。

いや、だからこういうのを受け取りたくないからそうしてるんであって。

Popularity: 4% [?]

0
Posted on 22nd 4月 2009 by y

同僚がphpDocumentorのソースに変なことが書いてあるというので見ると、確かに変だ。長いコメント部分を除くとこうなっている。

#!/bin/sh
if [ -z "$PHP" ]; then
   PHP=`which php`
fi
(exec $PHP -C -q -d output_buffering=1 "$0" "$@") 2>/dev/null
if [ "$?" -ne "0" ]; then
        echo "FAILED:  Bad environment variable \$PHP (set to \"$PHP\")"
        exit 1
fi
exit 0
<?php

ob_end_clean(); // make output from autofind php code disapear

$test = @include "phpDocumentor/find_phpdoc.php";
if ($test == 6) {
    // find_phpdoc.php returns 6
    include "phpDocumentor/phpdoc.inc";
} else {
    echo "Error: phpDocumentor not found" . PHP_EOL;
}
?>

シェルスクリプトが冒頭にきて、その中から今度はPHPとして実行されるように自分自身を呼び出して、しかもご丁寧に出力バッファリングでシェルのコード部分が出力されないようにしているよ!PHPはHTMLに埋め込まれる言語でもあるので、開始タグ「<?php」と終了タグ「?>」で囲まれていない部分はそのまま出力されるから、これでもちゃんと実行される。

それにしても、この手が使えるなら、シェルスクリプト以外の言語だって動かせるんじゃなかろうか。

さっそく実験。

#!/usr/bin/ruby

puts "This is Ruby!"
system("php -d output_buffering=1 -q #{__FILE__}")
exit
__END__
<?php
ob_end_clean();

print("This is PHP!\n");
exit;
?>

実行結果:

This is Ruby!
This is PHP!

なんと!

この手を使えば、PHP on Ruby on Railsだって夢じゃない!PHP4からの移行が大変?冗談でしょ。これからはPHPはあらゆるスクリプト言語の上(下)で動く時代ですよ。

Popularity: 9% [?]