T

当社比100倍のススメ

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

しかし、実際には遅いウェブサイトは機会損失であり、いくら昔と比べてハードウェアが安価になり、仮想化技術が発達したとはいえ、それだって無料だったり無限に増設可能なわけではない。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もの動的コンテンツへのリクエストを受けるといった無謀な環境で大冒険している人は、こんなことを検討する必要はこれっぽっちもない。手元の中古のデスクトップを抱えてデータセンタに駆けつけてケーブルを引っこ抜いて差し替えて、全部のリクエストに「ごめんね」と返すだけの設定が完了したら、あとはなるべく遠くまで逃げることだ。追いかけてくる連中も、そんなに賢いことはあり得ないので、深刻に気に病むこともない。

ソフトウェアを公開すると

ときどき、気が滅入ることがある。

Sql Injection-1

昔やっていたプロジェクトに、とあるきっかけで久しぶりにログインしたら、この有様。

完全なテストは不可能だ

思うに、それは論理学でいうところの帰納法で解決できるのではなかろうか。

完全なテストは不可能だ:
さて、プログラムの話に戻ります。intの引数を2個とる場合、その組み合わせは1600京ほどに なるということを先の稿で述べました。 そして、バグが「ある」ことを証明する場合、バグの例をひとつ探し出せばよいのに対し、 バグが「ない」ことを証明するにはこの1600京のパターンすべてを網羅して検査し、 全て正常に動いたということを提示しなければなりません。

数学でも、全ての数を計算したわけではないのに成立している定理は山ほどある。というかそうでないものの方が少ないはず。

悪魔の証明、という目の付けどころは悪くないのに。まあ、ちょと前に自分でも取り上げたわけだが。

Prototype Portal Class

コンテンツをブロックに分けて、それぞれをWidgetと称して自由に位置を変更したり非表示にしたりするJavaScriptライブラリ、Prototype Portal Classyoumosで紹介されている

PCサイト向けCMSのページ編集機能なんかに使えるな、と思ったら、これってJetspeedの画面みたいだな。

品質管理についてみんな本当は知りたいこと

GoogleはPythonの開発者に、コードレビュー支援ツール「Mondrian」を作らせている。他にも、Google Testing Blogを読むと毎年テスト自動化カンファレンスを開くなど、品質管理への取り組みに積極的だ。

パッケージ商品や受託のソフトウェア開発で、コストに見合わない過度のテストは無理と主張する人はいても、品質管理が大事ではないと断言する人はいないだろう。Webアプリ開発のいわゆるチープ革命や「50%の完成度でリリース!」などのお題目に勘違いしてしまうと、この世界では命取りにしかならない。

しかし、いざソフトウェアの品質管理に取り組むと、これが一筋縄ではいかない問題だというのはおよそ全ての開発者も肯定するところだろう。素晴らしい出来映えのソースコードは一人の天才プログラマが生み出すことが出来るものだが、経験則に照らし合わせると、究極的な品質管理のプロセスもまたそうだというわけではない。

なぜ、品質管理は難しいのか。まず、品質の管理というプロセスそのものが、常にその品質を管理されていなければならないので、品質管理自体が常にメタレベルの問題を孕んでいるという事実が問題を難しくする要因の一つだ。というとなんだか現代思想のレトリックのようだが、品質管理というのは常に移ろい変化するものだと考えれば、当然のことだともいえる。例えば、セキュリティの観点から常にソースコードをチェックしているチームは、全く新しい攻撃手法が公開されれば、これまで実行していたチェックのプロセスを改善する必要があるのだ。

品質管理という作業のスコープがあいまいなのは、品質管理に手をつけようとすると、あらゆるところに問題を見いだすことが出来るせいでもある。スケジュール作成プロセスの見直しでも品質は改善される。SEがもっと粒度の高い作業指示をすれば品質は改善される。販売戦略だって劇的に製品の品質を変えることがある。職場の環境だって改善すれば品質は向上する。ボトムアップでもトップダウンでも隣同士の話し合いでも何らかの効果があるだろう。でも、だったら誰がこの作業を担当すればいいのだろう。全員だろうか。では、品質管理はみんなの副業なのか。でも、全社規模の働きかけって、ちゃんと機能したことなんかあった試しがないと思わないか?大きすぎる目標は得てして来るべき理想社会のように幻に終わってしまいがちである。

