fc2ブログ

本を読む

読書やコンピュータなどに関するメモ

「タクシー王子、東京を往く。」

 日本交通の御曹司として生まれ、3代目社長を継いだ著者が、いちどは1,900億円の負債を抱えるまでに至り、自分の始めた新規事業も失敗して挫折、しかしそこから這い上がって会社を再建…

 …という部分は数行で済ませて、その後の話を語るのが本書。突然、1か月間、実際に見習い運転手としてタクシーに乗って営業するという体験談だ。

 ただし、最大の問題は、著者が道を知らないということ。なにしろ、渋谷から池袋まで明治通りが通っていることも知らなかったぐらい(笑)。それでも、お客さんに聞きながらこなしていく、そんな様子が、読み物として面白かった。

 以下、本書で仕入れたタクシー(日本交通)関連のトリビア。タクシーにあまり乗る機会がないので、有名な話だったらすみません。

  • ほかのタクシーを追い抜いて客を拾うのは昔は暗黙のルールでご法度だったが、規制緩和で台数が急増した結果、うやむやになっている
  • 隔勤:朝8時から深夜2時まで乗車(途中3時間休憩)し、1日休んで、また翌朝から勤務する形態
  • 派手な格好をした若い女性からのクレームがいちばん多い
  • デジタルGPS無線で、最適な車を回せるようになった
    • ただし新人はパニックにならないよう3か月は無線配車は受けない
  • わざと場所を間違うように誘導してクレームをつけ、金を払わない、常習犯の手口
  • 走行記録はスマートメディアで
  • 墨田区にも立川(たてかわ)という地名がある
  • 飯田橋の大曲交差点近くにあるスタンドが、日本一大きいLPガスのスタンド
  • 青タン:深夜割増料金(メーターが青くなる)
  • 客に「お任せ」と言われた場合でも、事前にルートを告げないと、クレームになることがときどきある
  • 新人の場合、1日に走行距離300km、営業回数30回がひとつの指標
  • 洗車のコツは水を使いすぎないこと。拭きとりが大変だし、拭きムラも出てしまう
    • タクシー運転手には「グラースターゾル」が愛用されている
  • スポーツ、コンサート、パーティなどのイベント情報を押さえておくのもタクシードライバーの基本スキル
  • タクシー車両の座席はフルフラットになって仮眠をとれる
  • 日本交通では7割の車両がトヨタ。アイドリングストップ機能が充実しているから
  • 「お客さまがお客さまのいるところに連れていってくれる」
  • 左三回の法則:降車したあと、左回りで同じブロックを3回まわってみる
  • 銀座ではタクシーの乗禁地区が設定されていて、22~5時は指定の場所以外では乗せてはならない
  • GPSコード:日本交通のタクシーではレシートに降車場所のGPSコードが印字され、次回は乗車時にそれを出すと自動で行き先をセットできる
  • タクシー運転手が道交法で捕まると、点数と罰金だけでなく、営業所にペナルティがついて(累積すると台数を減らされる)、賞与が削られる
  • 乗り場、無線、チケットは、流しより単価が高く効率がよい
  • 泥酔などで客が寝込んでいる場合、手を触れて起こすのはNG。ドロボウやセクハラに間違えられる可能性がある
  • 都内の著名な抜け道(emasaka注:確かに有名なところが多い)
    • 外苑東通りから慶應病院の横を抜けて外苑西通りへ
    • 外苑東通りから権田坂で四谷へ
    • 桜田通りから赤羽橋で分かれて日比谷通りへ
    • 六本木(麻布十番)から鳥居坂→飯倉入口→オークラ別館
    • 日テレ通り→清水谷公園→赤坂
    • 永代通りから首都高沿いに新大橋通りに
    • 新橋から線路沿いに進み、帝国ホテルのところでチェンジして有楽町へ
    • 浜松町一丁目交差点をさけてすぐ南から線路に寄り、戻って汐留に
    • 湾岸通り→泉岳寺の日本トムソンの南から線路を潜る
    • 白金台からグランドプリンス高輪を右に見て品川へ
    • 西麻布交差点から根津美術館に抜けるルート
  • 満タン返しかどうかは、同じ会社でも営業所によって違う
  • アイドリングストップ車両は、ニュートラルに入れるとエンジンが切れ、ドライブに入れるとエンジンがかかる
  • 契約していないスタンドで入れるときは20Lまでというルール
  • 給料日直後は銀行で札をおろしたばかりの人が多く、釣りが足りなくなる

TOMOYO Linuxでサンドボックス実行環境を動かす

 「404 Blog Not Found:perl - FreeBSD::i386::Ptrace released!」あたりを見たのをきっかけに、セキュアOSのことを思い出したので、TOMOYO Linux(のほんのさわり)を試してみました。

 以下、チュートリアルまんまの「動かしてみました」エントリってやつです。

TOMOYO Linuxってなに?

 TOMOYO Linuxは、LinuxカーネルにセキュアOS機能を追加するパッチです。もうじきLinuxカーネル本家にマージされるそうです。

 ちなみに、略称はなぜか「ccs」みたいです。関連プロジェクトには、SAKURA LinuxとかCERBERUS認証とかSYAORANファイルシステムとかYUEとかもあるみたいです。不思議ですね。

セキュアOSはシステムコールを制限する

 セキュアOSというのは、実行できるシステムコールをカーネルレベルで制限するOSです。root権限でも許可がなければブロックしちゃいます。多くの場合、誰がどのシステムコールを呼べるかのホワイトリストをもとに制限します。こういうのをMAC(Mandatory Access Control、強制アクセス制御)って呼びます。

 セキュアOSとしては、LinuxではSELinuxやLIDS、FreeBSDではTruestedBSDなど(の名前)が知られています。

 セキュアOSは、組み込みなどの特定用途向け環境に適しているようです。サンドボックス実行環境にも使えそうですね。

TOMOYO Linuxなら誰でも設定できる

 セキュアOSの問題は、設定がとても面倒なことです。ファイルやデバイスだけならまだしも、共有ライブラリの呼び出しや、共有ライブラリからアクセスするリソースなど、目に見えない部分まで、いちいち手で許可してやらなくちゃなりません。

 TOMOYO Linuxでは、これを解決するために、学習モードというのを用意しています。安全を確保した状態で学習モードで起動し、許可する対象の動作をいちど実行します。ここで呼び出しのログをとり、それをポリシーとしてまとめて許可します。

インストール

 では実際にやってみます。ここではCentOS 5.2を使います。

 といっても、インストール方法は公式サイトの「TOMOYO Linux 導入手順書 (CentOS 5.2版)」のとおりにやればいいので、以下省略します。

学習モードで実行

 さて、再起動を実行して、TOMOYO Linuxのカーネルで起動します。セキュアOSなので(?)rootでログインしちゃいます。

 まず、mingettyの子孫プロセスを学習モード(プロファイル1)に移行させます。

[root@localhost ~]# setprofile -r 1 '<kernel> /sbin/mingetty'
1 <kernel> /sbin/mingetty
1 <kernel> /sbin/mingetty /bin/login
1 <kernel> /sbin/mingetty /bin/login /bin/bash
1 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/egrep
1 <kernel> /sbin/mingetty /bin/login /bin/bash /usr/bin/id
1 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/hostname
1 <kernel> /sbin/mingetty /bin/login /bin/bash /usr/bin/dircolors
1 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/grep
1 <kernel> /sbin/mingetty /bin/login /bin/bash /sbin/consoletype
1 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/unicode_start
1 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/unicode_start /bin/kbd_mode
1 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/unicode_start /bin/setfont
1 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/unicode_start /bin/setfont /bin/sh
1 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/unicode_start /bin/setfont /bin/sh /bin/gzip
1 <kernel> /sbin/mingetty /bin/login /bin/bash /usr/lib/ccs/setprofile

 ここで、Perlスクリプトを書いてみます。