それから、品質管理がいったいどれだけ儲けに繋がるのかがわからないというのも問題だ。極端な話、製品は作れば売ることが出来るが、偉大な品質管理チームは製品の完成には寄与出来ても作り出すことは出来ない。どこまでの費用対効果を見込んでいいものか、経営者なら必ずや迷うところだろう。

たとえ品質管理の問題をとりあえず開発現場の仕事と限定したとしても、品質管理を担当するチームの人員配置は悩ましい問題だ。ソフトウェア開発会社が、コーディングを担当するメンバーより優秀なプログラマを品質管理チームに配属させることが、果たしてどれだけあるだろうか。では、多少の差がある程度の粒の揃った技術力の高いメンバーを揃えている開発会社はどれくらいあるだろう。先日こんな記事を読んだ。ソフトウェア工学の博士号を持ったようなプログラマ志望者たちに簡単なテストを実施すると、驚いたことにほとんどの人間が全くそのテストの問題を解けなかった。どれくらい簡単なテストかというと、1から100までの数字を画面に出力するが、3で割り切れる場合は数字ではなくある文字列を、5で割り切れる場合は別の文字列を、3と5で割り切れる場合はこれもまた別の文字列を出力するという内容だ。これは、何もアルゴリズムの問題ではない。ある数字が3で割り切れるか、5で割り切れるか、それともその最小公倍数の15で割り切れるか判定するだけのロジックを実装できないのである。

自身が優秀な開発者には驚きをもって迎えられたこの記事だったが、実際に現場で採用活動をしたことのある人なら知っている通り、この売り手市場のプログラミングの世界では、こんなことはとうに珍しくもない現象になっている(知らない?それはそれはおめでとうございます)。筆者の勤め先でも、面接時にこれよりもっと簡単な試験を実施している。例えば、5つの数字が改行で並ぶ(改行コードはLF)テキストファイルからこれらの数字を読み込み、その最大値、最小値、合計値、平均値を画面に表示させる。実装する言語はPHPが望ましいが、別に問わない。あまりに簡単な問題なので実装方法は幾通りもあるだろう。自分でクイックソートを実装するもよし、組み込みの関数を使うもよし。紙の上に書いてもらうのだから、まあ多少のエラーは大目に見よう。問題を作った当初はそんなことを考えていた。だが、現実には、今までにこの問題に正解を出したプログラマ志望者はほとんどいない。パースエラーがあるとか、そんな生易しい間違いではない。そもそも最後まで与えられた仕様通りに実装出来るケースの方が稀なのだ。それに、もしちゃんと書けたとしても、その人は優秀なのでいくらでも働き口が見つかるから、条件のいいところに取られてしまう。そして、結局あれやこれやと胸に抱いていた希望を捨てて、ポテンシャル採用と称して誰もいないよりはマシだろうと妥協することになる。

各メジャーバージョンに超強力なメンテナを要するソフトウェア開発の現場(アンドリュー・モートンやアラン・コックスが面倒みてくれる!)ならいざ知らず、一般的なソフトウェア開発会社の実情なんてこんなものじゃなかろうか。そうでないところは、きっと何かしらの手を打ってきたところに違いない。品質管理の重要性が最近より声高に唱えられるようになってきたのは、こんな開発現場の凄まじい事情もある。優秀なプログラマがいないなら、優秀でないプログラマの書くコードをなんとか製品レベルにするために手を打たないと、開発会社として立ち行かなくなる。ましてや、Googleさえも相当なコストをかけて品質管理に取り組んでいるのだから、このままでは普通のソフトウェアベンダならまったく太刀打ち出来なくなってしまう。

ちょっとしたソフトウェア歴史観というやつを思いついた。これは、かつて大学の研究機関やNASA、IBMのようなエリート集団や巨大企業(同じか)が中心となっていたソフトウェア開発が、一般企業の業務として開かれて拡散していったことへの揺り戻しなのだろうか。今度はGoogleを含む超優秀なプログラマ集団(まあ、Googleだって大きくなればそれなりに問題は発生してきて、結局は普通の開発会社に成り下がることだってあり得なくはないわけだが。例えば、来週キャンパスの屋根が落っこちるとか)によって集約されて、そのニッチからまた新たに開発会社の拡散が始まる、という歴史解釈もあり得るのではなかろうか。まあ、思いつきの領域を出ない話だが。

もちろん、だから今のうちにソフトウェア開発からとっと手を引いて、もっと儲かる仕事を見つけて鞍替えするという選択肢もあるだろう。開発部門とサービス部門を分社化して、ホールディングカンパニーを組織して、会食の場で情報交換して儲かりそうな投資先を交換し合うのも立派なビジネスだ。よく知らないが。

しかし、こんな状況にあっても、個別にみれば実際にうまくいっているか、少なくともそう見える会社もあるのだから、自分たちがやり方を変えれば道は開けるのかもしれない。そう思っているうちは、出来るだけのことはやってみた方がいい。

もちろん、ソフトウェアの性質上、こんな問題が起きないケースもある。基本的に、品質管理が問題になってくるのはパッケージ商品として開発される、あるいは受託開発されるソフトウェアであって、自社開発の社内システムなら多少の苦情でもなんとかなるだろう。それに、例えばLinuxカーネルの開発にさっき書いたような程度の試験問題が解けない人は参加しないだろう。フリーソフトウェアというのは、ある意味究極の答えだともいえる。ソースコードの中身を公開して、問題があったら見つけた人が直せばいいというのは、品質問題の解決という面でも究極のアプローチだ。フリーソフトウェアというのは、品質管理という視点でもかなり特異な存在といえるだろうが、いくら特異点の話をしても飯は食えないわけで、ここでは脇に置く。

やはり、今もっとも需要があって、それなのにウェブ上ではあまり情報が見つからなくて、開発現場の管理職たちがまるで異性の体はどうなっているのか知りたくて悶々とする思春期の子供たちのようになっているのは、品質管理のベストプラクティスなのではないだろうか。そういう意味で、SIer的なノウハウが表に出ないウェブの情報は問題があるといえる。

そこで、ふと思ったのだが、スケジュール管理、ソースコードの問題検知、コーディングの支援、バージョン管理、進捗管理、バグ管理、改善プロセスに必要なデータ出力といったところを揃えた、ある意味で究極のソリューションは、ひょっとしたら自社開発せざるを得ないものなのかもしれない。ビジネスのコアになるものを外部に委託するというのは、うまくいかない企業の典型だ。そして、開発会社のコアは、やっぱり開発だ。もちろん、外部の会社を買って自社のコアビジネスに組み込むのは外部委託とは違う。マイクロソフトがDOSを買い、PowerPointを買ったのは、すごいことだと思う。もしそれらの製品を開発している企業と下手なアプライアンスを組んでビジネスを進めていたら、決して数十年間ソフトウェア開発の世界でトップを進むことは出来なかったはずだ。

話がズレたので元に戻すと、現在商用、フリーを問わず出回っている品質管理のためのツールを見ていると、個々のソリューションはなかなかいいのだが、いざそれらを自社のワークフローに組み込もうという段になるとどうしても不満が出てきてしまう。ソースコードの検品に絞ってみても、例えばEclipseのソースコードチェックツールを見ると、それはそれでそれなりに優秀だとは思うが、どうしても真面目に運用すれば管理コストがかさみすぎて実用的ではない。商用製品を一通りチェックしてみても、インターフェースがいまいちだったり、ソースコードの問題検知ツールから実際にどのようなワークフローで業務を運用すれば最適なのかがわかりにくかったりして、まだまだ難しい。

そんなわけで、社内で使うツールについては自作してみようと思う。気づいたことがあれば、こちらにも載せながらあれこれ考えていく。

Flexソースコード公開

MPLで公開されるらしい

ニュース元はphp|architect

へぇ、と思ったら昨日の時点でスラドに出てるし。

QC、QAとテストエンジニアリングの違いについて

原文はこちら。面白かったので訳してみた。

テストの世界では、日々の業務を指すのにたくさんの用語が使われている。皆さんもQAやQC、テストエンジニアリングという用語がお互いごっちゃになって使われているのを耳にしたことがあるはずだ。開発者が相手ならそれでも話は通じるだろうが、これらの用語について、さらにはソフトウェアテスティングの世界では一体これらがどのように使われているのかを考えてみるのも有益だろう。QCの古典的な意味は品質管理(Quality Control)で、品質についてあらかじめ決められた要件をみたしているかどうかを検証するプロセスのことをいう。組み立て工場のラインでは、製造された部品を工程の最後の箇所で抜き取ったり、複数の異なる組み立てプロセスを検証したりすることも含まれるだろう。ソフトウェアでは、QCの機能にはソフトウェアを要件にもとづいて検証したり、あらかじめ決められた要件通りのものかどうか検証することが含まれる。