[root@localhost ~]# vi hoge.pl

 中身はこんな感じ。

#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw(max);

print max(2, 10, 5), "\n";

 実行します。

[root@localhost ~]# perl hoge.pl
10

ポリシーを確認して保存

 記録したポリシーを確認してみます。

[root@localhost ~]# editpolicy

 キャラクタで画面が表示されました。プロセスの呼び出し関係がツリー状に表示されます。

ccs editpolicy #1

 図では、perlの実行部分にカーソルがあります。ここで、Enterキーを押すと、そのプロセスのアクセスしたものが表示されます。

ccs editpplicy #2

 qキーを押すと終了します。

 記録したポリシーは、忘れずに保存しておきます。

[root@localhost ~]# savepolicy

サンドボックスで実行

 いよいよサンドボックス環境(プロファイル3)に移行します。

[root@localhost ~]# setprofile -r 3 '<kernel> /sbin/mingetty'
3 <kernel> /sbin/mingetty
3 <kernel> /sbin/mingetty /bin/login
3 <kernel> /sbin/mingetty /bin/login /bin/bash
3 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/egrep
3 <kernel> /sbin/mingetty /bin/login /bin/bash /usr/bin/id
3 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/hostname
3 <kernel> /sbin/mingetty /bin/login /bin/bash /usr/bin/dircolors
3 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/grep
3 <kernel> /sbin/mingetty /bin/login /bin/bash /sbin/consoletype
3 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/unicode_start
3 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/unicode_start /bin/kbd_mode
3 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/unicode_start /bin/setfont
3 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/unicode_start /bin/setfont /bin/sh
3 <kernel> /sbin/mingetty /bin/login /bin/bash /bin/unicode_start /bin/setfont /bin/sh /bin/gzip
3 <kernel> /sbin/mingetty /bin/login /bin/bash /usr/lib/ccs/setprofile
3 <kernel> /sbin/mingetty /bin/login /bin/vi
3 <kernel> /sbin/mingetty /bin/login /usr/bin/perl
3 <kernel> /sbin/mingetty /bin/login /usr/lib/ccs/editpolicy
3 <kernel> /sbin/mingetty /bin/login /usr/lib/ccs/savepolicy

 さきほどのスクリプトを実行します。

[root@localhost ~]# perl hoge.pl
10

 問題ありません。

 では次の、学習していないワンライナーはどうでしょう。

[root@localhost ~]# perl -le 'print "Hello"'
TOMOYO-ERROR: Access 'read(open) /dev/null' defined for /usr/bin/perl
Can't open /dev/null: Operation not permitted

 TOMOYO Linuxでブロックされました。めでたしめでたし。それにしても、ここで/dev/nullをopenするなんて知りませんでした。

 ちなみにこのままでは/sbin/shutdownも実行できません。実行するには、無効モード(プロファイル0)に移行します。

[root@localhost ~]# setprofile -r 0 '<kernel> /sbin/mingetty'

まとめ

  • セキュアOSを使うと、ホワイトリスト(ポリシー)にないシステムコールを、rootでも実行できないように制限できる
  • TOMOYO Linuxでは学習モードでポリシーを設定できるのでらくちん

「神獣聖戦 Perfect Edition」上・下

神獣聖戦 上 Perfect Edition (上)
山田 正紀
徳間書店
売り上げランキング: 74665
神獣聖戦 下 Perfect Edition
山田 正紀
徳間書店
売り上げランキング: 75034

 実は好きなSFのひとつである「神獣聖戦」シリーズに、20年ぶりぐらいの新作が登場したので、読んだ。

 「Perfect Edition」と銘打っていて、一見改訂版っぽい題名になっているけど、実質は続編じゃないかと思う。つまり、「舞踏会の夜」か。「神獣聖戦」1~3とかを読んでないと、わからない箇所があるかも。…って調べたら絶版なのかぁ。

 内容は、ネタバレを含むので、「続きを読む」で。

続きを読む »

「弁護士のくず」8巻

 タケちゃんマン似の弁護士が、主に男女関係がらみの事件を解決する連作マンガ。

 「DOLL」では、二転三転する内容以上に、ワイドショーの風評被害を取り上げているなぁと思った。あと織田信長w

LWPはHTMLのhttp-equivを解釈する

 結論はタイトルのとおり。PerlのWebプログラマーの人だったらみんな知ってるようなことでしょうが、初めて知ったので、メモ。

 hoge.htmlを用意。

<HTML>
<head>
<meta http-equiv="content-type" Content="text/html; charset=utf-8">
</head>
<body>
</body>
</HTML>

 hoge.plを用意。fileスキームなのでHTTPヘッダーの情報はほぼ付かないと予想。

#!/usr/bin/perl
use strict;
use warnings;
use feature qw(:5.10);
use LWP::UserAgent;

my $url = 'file:///path/to/hoge.html';

my $ua = LWP::UserAgent->new;
my $res = $ua->get($url);
my @ct = $res->header('Content-Type');

say for @ct;

 実行結果。Content-Typeにcharset情報が。

$ perl hoge.pl
text/html
text/html; charset=utf-8

 どこで解釈しているか、LWP::UserAgent→LWP::Protocol::http→LWP::Protocolとソースをドリルダウンして確認。collectメソッドで以下のようになっていました。

	$parser = HTML::HeadParser->new($response->{'_headers'});
        (略)
	    if ($parser) {
		$parser->parse($$content) or undef($parser);
	    }

「宇宙兄弟」1~5巻

 「このマンガがすごい!」でランキングで知って、後付けで読んでみたら、本当に面白かった。

 「度胸星」+「ドラゴン桜」という評判はなるほどと思った。なにより、人物やエピソードに少しずつフックがあって、印象に残る。

termtter 1.0.6でnotify-sendプラグインがエラーになる件

 野良パッチ。