一方、品質保証(Quality Assurance)は、継続的で一環した改善と、QC業務を可能にするためのプロセスを維持するものという意味合いが強い。QCプロセスは製品が自分たちの考えている通りに動くのかどうかを検証するのに利用され、QAプロセスは製品が顧客の求めるものなのかどうかを確証を得るために利用される。つまり、QAプロセスはQCプロセスの視点を含んだメタプロセスであると考えてもいいだろう。QAのプロセスはユーザビリティやデザインを左右するだけでなく、その機能が正しいのみならず、便利なものであるかどうかを検証するものでもあるのだ。

ここGoogleでは、わたしたちは自分たちでテストエンジニアリングと称している第3のアプローチを採用している。わたしたちはこれをQAのメタ世界とQCの現実世界とを結ぶ橋のようなものと見なしている。わたしたちのやり方では、日々のエンジニアリングプロジェクトに必要な結果を出しつつ、自分たちが顧客のことや顧客が望むものについて考える機会を確実に得ることができる。

確かにわたしたちのチームはQAやQCの立場からソフトウェアエンジニアと一緒に仕事をしているが、それだけでなく、製品がテスト可能で、なおかつ十分にユニットテストが行われ、さらには自分たちのチームの中でもそれがちゃんと自動化されるために働いている。

わたしたちは人間は人間が得意なことに注力し、コンピュータが得意なところはコンピュータがやれるようにするために、テストの自動化を重視している。これは自分たちでは手作業のテストは実施しないという意味ではない。そうではなく、わたしたちはもっと人間にフォーカスした(例えば探査試験など)テストを「適切な」量だけ手作業で行うようにして、手作業による繰り返しテストは決してしないということだ。

ウェブアプリケーションのテスト自動化にいまものすごく興味があるのだが、どこかに面白い資料はないだろうか。

社内文書の検索システム

思い立って仕事の合間にブラウザから閲覧する社内文書の全文検索システムを作っている。

【ざっとした要件】

■PDF、Word、Excel、PowerPointのファイルに対応

wvWarepdftotextxlhtmlが使える。

■検索エンジンはSennaを利用

Hyper EstraierNamazuが候補だった。

前者は付属のCGIが便利だけど改造するのが面倒で、後者は珍しさと真新しさに欠けるので。

技術的な優位性とかは考慮せず。

ludiaが使えるので。

■ファイルをアップロードするとその場でインデックスを更新

PDFはludiaのマニュアル通りに、他はテキストに変換してINSERT。

■アップロード処理中はプログレスバーを出す

カッチョイイ!

■検索クエリはGETで渡す

外部サービスと結合しやすいし。

■追加されたファイルの情報を表示

トップページに更新情報として最近追加されたファイルを表示してあげる。

非同期通信で定期更新。

■検索結果にスニペットを表示

ludiaの関数が使える。

誤検出があってもファイルを開く前にユーザが見て判断できる。

■SennaのバインディングはPostgreSQL

MySQLだと本体にパッチを当てないといけないのでPostgreSQLに。

【いろいろ環境設定】

ExcelファイルをHTMLに変換するツールはxlhtml。Mac OS X 10.4.9でxlhtml-0.5をビルドしたら「cole/Makefile.am: required file `./depcomp’ not found」というエラーが出て失敗した。下のようにやってみた。

$ aclocal
$ autoconf
$ automake --add-missing
$ make
$ sudo make install

これで通った。

wv2がfinkに入っていたのでインストールしてみたが、wvWareの使い方の方がウェブでたくさん見つかるのにwv2だといろんなコマンド群が入らないのでwv1系をインストール。途中でlibgsfのバージョンが低いと怒られたが、finkだとlibgsfじゃなくてlibgsf1.114という名前になっていたので、いったんlibgsfを外して入れ替える。このパッケージ構成はよくわからない。

コピー禁止のPDFファイルをインデックス化するために、こちらを参考にxpdfをちょっと変更。まあ、自分だけで使うツールだし、いいよね。ね?ね?

SennaとludiaのインストールはThinkITの記事マニュアルを参考に。今回はMecabを使うことにした。

DBはPostgreSQL。createdbの際、エンコーディングはUTF-8を指定した。

テーブルとファンクション、インデックスの作成はこんな感じ。ウェブからアップロードされたファイルは新しくユニークなファイル名を付与されて適当なパス上に保存される。元の名前はDBに格納されて、検索結果ページでクリックされるとattachmentとして元のファイル名でインライン表示されるようにした。ええ、SQLもDBもあんまり得意じゃありません。

CREATE OR REPLACE FUNCTION 
	pgs2pdftotext1(TEXT) 
RETURNS TEXT AS '$libdir/pgsenna2', 'pgs2pdftotext1' 
LANGUAGE 'C' STRICT IMMUTABLE;

CREATE TABLE search (
	search_id serial PRIMARY KEY,
	filename text NOT NULL DEFAULT '', --元のファイル名
	filepath text NOT NULL DEFAULT '', --新たに付与したファイル名
	regist_date timestamp without time zone 
		NOT NULL DEFAULT '2007-01-01 00:00:00'	
);

CREATE INDEX 
	idx_search_filepath 
ON search 
USING fulltextb(pgs2pdftotext1(filepath));

PDFファイルのデータをINSERTする場合、こんなSQLでインデックスが作成される。

INSERT INTO search 
	(
		filename, 
		filepath, 
		filetext, 
		regist_date
	) 
VALUES 
	(
		'元のファイル名', 
		'新しいファイルへのパス', 
		pgs2pdftotext1('新しいファイルへのパス'), 
		now()
	);

PowerPointやExcel、Wordのファイルもそれぞれ => テキスト => PDFと変換してINSERTは常に同じコマンドを使うようにしてもいいんだけれど、それも不健康な感じなのでテキストとして普通に処理することにした。now関数を使うけど、別にDBのレプリケーションはしないからいいや。

【実装しないもの】

今回の作業で実装しない機能は:

  • クローラ(Window環境用も作りたくなるから)
  • ファイル形式の自動判定(無理!拡張子で判定)
  • 検索結果にタグ付けして次に簡単に呼び出せるようにする(時間が…)

クローラはないけど、特定のディレクトリ内のファイルを一気に処理するバッチファイルは作っておいた。最初のデータ入力が面倒だし。

もしかしたら実装しちゃうかも:

  • 検索語のサジェスチョン(インクリメンタルサーチで今までに入力されたデータから引っ張ってくる)

こんなもんかな。さて、作業開始。

はてなブックマーク – ポール・マッカートニー取調室 / 2007年03月22日

コメント欄がないのでここに。otusne遍在説によれば、ネットワーク上にさえあれば必ず見つけてもらえるはずなので問題ないだろう。

はてなブックマーク – ポール・マッカートニー取調室 / 20070322:
Oracle でセッション管理するならどうする? :: Drk7jp

「おらくるってベンチマーク取って公表しちゃいけない契約があるとか聞いた気がしたけど都市伝説だったか」

これ、聞いたところではLinux版が出た当初のEULAには本当にこんなことが書かれていたらしい。Windows版のパフォーマンスとあまりにも差が大きい(Linux版の方が圧倒的に速い)のでこんな処置がとられたと噂されていた。時代的にはOracle7か8くらいの頃かな。

当時の話としてはこのリンクがホットだったと思う。

Open Tech Press | CscopeとSilentBobによるソースコードの解析

驚きの記事(下線筆者):

Open Tech Press | CscopeとSilentBobによるソースコードの解析:
SilentBobは構文解析を利用してソースファイルを解析する。そのため、正規表現を利用してマッチする行をファイルから探し出すExuberant Ctagsのようなユーティリティよりも高速な解析が行える。試しにLinuxカーネル(バージョン2.6.19)を解析させたところ、Exuberant Ctagsではタグテーブルの生成に90秒かかったが、SilentBobでは10秒しかかからなかった(いずれも2.6MHzCerelonマシンで実行)。また、SilentBobは、マルチスレッド処理による最適化にも対応している。

2.6MHzのCerelonマシン!

急いで原文をみると(下線筆者):

Linux.com | Using Cscope and SilentBob to analyze source code:
SilentBob uses syntax analysis to parse source files, which makes it faster than a utility like Exuberant Ctags, which uses regular expressions to locate the appropriate line in a file. In a test run on the sources for the Linux kernel (version 2.6.19) Exuberant Ctags generated the tags table in 90 seconds, while SilentBob did its job in 10 seconds (on a 2.6MHz Celeron). SilentBob also supports multithreading optimizations.

誤訳ではない。