--- /opt/ruby1.9/lib/ruby/gems/1.9.1/gems/jugyo-termtter-1.0.6/lib/plugins/notify-send.rb	2009-03-22 10:50:06.000000000 +0900
+++ ./.termtter/plugins/notify-send.rb	2009-03-22 13:27:37.000000000 +0900
@@ -10,7 +10,7 @@ Termtter::Client.register_hook(
       text = statuses.take(max).map {|s|
         status_text = CGI.escapeHTML(s[:text])
         status_text.gsub!(%r{https?://[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+},'<a href="\0">\0</a>')
-        "<b>#{s[:screen_name]}:</b> <span font=\"9.0\">#{status_text}</span>"
+        "<b>#{s.user.screen_name}:</b> <span font=\"9.0\">#{status_text}</span>"
       }.join("\n")
 
       text << %Q|\n<a href="http://twitter.com/">more...</a>| if statuses.size > max

「宗像教授異考録」第10集

 古代史の仮説ファンタジー漫画。Amazonのレビューでも書かれてたけど、やっぱり「馬で駆けつけるシーン」がビジュアル的にインパクトがあった(笑)。

 ネタバレなので、今回のネタリストは「続きを読む」で。

続きを読む »

「地を這う魚」

地を這う魚 ひでおの青春日記
吾妻 ひでお
角川グループパブリッシング


 吾妻ひでおの、いまのところ最新作みたい。「夜の魚」の表現(あそこまで底無し沼っぽくないけど)と「不条理日記」のノリ(あそこまでトンではいないけど)で「まんが道」をやったような自伝マンガ。すごくよかった。

termtterを1.0.0に

 twitterクライアントのtermtterが1.0.0になったと聞いて、アップデートしてみた。

 とりあえずやったことメモ。Linux+Ruby 1.9.1。

  • sudo gem update termtter
  • termtterを実行すると「uninitialized constant Module::FileUtils」と言われる
    • 古い設定ファイルをリネームしようとしてるらしい
    • 手動でmv .termtter .termtter.bakしてから再実行
    • .termtter/configが作られた
  • .termtter/configにプラグインのrequireを入れるとエラー
    • 「plugin 'update_editor'」みたく、パスなしで書くらしい。っていうか、それ最初からそうみたい。しょぼん
    • あと、filterとpluginがpluginsに統合されたらしい
    • 自作プラグインは~/.termtter/pluginsディレクトリを作ってその中に置いたら、「plugin 'expand-shortened-url.rb'」とかで呼べた

「not simple」

not simple (IKKIコミックス)
オノ ナツメ
小学館

 ツイてなくて無邪気な男と、そのまわりの人たちの物語。表現も構成も印象的で、笑顔が切ない。

「ヴィンランド・サガ」7巻

オレはさ…アンタと…友達になりたかったんだよ

 すっかりアシェラッドが主役になってるなぁ。腹黒いけど。

 スヴェン王が、わりとステロタイプとはいえ、いい味出してる。

「無限の住人」24巻

 表紙のとおり、あの男と対決。

「PLUTO」7巻

PLUTO 7 (ビッグコミックス)
浦沢 直樹
小学館
ゼペットじいさんも、本当は操り人形…

 次巻で完結とのこと。

 そういえば浦沢直樹って、手が迫ってくるシーンをけっこう使う気がする、とビーゲラン城のエピソードを見ながら思った。あと、冒頭のカラーページの部分、画力に自信がなくちゃ描けないと思った。

bash 4.0:CHANGESの試訳

 bash 4.0のソースに含まれるCHANGESファイルを試訳してみました。bash-4.0-alphaからbash-4.0-releaseまでの分です。

 意味がわからず訳を当てた部分もあれば、これは違うんじゃないかと思う部分もありますので、あくまでご参考程度に。


この文書は本バージョンbash-4.0-releaseと前バージョンbash-4.0-rc1の間の変更点について詳述します。

1. Bashの変更点

a. setlocale(3)が失敗してerrnoの値が変わったときのエラーメッセージとして、strerrorのエラーテキストを含めるだけにしました。

b. trapコマンドで設定したトラップコマンドを実行する前に、行番号をリセットするように変更しました (DEBUGとRETURNのトラップを除く)。

c. 大文字小文字を変更する単語展開が、変数の値に含まれる単語単位で働かないように変更しました。

d. mapfileが対話シェルで実行されたときに割り込み不可能になるバグを直しました。

e. mapfileで最初の行にコールバックが実行されないバグを直しました。

f. mapfileが対話シェルで入力されたEOFを尊重しないバグを直しました。

g. コプロセスを受け取るコードがシグナルハンドラから正しく実行できないのを直しました。

h. printf -bが、64bitシステムで書式文字列中の最初の%書式指定子を無視するバグを直しました。

i. $IFSに`:'や`='、`~'が含まれるときに単語分割が正しくないバグを直しました。

j. プログラム補完で呼ばれたシェル関数が中断されたときにデータが壊れるバグを直しました。

k. 組み込みコマンドtimeが報告するCPUの使用率が100%を凌ぐバグを直しました。

l. シェルで-eオプションが有効なときの挙動を、Posixシェル標準化ワーキンググループの合意を反映するよう変更しました。

m. いくつかの状況で、リダイレクトが関数に現れるときにtypeやdeclareで表示されないという、bash-4.0-alphaで入ったバグを直しました。

2. Readlineの変更点

a. 拡張パターンマッチング!(...)により以後の履歴展開が妨げられるバグを直しました。

b. 許可されない関数をシグナルハンドラから呼び出せないように、シグナルハンドリングのコードをやり直しました。

3. Bashの新機能

a. readarrayがmapfileの別名となりました。


この文書は本バージョンbash-4.0-rc1と前バージョンbash-4.0-beta2の間の変更点について詳述します。

1. Bashの変更点

a. $()形式のコマンド置換の直後にクォートされた改行が来るとパースエラーになるバグを直しました。

b. `*('ではじまる拡張パターンマッチングがパターン置換の単語展開と併用できないバグを直しました。


この文書は本バージョンbash-4.0-beta2と前バージョンbash-4.0-betaの間の変更点について詳述します。

1. Bashの変更点

a. 単語展開の失敗がPIPESTATUSでなく$?にセットされるバグを直しました。

b. 先頭にチルダのついたファイル名がカレントディレクトリにある場合、ファイル名の補完がチルダをクォートするように変更しました。

c. 複合コマンドに対するリダイレクトでファイルディスクリプタが回収されないバグを直しました。

d. -uオプションが指定されているとき、位置パラメータが与えられていないのに、$@や$*の展開でシェルが終了しないバグを直しました。

e. 出力中に終了シグナルを受け取ってもすぐに終了しないバグを直しました。

f. 単語の補完の間に256個のプロセス置換を作るとシェルがクラッシュするバグを直しました。

2. Readlineの変更点

a. マルチバイトのロケールで非表示文字を含むプロンプトを使いコマンドに数値の引数を与えたときに再表示にエラーが起こるバグを直しました。

b. 画面で2行にわたる非表示文字を含むプロンプトを使っているときに再表示にエラーが起こるバグを直しました。


この文書は本バージョンbash-4.0-betaと前バージョンbash-4.0-alphaの間の変更点について詳述します。

1. Bashの変更点

a. Posixスタイルのコマンド置換をパースするときの初期化の前に使われる変数の誤字を直しました。

b. パラメータの展開が、パターンを削除する展開が空になるパターンの一部で、空ではない文字列の一部として使われるときに、迷子の^?ができるバグを直しました。

c. 文字列がstrtolで数値に変換されないのに変換が成功したように扱われるバグを直しました。

d. 組み込みコマンドreturnは、Posixの要求に合わせ、オプションを認めません。負の終了ステータスを指定するには、前に`--'を置きます。

e. ローカル変数が空の値ではなく空文字列で作られるバグを直しました。

f. リストを実行しているときにSIGINTでパイプラインが終了すると、シェルが割り込みを受けたように動作するように、振る舞いを変更しました。

g. `declare var'や`typeset var'がvarを空文字列で初期化するバグを直しました。

h. 組み込みコマンドbindが行編集の動作しない状態で呼ばれたときに、警告を表示するが先に進むように変更しました。

i. errexitオプションがセットされていて、パイプライン中のコマンドが0でない終了ステータスを返したときに、シェルが終了するバグを直しました。

j. いくつかの状況において、bash -cでコマンドを実行したときにexitトラップが実行されないバグを直しました。

k. evalでコマンドを実行したときに$?がときおりセットされないパーサーのバグを直しました。

l. $'\x7f' のエスケープを含む複合的な配列の代入を評価したときに、迷子のコントロール文字ができるバグを直しました。

m. ファイルディスクリプタ10を対象とするリダイレクトが勝手な振る舞いをするバグを直しました。

n COMP_WORDBREAKSに代入を複数回行なったときに、メモリを複数回解放してしまう場合があるバグを直しました。

o. COMP_WORDBREAKSがunsetされたときにNULLポインタの参照が起こる場合があるバグを直しました。

2. Readlineの変更点

3. Bashの新機能

a. readコマンドの-tオプションに0を指定すると、指定したファイルディスクリプタに読み込めるデータがあれば、成功の終了ステータスを返します。

b. シェルが特権モードで実行されている場合、CDPATHとGLOBIGNOREは無視されます。

c. キーに割り当てられるreadline関数shell-forward-wordとshell-backward-wordが新しく導入されました。シェルのメタ文字で区切られた単語の前または後ろに移動し、シェルのクォートに敬意を払います。

d. キーに割り当てられるreadline関数shell-backward-kill-wordとshell-kill-wordが新しく導入されました。shell-forward-wordやshell-backward-wordと同じ単語区切りで前または次の単語をキルします。

4. Readlineの新機能

a. カーネルがサポートしていれば、readlineはキーボードからのシグナルを受け取ると対応する特殊文字を表示します。


この文書は本バージョンbash-4.0-alphaと前バージョンbash-3.2-releaseの間の変更点について詳述します。

1. Bashの変更点

a. 古い形式のコマンド置換である``をパースする際のバグをいくつか修正しました。コメントのパースやクォートの扱いが含まれます。

b. [[コマンドで正規表現マッチングの演算子=~の引数をパースする際のバグを修正しました。メタキャラクタと空白文字のパースです。

c. シェルが内部で使う高い番号のファイルディスクリプタを不適切に再利用してしまうバグを直しました。

d パターン置換の単語展開において、展開後のパターンが`/'で始まるときに全置換の指定と誤解されるバグを直しました。

e. asprintfとsnprintfの置き換えによりハングやクラッシュが起こるいくつかの問題を直しました。

f. 現在のジョブとひとつ前のジョブを計算するときに不正なジョブを参照するバグを直しました。

g. ハッシュされているコマンドのパス名の正当性を検査するときにハッシュ表に不必要な削除や追加がなされるバグを直しました。

h. 子プロセスに$!の誤った値が引き継がれるバグを直しました。

i. `.'が通常のファイルではないデバイスやパイプなどからコマンドを読み込んで実行するのに失敗するバグを直しました。

j. printfがいくつかのシステムで%xや%Xの展開に失敗するバグを直しました。

k. 書き込み権限のないディレクトリが$TMPDIRに指定されているとき、一時ファイルを作ろうとしてクラッシュするバグを直しました。

l. いくつかの状況で一時ファイルを作るときに$TMPDIRを無視することがあるバグを直しました。

m. プロセス置換によって作られた名前付きパイプが後始末されないバグを直しました。

n. HISTTIMEFORMATが初期化シェル環境に現れたときに尊重されないバグを直しました。

o. IFSが空か空白文字以外を含んで着るときの、$*や$@の展開(クォートされているときもされていないときも)に関するいくつかのバグを直しました。同じ変更は、配列の添字に*や@を指定したときにも適用されます。

p. $IFSに空文字が設定されているとき、位置パラメータや添字に*や@を指定した配列のパターン置換展開に起こるいくつかの問題を直しました。

q. デフォルトのロケールの初期化コードに変更を加え、ロケールを意識したライブラリ関数がより望ましい動作をするようにしました。

r. ジョブのリストを縮めるときにジョブを取りこぼすバグを直しました。

s. 矛盾した状態でシェルを抜けようとしたときにトップレベルの処理ループに引き戻されるバグを直しました。

t. 内部でエスケープされる文字がバックスラッシュでエスケープされたときに2倍になるバグを直しました。

u. シェルの起動時に、メールボックスを初期化してもmaildirを読み込まない (そしてstat(2)がすべてのメッセージに対して呼ばれる) のを直しました。

v. 組み込みコマンドreadが、バックスラッシュで続いた行を読むときに$PS2を表示しないバグを直しました。

w. 内部のクォートに使う文字が$IFSに含まれるときに単語分割でエラーになるバグを直しました。

x. いくつかのシステムで組み込みコマンドからの出力が完全には表示されないバグを直しました。

y. リダイレクトがシェルの出力ファイルディスクリプタに作用するときに出力が失われるバグを直しました。

z. 組み込みコマンドが出力エラーをチェックしていないことによるバグを直しました。

aa. 展開エラーになるパターンを、パターンを削除する単語展開に与えたときにコアダンプするバグを直しました。

bb. 4096のジョブを作って待つと無限ループに陥るバグを直しました。

cc. ある状況でbashがバックグラウンドジョブの状態を見失うバグを直しました。

dd. いくつかの状況において変数の参照で一時的な環境を見ないバグを直しました。

ee. 10番より大きいファイルディスクリプタがリダイレクションで使われたときにbashがクローズするバグを直しました

ff. `bash -i script'で起動したときにシェルが標準入力から読もうとする問題を直しました。

gg. printfに-vオプションが指定されて不正な結果になった場合、メモリリークと変数の初期化が起きる問題を直しました。

hh. 組み込みコマンドreadに-nオプションが指定された場合、(もしかするとマルチバイト文字の) 文字数ではなくバイト数を数えるバグを直しました。

ii. 関数を表示するときに外部形式に変換しないことによるバグを直しました。

jj. ジョブコントロールの初期化を変更しました。ジョブコントロールを有効にする前に端末コントロールに使うttyをシェルが持っているかどうか確認します。

kk. 組み込みコマンドtestが、`-'で始まり1文字より多くの文字が続く引数の解釈を誤るバグを直しました。

ll. いくつかのケースでコマンドがSIGINTをデフォルトにセットするとシェルがコアダンプするバグを直しました。

mm. パターン置換でパターンと置換文字列の両方が空の場合のバグ (単語展開と組み込みコマンドfcの両方に影響) を直しました。

nn. 算術評価のエラーによって以後の評価が無効になるバグを直しました。

oo. パス名展開においてパス名中のバックスラシュをクォート文字と解釈するバグを直しました。

pp. getcwd()を置き換えた実装がメモリを上書きするバグを直しました。

qq. Posixモードでは、組み込みコマンドulimitの-cオプションや-fオプションに、ブロックサイズを512バイト単位で指定するようになりました。

rr. ブレース展開はプロセス置換を変更なしで素通しにします。

ss. コマンド名がチルダで始まっているときに、コマンド名の補完のコードがエスケープされた特殊文字を再度クォートするのを避ける問題を直しました。

tt. 組み込みコマンドprintfで、"'"でエスケープしてマルチバイト文字を使っていてもシングルバイト文字で表示される問題を直しました。

uu. 複合コマンドのリダイレクトが失敗したときに、失敗の終了ステータスが失われるバグを直しました。

vv. サブシェルを作ったときに内部の乱数生成器が乱数の新しい種を正確に取りなおさないバグを直しました。

ww. bashの置き換えたgetcwdがメモリを上書きするバグを直しました。

xx. シェルがコマンド置換の終わるのを待っている間にSIGINTが送られ、終了ステータスが正しいかどうか確かめるときにシェルがSIGINTを受け取らないバグを直しました。

yy. シェルから実行された2番目以降の子プロセスがコマンド置換を違ったプロセスグループで実行するバグを直しました。

zz. チルダの展開の成功がパス名展開や単語分割に制約されるバグを直しました。

aaa. コマンド置換やevalコマンドの最中にトップレベルの処理ループに引き戻されるエラーが発生すると、シェルがハングするバグを直しました。

bbb. 組み込みコマンドreadが-nオプションと-dオプションを処理するときに、-uオプションで渡されたファイルディスクリプタの属性ではなくttyの属性を使うバグを直しました。

ccc. $IFSの最初の文字が空白文字ではない場合に${array[@]:foo}の展開が間違ったものになるバグを直しました。

ddd. ${parameter/pat/sub}の展開で末尾の区切り文字を探すときに起こるバグを直しました。

eee. 補完でディレクトリ名を展開しているときにコマンド置換を不適切に展開するバグを直しました。

fff. 組み込みコマンドfcがいくつかの状況で履歴リストを遡りすぎるバグを直しました。

ggg. Posixモードで動作しているシェルが、sourceや.の引数として指定されたファイルが$PATHで見つからなかったときに$PWDから探すバグを直しました。

hhh. 補完で大文字と小文字を区別しない動作のときに、補完で見つかったコマンド名の大文字小文字を変更するバグを直しました。

iii. sourceや.の引数に `/' が含まれているのに$PATHから探すバグを直しました。

jjj. ロケールにaAbBcC...zZのような照合順序が含まれないときに、ブレース展開で順序を間違えるバグを直しました。

kkk. `set +o history'を初期化ファイルやソースされたファイルで実行しても効果がないバグを直しました。

lll. 条件の算術演算子?:で優先順位のバグを直しました。

mmm. 一時的な変数への代入がシェルの環境変数として生き残るという副作用のバグを直しました。

nnn. 現在のコマンドラインの編集から呼び出された編集コマンドで、端末がcanonicalモードにならないバグを直しました。

ooo. パターンマッチング文字や$IFSに含まれる文字が、代入文の表示で適切にクォートされないバグを直しました。

ppp. ファイルをソースしたときやコマンドをevalしたときに、コマンドの終了ステータスを無視するはずなのに-eオプションが引き継がれるバグを直しました。

qqq. 最初の環境で不正な変数名が使われるときに、シェルがその名前の変数を作ろうとするバグを直しました。

rrr. 文字列がバックスラッシュで終わるときにクォートを取り除くバグを直しました。

sss. 特殊変数が、シェルスクリプトを実行してシェル自身を再初期化したときにunsetされても生き残るバグを直しました。

ttt. `history -c'や`history -d'を実行した後、十分な数のコマンドが履歴にたまるまで履歴が保存されないバグを直しました。

uuu. Bashはコマンド置換をPosixのルールにしたがってパースするようになりました。$()に含まれるコマンドのパースでは、閉じ記号を探します。

vvv. SIGCHILDのハンドラからSIGCHILDをトラップしても生き残らないバグを直しました。

www. SIGCHILDがPosixの仕様どおりに組み込みコマンドwaitを中断させないバグを直しました。

xxx. 組み込みコマンドの数値引数が不正なときに実行中の複合コマンドがショートすることはもうありません。

yyy. breakでループの実行をショートカットしたときに終了ステータスが失われるバグを直しました。

zzz. "${array[*]}"の展開で迷子の文字^?が残るバグを直しました。

aaaa. ヒアドキュメントがEOFで終わっているときのエラーメッセージや、算術式が間違っている時に問題箇所を特定するためのエラーメッセージを、改善しました。

bbbb. 変数の長さを展開するときにマルチバイト文字の文字数の計算を間違うバグを直しました。

cccc. シェルの子プロセスの子プロセスによってプロセスグループが変更されるとトップレベルのシェルが端末のプロセスグループを不正な値にセットする競合状態を直しました。

dddd. 複合コマンドの中のヒアドキュメントが文法的に正しくない形式で表示され、標準入力から読み込み直せないバグを直しました。

eeee. シェルは、ロケールの設定に失敗したときに、いままでより多くの警告を表示します。

ffff. ヒアドキュメントの内容が履歴リストに保存されないバグを直しました。

gggg. configureが誤ってFreeBSDに/dev/fdがあると結論を出すバグを直しました。このバグはプロセス置換で問題になります。

2. Readlineの変更点

a. マルチバイト文字環境での再表示に関する多くのエラーを直しました。

b. vi形式のコマンドモードで不適切に設定されたマークへの移動のバグを直しました。

c. vi形式の挿入モードで矢印キーを使うときに、(コマンドモードとは違い)行末を超えて移動できます

d. 端末が片づけられていて読み込むと-1/EIOが返るときに、readlineがループに陥るバグを直しました。

e. 非表示文字を含むプロンプトを表示するときに起こる再表示のバグを直しました。

f. アプリケーションの指定する補完機能で変更しても、補完で文字が追加される動作をデフォルトに戻せないバグを直しました。

g. emacs編集モードで、ロケールでサポートしたマルチバイト文字を使っているときに、行末からカーソル位置を進めるとカーソル位置が不正になる問題を直しました。

h. 入力のうち511番ごとの文字を取りこぼして1つずれるエラーを直しました。

i. SIGTERMが捕捉されず後片付けもされないバグを直しました。

j. 複数行のプロンプトが非表示文字からなるか、最後の改行の後に文字がない場合の再表示のバグを直しました。

k. プロンプトが非表示文字だけからなる場合の再表示のバグを直しました。

l. 非常に速く連続して文字を受け取ると文字を取りこぼすコード上のバグを直しました。

m. 補完を初期化する前にSIGWINCHを受け取ると、readlineが初期化されていないデータ構造を参照するバグを直しました。

n. viモードでひとつ前のコマンドが不正にセットされ、その結果繰り返しができなくなるバグを直しました。

o. 端末ではない出力ファイルディスクリプタを使っているときにreadlineがエコーバックを無効にするバグを直しました。

p. Readlineは再表示のため内部のデータ構造を操作している間SIGINTをブロックします。

q. 非常に長い行 (130,000文字以上) をペーストしたときにセグメンテーションフォルトを起こす再表示のバグを直しました。

r. プロンプトに表示できる文字がない場合の再表示のバグを直しました。

3. Bashの新機能

a. 位置パラメータに対して部分文字列展開を使う場合、開始位置に0を指定すると、リストの先頭に$0を置きます。

b. 組み込みコマンドhelpは、項目を横方向ではなく縦方向の順に並べます。

c. 変数$BASHPIDが新しく導入されました。常に現在のシェルのプロセスIDを返します。

d. オプションautocdが新しく導入されました。有効にすると、bashはコマンドの最初の語として与えられたディレクトリ名へのcdを試みます。

e. オプションcheckjobsが新たに導入されました。シェルの終了時に、実行中や停止中のジョブをすべて確認して報告します。

f. プログラム補完でエクスポートされる変数COMP_TYPEが新しく導入されました。補完のタイプを表す文字がセットされます。

g. プログラム補完でエクスポートされる変数COMP_KEY新しく導入されました。補完を呼び出した文字 (例: TAB) がセットされます。

h. 子プロセスの作成がリソース不足のために失敗する場合、bashは失敗を報告する前に何度かやり直します。

i. プログラム補完では単語を分割する際にreadlineと同じ文字の集合が使われます。

j. ulimitの-cオプションと-fオプションの指定は、PosixモードではPosix仕様に合わせて512バイト単位になりました。

k. 組み込みコマンドreadの動作を変更して、読み込みがタイムアウトしたときに途中までの入力を変数に保存するようにしました。入力がなかったときには変数に空の文字列がセットされます。タイムアウトしたときには、128より大きい終了ステータスを返します。

l. 互換性レベルの概念が新しく導入されました。shoptによって設定できます。いまのところ、[[コマンドで演算子=~の右辺のクォートされた文字列を処理するときのふるまいをbash-3.1相当に戻すだけです。

m. 組み込みコマンドulimitに、-b (ソケットのバッファサイズ) オプションと-T (スレッド数)オプションが追加されました。

n. declareの-pオプションは、すべての変数の値と属性を表示します。-fオプションとともに指定された場合は、関数の値と属性を表示します。

o. 組み込みコマンドcompoptが新しく導入されました。既存の補完や実行している補完のオプションを変更できます。

p. 組み込みコマンドreadに-iオプションが追加されました。readlineを使うときに、指定された文字列をバッファに挿入します。

q. 組み込みコマンドcompleteに-Eオプションが追加されました。空行の補完のときのデフォルトの挙動を制御できます。

r. パターンマッチ文字を含むコマンド名のコンプリーションが限定的にサポートされます。

s. すべての組み込みコマンドについてヘルプ情報の書式を変更し、manページの書式におおよそ合わせました。

t. 組み込みコマンドhelpに、短い説明を表示する-dオプションが追加されました。また、manページ風の書式で表示する-mオプションが追加されました。

u. 組み込みコマンドmapfileが新しく導入されました。与えられたファイルから各行を配列に投入します。

v. コマンドが見つからないとき、シェルはcommand_not_found_handleという名前のシェル関数の実行を試みます。関数の引数としてコマンド名が与えられます。

w. オプションglobstarが新しく導入されました。有効にすると、パターンマッチで`**'を特別に扱い、すべてのディレクトリ (適切な場合にはその中のファイルも) に再帰的にマッチします。

x. オプションdirspellが新しく導入されました。有効にすると、コンプリーションのときにデイレクトリ名の綴りを修正します。

y. 組み込みコマンドreadの-tオプションは、タイムアウト時間の値として分数をサポートします。

z. ブレース展開で、数の先頭の0詰めができます。すべての数字が同じ桁数になるように適切な数の0が付けられます。

aa. bashに特化した関数dabbrev-expandがreadlineに新しく導入されました。履歴リストから取った候補から選択的に補完できます。

bb. bind -xでキーシーケンスに割り当てられたコマンドに、READLINE_LINE_BUFFERとREADLINE_POINTの2つの変数をセットします。コマンドからREADLINE_LINE_BUFFERやREADLINE_POINTを個別に変更することで、readlineの現在行やカーソル位置を変えられます。

cc. リダイレクション演算子>>&が新しく導入されました。標準出力と標準エラー出力をファイルに追加出力します。

dd. パーサーは`|&'を`2>&1 |'の別名と認識します。コマンドの標準エラー出力をパイプにリダイレクトします。

ee. case文で実行リストの最後を示す`;&'が新しく導入されました。コマンドを終了するかわりに、次のパターンの文に進みます。

ff. case文で実行リストの最後を示す`;;&'が新しく導入されました。コマンドを終了するかわりに、次のパターンを試します。

gg. シェルは新しい変数PROMPT_DIRTRIMを認識します。0より大きい数がセットされると、プロンプトで\wと\Wが展開される際に、パス名をその文字数までにとどめ、途中の文字を`...'で置き換えます。

hh. 単語展開に、新しく大文字小文字変換が導入されました。大文字変換(^[^]) と小文字変換 (,[,]) です。どちらも、文字列や配列要素について、先頭を置換または全置換します。変換する文字をシェルのパターンで指定することもできます。キャピタライズ変換も、ビルド時の指定で使えるようにできます。

ii. シェルには連想配列が用意され、作成、削除、代入、展開が適切にサポートされます。

jj 組み込みコマンドdeclareに、-l (代入された値を小文字に変換する) オプションと-u (代入された値を大文字に変換する) オプションが追加されました。代入された値をキャピタライズする-cオプションもビルド時の指定で使えるようにできます。

kk. コプロセスを指定する予約語coprocが新しく導入されました。非同期に動作し、生成元のプロセスと2つのパイプで接続されます。コプロセスには名前を付けられます。コプロセスの入力ファイルディスクリプタとや出力ファイルディスクリプタ、PIDは、coprocで指定した名前の変数から呼び出せます。

4. Readlineの新機能

a. 変数rl_sort_completion_matchesが新しく導入されました。アプリケーションから候補リストのソートを抑止できます(注意:アプリケーションによってうまくいかない場合もあります)。

b. 変数rl_completion_invoking_keyが新しく導入されました。rl_completeやrl_menu_completeを呼び出したキーをアプリケーションから見つけられます。

c. 関数rl_block_sigintとrl_release_sigintが公開されました。アプリケーションがクリティカルセクション(再表示など)を守りたい場合に呼び出します。

d. 関数rl_save_stateとrl_restore_stateが公開され、アプリケーションから呼べるようになりました。readlineの状態フラグの値の残りが記録されます。

e. ユーザーが設定できる変数history-sizeが新しく導入されました。履歴リストにセットできるエントリー数の最大値をセットできます。

f. 選択的な補完について、新しい実装や実装の置き換えをしました。最も注目すべき改良点は、よりよい`completions browsing'モードです。

g. 選択的な補完では、変数rl_menu_completion_entry_functionの関数が使われるようになりました。アプリケーションが選択的な補完を独自に生成できます。

h. 補完候補を表示するときに、パス名の前のほうを`...'で置き換える機能を用意しました。変数completion-prefix-display-lengthに値をセットして制御できます。この数値より長い共通の部分が`...'に置き換えられます。

i. 変数revert-all-at-newlineが新しく導入されました。有効にすると、accept-lineが実行されたときに、変更して実行していない履歴行の変更が元の状態に戻されます。

bash 4.0:数値列のブレース展開(2)

 Bash Hackers Wikiからほぼそのまま。

$ echo {0..10..2}
0 2 4 6 8 10
$ echo {a..z..5}
a f k p u z

 これ(↓)はバグかな。

$ echo {10..0..2}
0010 0008 0006 0004 0002 0000

「Shibuya.lispテクニカルトーク#2」に参加

 Lispコミュニティ「Shibuya.lisp」のテクニカルセミナーイベント「Shibuya.lispテクニカルトーク#2」が開催された。今回も楽しく話を聴けて、感謝。以下、受講メモ。間違いがあったらご指摘ください。

 今回は、前回の藤田さんの講演を受けてか、速度にこだわりのある発表やスピーカーが並んでいたのが印象的だった。LL言語より速くて当然、C++に負けたくない、とかそんな感じ。

開会の挨拶(naoya_t)

 Shibuya.lispの紹介。テクニカルトークのほか、逆引きCL/逆引きScheme/逆引きClosureのWikiなどの活動をしている。また、PerlのCPANのようなR6RSライブラリ集積所「spon」(仮称)を作ろうとしている。Lispの求人情報サイトLispjobs.jp(仮称)も作った。ただしまだ求人はない(笑)

 で、第3回テクニカルトークは7/4の予定(あくまで予定)とか。

Toy to Practical -- Mosh internals(ひげぽん)

 ひげぽんさんが、SchemeインタプリタMoshを、おもちゃのインタプリターから実用的なインタプリターまで改善していったという体験談。Lispインタプリタの実装の重要点を体験から語っていて、面白かった。

 まず、Lisp/Scheme処理系を作ったことがあるかどうか会場に尋ねると、半分ぐらいの人が挙手(笑)。

 IPAの未踏でMoshに応募したときのレベルは、ひげぽんさんいわく「おもちゃ」。SICPを見て作った簡単なインタプリターで、木構造を作って実行するもの。Pure C++で実装。とりあえず動くし、R5RSをほとんどカバーしていたが、とにかく遅い。fib(31)が1分以上かかるもので、実用にたえない。

 遅いとそれだけで使いものにならない、とにかくスピードが必要ということで、問題点をあらいだした。GCが遅い、再帰にネイティブスタックを使っている、環境のlookupが遅い、末尾呼び出しの最適化が不完全、算術計算が遅い、ほとんど最適化していない、など。たとえば、数をいちいちC++のNumberクラスのオブジェクトにしていたため、足し算でもnewしまくったし、それによりGCの遅さも重なった。

 対策として、木構造ベースからVMにしてみた。VMが速いらしいと聞いたぐらいの理由(笑)。有名な論文「The 3imp」を読んで実装した。3impに書かれていないところとしては、多値やトップレベル環境、Subr(外部手続き)、let(論文ではlamdaで代用しているがlet用のフレームを作って処理したほうが速い)、コンパイル時の最適化(Gaucheから借りた)などを実装した。

 このとき、いったんC++をやめてScheme(Gauche)でプロトタイプ「Mini Mosh」を作った。Schemeで作る利点、特にメモリやスタックを間違えてもSEGVしないのを生かして、50回ぐらい作り直した。VMが1400行、コンパイラが2400行。スタックレイアウトのデザインがいちばん大変で、図を書いて整理したり、作り直したり何度もした。

 Mini Moshができたとろで、C++に移植。VMは簡単だったが、コンパイラは大変。そこで、Schemeで書いたコンパイラをMini Moshでコンパイルし、そのコードをC++に1対1で変換するツールを作った。これでMini MoshとC++版で共通に使えるため、デバッグが簡単になったし、Schemeのままコンパイラの開発を進められるようになった。

 GCはBoehm GCを採用して速くなった。また、数値はタグベースのオブジェクトシステムで即値を格納するようにした。この時点でだいぶ速くなった。

 しかし、まだ「実用的」とはいえない。なぜなら、スピード狂の「ひげのお兄さんたち」2人が作った、GaucheとYpsilonがある。この2つが、ベンチマークでCやJavaに次ぐという実績を作り、基準を作った。

 そこでパフォーマンスチューニングのフェーズに。チューニングするうえで、グラフは絶対書いたほうがいい。ゴール(対Gauche、Ypsilon)が明確になるし、それに比較して変更がよかったか悪くなったのかがわかる。さらに、維持しつづけることも重要なため、一発でベンチをとってグラフを作れる仕組みを作り、グラフデータもリビジョン管理した。

 さらにプロファイラを作った。C++のプロファイラだと問題箇所がわからないので自作。mosh -pで呼び出す。LinuxのSIG_PROFから記録している。

 作ってみて気づいたことだが、起動も速い必要がある。PerlやRubyはここが速い。対策として、起動ファイルをあまり読まない、起動時に大きなメモリをアロケートしない(あとで増やす)、C++のstatic initializerを使いすぎない(コンパイラのバイナリフォーマットを決めてC++の配列として読み込むFASL方式)、というのをやった。

 あとは最適化。β変換、手続きのインライン展開(すごく効いた)、定数畳み込み(β変換との組みあわせで効いた)、ピープホール最適化、VMの命令融合、Direct threaded codeなど。

 これでもあの2つに追いつかない。そこで、GaucheやYpsilonのコンパイラが出したコードとひとつづつ比較した。その結果、ベンチマークでGaucheやYpsilonより速くなった(会場拍手)。たぶんいま追い打ちをかけられているところ。

 まとめとしては、実用的なインタプリタへの道は簡単ではなかった。あと、ひげをはやしていると速いコードが書けるらしい(笑)。

  • Q: letフレームの最適化はどこまで
    • A: let相当のlambda式もletフレームに
  • Q: 最後に速くなった要因は
    • Gloc。トップレベルのルックアップをキャッシュする

Common Lisp quote unquote(黒田寿男)

(「ブログでの言及はおひかえください」とのことなので、省略。あれは要約は難しいし)

R6RS Schemeの実装、syntax-caseなどについて(藤田善勝)

 最初にYpsilonの基礎を説明。スループットよりレスポンスを重視と言ってたのは、邪推すると、ひげぽんさんへの牽制かな(笑)。

 前半は、かなりキていた前回の発表の続きとして、メモリスタベーションの対応と「スピンロックに失望」からの話。

 Ypsilonの高速化の結果、メモリスタベーションが起きるようになった。Ypsilonではマルチコアを前提としており、リアルタイムゲームの定石として画面やゲーム本体、通信などのそれぞれをスレッドにして処理する。これにより、メモリ消費は格段に数倍になるため、メモリスタベーションの可能性が上がる。

 プロファイルをとってみると、ミューテックスで回収側とアロケーション側の激しい競合が起きている。そこでスピンロックをためした。システムに制御をうつさず、ユーザースペースで空回りするタイプ。システムコールのオーバーヘッド削減を期待したが、ぜんぜん役に立たなかった(笑)。

 それどころか、明らかに遅くなるテストプログラムがあった。どうも新しいメモリブロックを確保したときにフリーリストを作成するのに時間がかかるらしい。ここで競合は起きないはずだが。

 そこでバスのロックをうたがった。スピンロックは繰り返しコンペア&スワップでバスをロックする。どうやら、x86ではバスをロックすると、すべてのメモリ書き込みが終了するまで次の命令を実行しないようだ。フリーリストの作成には、1000単位の書き込みが発生するため、そこがボトルネックになるらしい。なので、ボトルネックの部分では同期を最小限にした。スイープフェーズで、ミューテーターとアロケーターがハンドシェークしていたが、一方的に依頼するだけにした。

 ここまでやって、paraffinsベンチマークで測定。2コアでCPU利用率190%を達成し、同時にきわめて短いGC時間も達成した。

 会場ではここでベンチマークをデモが実演された。ベンチマークといっても、ゲームでの動作に近い条件にするために、ブロック崩しをオートプレイするというもの。SDLとOpenGLの上で動き、音も出て、Macで600fps、Linuxなら3000fpsという本格的ものだった。

 後半はR6RS対応の話。R6RSの大きな特徴として、ライブラリシステムがある。が、IkarusやLarcenyのcyntax-caseは実装がおかしいと思ったので、自前でsyntax-caseを実装した。そしたらえらい目にあった。実はsyntax-caseって使ったことがなかったのだが、ドキュメントが少ない。さらにportable syntax-caseというデファクトがあり、動作が違うと文句がくるので、動作をみくらべながらバグっぽいところまで合わせた。

 syntax-caseを作ったおかげでシステムの内部をすべて掌握し、コンパイル結果のキャッシュなどもできるようになった。Dead object elimination、つまりプログラムの実行に必要のないオブジェクトを判別して自動的にそれらを解放する機構ができた。コンパイラもマクロ評価器もREPLも解放できる。その結果、lighttpd+fcgiでメモリ使用量を比べて、1.3MBから64KB未満に減った。それによりGCの負担が減ったことも大きい。

 まとめとして、ここまでにかなり時間を使った、と感慨。

私がLispでプログラムを書く理由(和田英一)

 和田英一先生による、エッセイ風の講演。ニコニコと楽しそうに話していた。タイトルを出したあと、「最初に結論を言ってしまうけど、慣れているから、好きだから。どう考えてもこれだから」と(笑)。

 まず有名なコンピュータ科学者たちによるLisへの称賛の言葉を引用。そのあと、自身のLispとの長いつきあいを紹介した。1958年のMcCarthyの論文から、60年に「Lisp 1.5 Programmers Manual」を冬の軽井沢にこもって読んだ話、1964年にIBM計算センターでLispが使えるようになった話、1965年にLisp処理系を開発した話、1973~74にMITでMacLispやFranzLispに触れた話。あと、2000年ごろにSICPの翻訳でSchemeをやった、ALGOL60が好きなのでSchemeも好き、という話(会場限定ネタ)。

 ここでLispの長所と短所の話。ここでは論点より、近山先生の1文字Lisp(carを矢印とか)や、evalquote in simple fortranという論文とかのエピソードが面白かった。あと、いわく「再帰を嫌う人もいるけど、こんなに気持ちがいいものはない」「長所にくらべれば短所はたいしたことではない」と(笑)。

 自身がLispを使う場面として、PostScriptのプログラムを生成するプログラムをLispで書く、と。インタビュー記事にもあった、PSで絵を描くという話で、端末に向かうと「%!」と打つ(笑)。が、PostScriptもいいけど、「似たようなパターンはLispで生成。ホモサピエンスなので」(笑)。

 ほかには、KnuthのTAOCP(The Art of Computer Programming)のアルゴリズムをLispで実装してみて本質をつかむ。ときどきは間違いをみつけて報告したり。

 ここで、正十二面体の絵を描くPSプログラムを生成するSchemeプログラムを紹介した。最初の1点から点と線、面を生成。全体を傾けたり、面の法線を求めて隠面消去したりして描画。「こう話すとなんでもないみたいですけど、試行錯誤して大変」と言ってたけど、いや先生、それじゃ「ボブの絵画教室」です(笑)。

 次に紹介したのが、KunuthのAlgorithm 7.1.2「Find normal lengths」をSchemeで実装する話。元の値から組み合わせをぜんぶ作ってコストを求め、コストごとに何個解があるかを求める。

 次は具体的なネタで、iPod Touch用に作った逆ポーランド電卓プログラム「Happy Hacking Calculator」をiPhone simulatorでデモ。泣く泣くObjective-Cで作ったのだけど、同じことをするプログラムをGauche上でも作った。Gauche版はサブルーチン定義などいろいろできて、いわくチューリングマシンぐらいの機能があるとか。「僕は冬休み中はこればっかりやっていた」と楽しそうに話していた。

 最後に、「Think recursively, write functionally」という言葉とともに、高階関数を使って偶数と奇数を分ける例を示していた。

  • Q: うまくやりかたが浮かばないときは
    • 考えて考えて、だめなときはやめる。気分しだい
    • けっこう電車の中で考えている
  • Q: 十二面体の例のコードで、点の生成が並んでいる箇所は、もうすこし抽象化できないか
    • 僕としては非常にきれいにできていると思う(笑)。解析幾何学の基礎に忠実
  • Q: いままでいちばんおもしろかった機械は
    • もちろんパラメトロン計算機。あれほどおもしろいものはない(笑)

LT:Schemeでbluetoothスタックを書く(奥村ゆうき)

 ここからはライトニングトーク。

 Wiiリモコン震度計をデモ。加速度センサーの値をMoshで読むというもので、通信プロトコルをすべてShemeで実装した。

 問題点として、SchemeのrecordはSchemeの外に持ち出せず、パケットの定義には使えない。そこで、define-packet-typeを定義した。マクロで展開しているが、プリミティブとして提案したい、と。そうすればUSB制御もTCP/IPもぜんぶSchemeでできる、という話。

LT:この木 なんの木 木になるS式 ~FUSEでS式ファイルシステム~(源馬 照明)

 FUSEを使ってディレクトリ構造とS式にマッピングした話。オートデモか動画だかで、次々にディレクトリやファイルを作ってS式になるところをデモしてみせた。同じディレクトリでの順番はnnn%を前置。Gaucheで評価もできる。実装はOCaml FUSEを参考にした。

 FUSEでやるコツとしては、ファイルを仮想的に作るのじゃなくて実際に作るほうが楽、というのと、openとcloseが対応するとはかぎらない、と。

LT:Lisperは怠け者の夢は見ないの?(山下伸夫)

 自動進行するスライドで、関数型プログラミングとLazy Evaluationを解説。関数型プログラミングはつまり、欲しいものをあることにしてとりあえず書くという、夢の記述。これをGaucheでやってみるとうまくいかない。Eager評価しないようにするため、lazySというLazy Evaluationのしくみを実装した。

 例としてエラトステネスのふるいやパスカルの三角形、シェルピンスキギャスケットをデモ。現実を見ろと言われても、夢と現実の区別なんてあったんだ(笑)、と。最後は「遅延評価はtaraiのためにある(わけではない)」。

LT:Cyanの現状と、これから(林 拓人)

 竹内郁雄先生の紹介で話題になった、Cyan言語を作った高校2年生が登場。自己紹介でいわく、言語マニア。

 Cyanは、Lispのエッセンスを多くとりいれた言語。インデントでブロックを表現(HaskellやPythonを意識)し、ブレースをもちいた記述も可能(Rubyを意識)。クラスをもたないオブジェクト指向で、すべてオブジェクトのメッセージ式。予約語が0個。

 S式ではない構文木がファーストクラスのオブジェクトで、Lispと同様のマクロもある。ファーストクラスの継続も持つ。

 ただし、実行が遅く、Hello Wordが4秒かかる(笑)。ちゃんとプログラムを書けるための言語にしたいと思うが、実は言語処理系しか作ったことはなくて(笑)、まず普通のプログラミングの勉強をするので、しばらくCyanは休みということだった。すごいなぁ。

LT:cl-irregsexp - the fastest regular expression library on the planet(John Fremlin)

 高速で理解しやすい正規表現システム「cl-irregsexp」を紹介。S式で正規表現を書く。ほかの言語の正規表現より速いというベンチマークを見せた。

 ただし、名前が問題で、s*xってのはどうかと思うので、名前募集中と(笑)。

LT:流行るLisp用Webフレームワーク(Gauche on Railsから学んだ事)(吉田裕美)

 肩書はGaucheファンクラブで、昨日考えました、と(笑)。

 Gauche on Railsを作った話を紹介。その後、公開したきり(笑)。ただし、Web媒体で記事を書いたらShiroさんなどに指摘をもらって、テンプレートエンジンなどは進化した。

 Railsは、メタプログラミングなどLispの影響のもとにある。次回Gauche.nightでGuche on Rails 2.0を発表したいと思うけど、みんなも自分で作っちゃったほうがいい、勉強にもなる、という話だった。

LT:よりよいLispプログラムを目指して(冬)(yhara)

 いわく「ライフハック」。プレゼンツールは自分の作ったBiwaScheme上のもので、S式で書いている。ほかにも、いろいろな言語を混ぜて使えるUnbabelで、どんな言語の仕事でもLispが使えるよと(笑)

 本題は、Lisperにいちばん重要な図形は「平行四辺形」だという話。初心者のLispコードは横にとびだすが、熟練者のLispコードは平行四辺形になる(笑)。

 そのため、ソースが平行四辺形になっているかどうかスコア付けするプログラムを作った(笑)。調査対象は、ひげぽんさんの日記(笑)。本当に時系列でそれっぽい感じのグラフになった。でも実は、Lisp以外のコードもある(笑)

 まとめは、このプログラムはRubyとLispで書いたけど、Unbabelで一つにできるね、と(笑)。

修正2009-03-01:誤字修正。ココサブさんありがとうございました。

 | HOME | 

Categories

Recent Entries

Recent Comments

Recent Trackbacks

Appendix

emasaka

emasaka

フリーター。
連絡先はこのへん

Monthly