Practical TLA+はとてもいい

はてなダイアリーはてなブログの区別はついていなかったのですが、いままでつかってたほうがなくなるらしいのでもう一つの方に引っ越しました。

で、久々の記事です。

 

www.apress.com

そういえばこのブログはTLA+ネタを中心に書いてたこともあったな、なんてすでに思い出になりつつありますが、本が出たというのはメーリングリストで前に見たものの、すっかり忘れててようやく購入しました。

今8章まで読み終わって、残るは3章。

この本は、とてもよいです。学ぶ内容は超基本的なのだけれど、そもそもTLA+の基本を学ぶのが超とっつきにくくて、これまでも何度も挫折していたので、この本は当時生じた疑問をすべて答えてくれる内容です。

普段使わない新しい言語を学んでも、殆どの場合は文法の対応付を覚えるだけだったりすることがままあるのですが、TLA+についてはそもそもプログラミング言語ではないので、考え方をガラッと変える必要があって頭のリフレッシュになります。

じゃあ実際これでPracticalな何かをかけるかというと別問題。。

 

ということで、おすすめ。

試して理解 LINUXのしくみ を読んだよ。

@satoru_takeuchiさんという方が書いた本。ダジャレをつぶやくアカウントだと思っていたのだが、Linux系のすごい人らしい。

で、せっかくなので書評というか、感想ですね。

Linuxへの深い理解に基づく解説と、丁寧な実験結果を用いて、OSの基礎を学べる本。OSを学ぶにあたっては、これまで「簡易OSをつかったテキスト」か、「特定のOSの詳しい解説*1」の2通りだったのだけれど、この本は新しいアプローチ。

この本がとても向いてるだろうな、という人は、「OS(or CS)を体系的に学んだことがなくて、Linuxを使ってきた」という人だろうな。僕は対象読者から若干外れているかもしれないけれど、Linuxなんにも知らないので、ふむふむと勉強になる点が多々あった。

メモリ管理、記憶階層の章はとてもよかった。秀逸です。(図05-47ェ…)

ファイルシステムとストレージデバイスは仕事柄僕は評価する立場にないけれど、ファイルシステムはちょっとアドミン側に寄りすぎたかな?すくなくともファイルシステムの3つめにクオータはいらないと思うし、基本的なinodeの構造とか、ハードリンクとか、ファイル名はディレクトリが持つことが多い、とか、そのへんはあっても良かったかも。

もう少し詳しくLinuxを知りたいな、と思わせたら多分この本の狙いとしては成功で、そう考えると大成功かなと思いました。

*1:ちなみに、Solarisインターナルはとても良い。今となっては過去の遺産になってしまったのでこれから読む人はいないだろうけど。

学院の地理の小川先生

すでに故人となってしまったが、高校時代のインパクトの強い先生の一人、小川先生。

授業は基本的に成立しておらず、先頭中央の席に座っている学生と世間話をして一年が終わっていた。一応テストの範囲は知らされて、いざ期末テスト。問題用紙が配られ、一問目を読む。選択式穴埋め問題だ。

[ ] 世紀のイギリスでは産業革命が起こり、なんとかかんとか。

そこで選択肢に目を移す。20個近い選択肢に、数字が"18"の一つしかない。ここで思わず吹き出してしまった。

ネットで検索したところ、今や小川先生の情報はmixiのコミュニティしかないではないか。そこで、権利関係面倒だが、ここに保存することにした。

一応リンク: http://mixi.jp/view_community.pl?id=358223




「次は中央線が出る」って言われてみんな新宿から八王子まで必死になって覚えた。
が、出たのは遥か遠く山梨とかの山、湖。。。15年くらい前だけどかなりインプレッシブ。


「学院の敷地の横を流れている川の名前を書け」というのがこれまでで一番の難問だったときいています。

答えは「石神井川」だそうです。。。難しいですね。らしくない(-。-) ボソッ
ちなみに「小川」でも正解になったそう。やっぱりこうでなくっちゃ。


小川先生、大塚に住んでいたらしく、「僕は大塚を経由で通ってくる人には10点増としている」とのことでした。大塚で乗り降りしなくとも、通り過ぎるだけでOK.ただし、自己申告が必要だったような。

家から学院までの道のり。バスの停留所の名前でもOKでした。


北米大陸にある、世界最大の経済大国は(  )合衆国である」の括弧を埋める問題が出た気がします。


こんな問題だったような。確か2年生の時だったので1986年ってことですね。勿論選択肢にひっかけのような迷う項目はありません。特に3.などは「大」を入れると日本語としておかしいので国語力も問われる高度な問題でした。

【選択問題】
1.北太平洋の南西部に発生する熱帯低気圧が協力に発達したものを【  】風という。
→「台」が正解

2.アメリカ合衆国とカナダの国境地帯に存在し、周辺は自動車を中心とした世界最大級の工業地帯となっている湖を【  】湖という。
→「五大」が正解

3.日本の国土はアメリカより【  】さい
→「小」が正解。

【自由記述問題】
北朝鮮と韓国の違いを書け。
→回答例:北の方が寒い。韓国はキムチが美味い。


西武新宿線の急行停車駅を書け」という試験問題があったとの伝説を聞いたことがあります。


私が小川先生に習ったのはもう25年くらいまえの話しだけど、西武新宿から上石神井までの駅の個数を書けという問題がでました。私は新宿方面から通っていいたので、簡単に答えられましたが、反対から通っている同級生は、答えに困り、急行で4個と答えていました。何点もらえたかは忘れてしまいました。あと、私たちのころの伝説は「山手線の駅を3つ書け」という問題があったのですが、小川先生の最寄駅・大塚駅を書くと高得点だというものがありました。



みなさんの場合よりかなりまともでした。「上石神井駅から出ているバスの行き先で、中央線の駅はどこか、漢字で書け」
荻窪、が正解。でも「窪」が書けずに久保とか書いて出した。

「アフリカにある川の名前を書け」
小川自筆の問題用紙の文字が汚すぎてよくわからず、アメリカの川、と読み違えて

コロラド川

とか書いて試験終了。答案用紙をふと見るとアフリカと書いてあるようだ。でもめんどくさいのでそのまま提出。どう回答しても一年間いつも87点だった。


10年前、幸運にも小川先生の最後の年に入学しました。少し前に学院長(伴さん)に叱られたとかなんとか仰っていたような気がします。なので、極めてまともな試験だったように記憶しています。

1学期 「何処何処の国は( )気候である」が3〜4問くらい。

2学期  いつもの調子の授業の最後に「試験範囲は教科書120頁分だな」
    →学院生「えっ!?」
    →試験問題「スイスの使用言語を答えなさい」
     
     ロマンシュ語が書けませんでした。

3学期 「君の家から学院までの道のりを地理的に説明しなさい」


・・・この問題を遺して、小川先生は退任されました。

ちなみに、私が学院時代に指導を受けていたOBの方(30年前くらい卒)によれば、当時の問題は「東海道線品川駅を出て、最初に右に見える山の名前を答えなさい」というものだったそうです。


Q: 下記の空欄を埋めよ。
 上石神井: 西武新宿線の急行停車駅がある。 ( ) があるため、毎日君たちがやってくる。

正解は、「早大学院」でも可だが、「小川先生の授業」などと書くと加点があった模様。


確かに、答案用紙に「100点下さい。」
と書いて100点もらってた奴がいたよ。


初めまして、やはり小川先生は神だったのですね。
僕は小川先生が学院で教鞭?を取られる最後の年に入学したのですが、
入学後まもなく授業中に菓子を食べてたら
「おいお前何食ってンだこっちこい」と言われ恐る恐る菓子を差し出しました。
小川先生は一口それをほおばると、「よし、お前は+10点だ」と言われました。
後になってこれくらいは日常茶飯事であることを知りました。

定期テストで思い切って白紙で出したら80点ちょっとくらいもらえたことや、テスト問題には自宅から学院までの道を書け等がありました。


彼は中央の1番前の生徒にだけ絡んでたような気がする!それ以外の生徒は、トランプや麻雀してたような!彼の試験は、自分の地元について書けみたいな感じだったかな!


驚くなかれ5、6時間目が連続して地理で俺らよく小川に交渉して5時間目で終わらしてクラス全員で早退してた。小川は「わかった。そーと帰れよな。」といって優しく了解してくれた。だって、あんな馬鹿な授業2時間も連続して聞くのやだもの。


私の時に出た期末の問題は”南極海に生息する世界最大の哺乳類はナガス(?)である”というもので、?を答えるものだった。引っかけか、あるいは何か特殊な答えがあるのかと思い、少し悩んだのを覚えている。でも?の答えはやはり”クジラ”でした(笑)。

一度、何やら巨大な世界地図らしきものを持ってきたことがあり、「おぉっ!」と驚きと期待を抱いたことがありましたが、結局教卓の横に置いたまま、一切使わずじまい。いつものように、お気に入りのT居くんと、彼の自宅のある地域の話をするだけでした。

普通の人でもわかる Paxos

スライドにまとめてみたよ。Tweetは流れて消えていくし、こっちの日記は訪問者ほぼ0なので、いずれにせよネットの大海に消えてく感じはありますが、一応ログとして。

http://www.slideshare.net/tyonekura/paxos-63835103

分散プログラミングモデルおよびデザインパターンの考察

分散システムバトンが回ってきていないので、僕も書いてみることにしました。が、先生方とは違い、私は全くの素人なので、俺俺分散論で行きたいと思います。

はじめに(予防線)

私は分散ファイルシステムを開発している部門で働いていますが、幸か不幸かあまり詳しいことは知りません。実際のシステムは私より10倍から100倍頭のいい人達が書いていて、私はそれをトントン叩いてチェックしているだけです。なので、この記事は特定の製品について語ったものではありません。

じこはおこるさ

事故がほら起きるよ 突然さ

運がない時はしょうがない

なんとかしよう

事故がもし起きたら

落ち込まないで

うまくやれるようにがんばろうよ

事故は起きるものさ

神歌ですね。これだけでこのエントリー終わりでいいんじゃないかって思ってきましたが、一応続けますね。

事故と言うとあまり聞こえが良くないので、エラーに変えますか。

エラーがほら起きるよ 突然さ

運がない時はしょうがない

なんとかしよう

エラーがもし起きたら

落ち込まないで

うまくやれるようにがんばろうよ

エラーは起きるものさ

と、いうわけで、トーマスで言えば、大事なのは死人が出ず、ソドー鉄道が倒産もせず、トップハムハット卿に怒られるくらいでいこう、ということですね。(たしかあまりにも悪くてコンクリートで固められた汽車が居た覚えがあるけど)

分散システムも、大体の場合は、「エラーが起きてもがんばろうよ」というスタンスです。いついかなるハードウェアエラー、ソフトウェアが起きても、なんとかしないといけません。処理が冪等であればリトライすればいいですし、そうじゃなくても、データ不整合を起こさない範囲でできるだけ頑張る。パニックを起こしていいのは、「やばい、今俺が死なないとデータが壊れる。メガザル!」という時だけです。

限界はある

設計上考慮する限界というのはあります。そして、設計上考慮しない限界というのもあります。昔「N+4構成なら4ノード同時に壊れてもデータを守れます」と説明したら、嬉々とした表情で「じゃあ、5台同時に壊れたら?」と聞いてきた見込み客がいましたが、「はあ、データは消えますね。それがなにか」というのをもう少しソフトに答えた記憶があります。まあ、そういう論外なのは脇に置くとしても、開発リソース、テストリソース、そしてなにより起こる可能性、起きた場合の対象方法を考慮して、どこまでやる必要があるかは商用システムの場合(そして、本来はOSSだったとしても)考える必要があります。また昔話になりますが、他社のエンジニアが「ここでSHA1をindexにしてデータを書いて」といったので「ぶつかった場合は?」と聞いたら、「え?ぶつかんないよ多分」と答えられたことがあり、「いや、それはうちの会社だと無理」と思ったことがありますが、まあ、例が悪いですね。

ビサンチンとか知らんけど。

別に論文の査読をしているわけではないので、実システムを組む上でビサンチン問題への対処を問われてもこまる、といえば困るのですが、現実問題として、アーキテクチャでどうにかするべきところと、実装上の工夫で緩和すべきところと、コンポーネント側のテストで何とかするべきところがあります。一番困るのは、ディスクに書いたら「ちゃんと書いたよー」と言ってきたのに、書いてない、とかですね。「歯磨きしたよー」といってるのに磨いてなくて、虫歯になった、みたいなやつ。定期的に親がちゃんと磨いてるかチェックするか?でも100万回に1回だけ磨いてなかったらどうする?それとも、それも障害として扱えるようにするか、もしくは嘘つきかどうか売る前にテストするか。アプライアンスの場合、「それは部品が嘘ついてました」じゃ済まないから、できるだけテスト。で、その結果どうなるかというと。。みんな、パソコンを買って、ドライブファームウェアのアップデートってしたことあります?無い?そうですか。それはラッキーですね。バグがないドライブを買ったんですね、多分。

現実的な分散システムを考えると、ビサンチン障害というのは概ね周辺ハードのファームウェア問題といってよいです。なぜなら、ノードXとノードYが異なるソフトウェアで動いていて、一人が嘘をつく、というのはあまりないから。(例外は、バージョンアップ時のミックスバージョンの挙動。少々趣が異なるのでここでは見なかったことにする)同じソフトウェアの中で一つのインスタンスが嘘をついてるケースは、どちらかというと「ソフトウェアのバグ」で片付く気がする。これは単なる気持ちの問題なので技術的な分類ではありませんが。

で、NICとか、Switchとか、ドライブとか、そのへんになるんだよね。いやー、辛いね。

一貫性とか

用途によって、実システムに必要な一貫性というのは変わってきます。入出金管理では1円単位であわないと困るかもしれません。適当でいいよ、という用途もあるでしょう。そして、その間も。クオータ(容量制限)システムにおいて、もしユーザーがその制限に対してお金を払っていたら、常に正確な容量を把握していないといけないです。が、全ユーザに追加で1GB余分に設定しておけば、一貫性がズブズブなシステムでもユーザが文句を言ってくることは無いです。が、もしそのユーザAが他のユーザBにシステムを提供していたら、余分な追加はユーザAにとって嬉しくないので文句が出ます。そういう微妙なバリエーションが色々出てきます。なので、誰も文句が出ないところはうまくやりましょう、と。それによって実装の複雑さや速度が変わってきたりします。

分散プログラミングモデル

分散してプログラミングするの?github便利だよ。

テストコードの品質

はじめに

私はテストを書くのは素人なので、「こいつなんにもわかってない」と思われるかもしれませんが、そういう人はスルーしていただければと思います。また、テスト駆動開発とか、アジャイルとか、いまいちわかっていません。この記事は、あくまでも分散ストレージをテストしていく中の一要素として、テストコードを見た時に、私が日々感じていることをまとめてみます。以下、関数レベルのunit testではなく、Integration test用のコード、くらいが対象です。

1.なにが最も重要か

製品コードの品質といった時、分散ストレージの場合は、1番は「データを壊さないこと」。随分離れた2番は「サービスが落ちないこと」です。その後、コンポーネントによって、性能や、拡張性や、可読性や、その他色々入ってきます。

テストコードは「バグを見つける」ためにあります。もう少し分類すると、「何かした時に、期待の動作をしていること(リグレッションしてないこと)」「なんかよくわからないことをした時に、壊れてないこと(stress, fuzzer, random walk)」がFSのテストの2本柱です。前書いた時は3本柱だった気がしますが、忘れました。なので、1番は「バグを見つけること」なのですが、それって項目に落とし込めてない気もするので、あえてひねり出すとすると、テストコードの品質項目で1番重要なのは、「そのテストが実行されること」です。素晴らしいテストやツールを書いて、それが書かれた後に二度と実行されないのが最悪のパターンです。意外とこれ、多いです。

その他は、重要な順に:

  • Correctness ・・・ False positive*1, False negativeが無い。
  • ロギング、再現性・・・エラーが起きた時に調査できること、再現できること
  • 可読性
  • バレージ
  • 性能
  • 拡張性

2.性能

製品コードでは、例えば O(N^2)のロジックを最適化してO(NlogN)にできたらすっごく嬉しいです。もしくは、Critical pathが10%早くなったらとても嬉しいです。が、テストコードは、直感的な実装で最適化された実装をチェックしたい場合が多いので、O(N^2)で構いません。別にテストを書く人がアタマが悪いのでN^2になっているわけではありません(そういう場合もあるだろうけど)。テストの性能は、そもそものテストの切り口や、パターンのピックアップで、現実的な時間内に終わらせることが重要で、コーディング中にテストコード自体の性能を考えることはあまり無いです。

3.スケーラビリティ、拡張性

将来の拡張性を考えて風呂敷を広げすぎたテストツールは、将来にわたってゴミを抱えたまま、
数年後に他のツールで置き換わることを待つことになります。製品コードが拡張性を考えないといけないのは、アップグレードをサポートする必要があるからです。既存の顧客が、既存のストレージを、データを保持したままアップグレードする。そうなると、何か一つ変えようとしても、昔適当に設計したものが足を引っ張ることになります。テストツールは、今その時点でベストであることが大切です。

スケーラビリティーも、製品コードである日リンクリストをツリー構造に変えようとしたら、うんざりするようなアップグレード計画が待っているわけですが、テストコードは、その時必要なスケーラビリティを定義すれば十分です。

4.マクロ病

製品コードを書く人(うちだとCコーダー)は、特にMAGICナンバーを嫌う傾向があります。

何かの処理
sleep 10 # 適応されるまで待つ
次の処理

これを、APPLY_SLEEP_SEC=10 と定義せよ、みたいなやつ。もっというと、4 * 1024 * 1024 * 1024 を
GB=1024*1024*1024 (or 1 << 30) として4 * GB とせよ、みたいなの。個人的には、単にテストの見通しが悪くなるだけなので、
「マクロ病」と呼んで無視しています。とくに、コマンド実行の run(cmd) という文で、cmd を切り刻んだロジックの集合にして喜ぶ人たちがいますが、同意しかねます。

5.スタイルは守る

うちだと Cは style9, pythonはPEP8, で、それぞれ少しカスタマイズされてますが、特別な事情がない限り、これを守るのは絶対です。逆に、Style Guideに定義されていない「好み」の部分をCRで指摘するのはあまり好きではないです。もしその好みが全社的な標準なら、Style Guideで定義されているべきなので。で、Style Guideを守ったうえで、最低限の労力で、必要最小限のテストをまず書く、というのが大事だと個人的には思ってます。

6. エラーハンドリング

製品コードはエラーハンドリングの塊なので、たとえば、pythonでいえばスタックトレースがベチャッと吐かれることはまずないですし、panicしたら大変です。テストコードも頑張ってエラーハンドリングしちゃう例をよく見かけますが、単に必要情報をログに残してスタックトレース吐いて落ちたり、Kernel側のテストであれば、panicするほうが嬉しいです。エラーハンドリングに関しては製品コードとテストコードは真逆のスタンスになります。

7. 再現性とランダム性

再現性を高めるには、どういう操作がどの順番で、どのタイミングで行われたかを記録するか、事前に計画する必要があります。ランダム性を高める上で、I/O Aと I/O Bが、ほぼ同時に実行されて欲しい、という場合があります。ほぼ、というのは、Aがちょっと早い場合と、Bがちょっと早い場合と、AとBが本当に(物理的には本当に同時はなくても、まあ、現実的なレベルで)同時に実行される場合。原子時計でも積んでいないとそこは不確実性に任せてストレステストを書くこともあります。その場合は、エラーが起きた時にできるだけ絞り込む工夫はしますが、100%の再現性は求めないことになります。何事もバランスです。

*1:必要悪として許容する場合もある

TLA+本、CHAPTER 3

結論から言うと、山火事問題はまだまだ荷が重い課題でした。これまでPlusCAL中心で来ていきなりTLA+の複雑な記述に挑むのは結構辛い。

なので、一旦TLA+本に戻ります。Chapter 3です。

送信機、受信機がval(値受け渡し用)、rdy(SYN用)、ack(ACK用)の3本の電線でつながってるとして、送信機はvalに値を入れると同時にrdy(0/1)の値をflipし、受信機がackの値(0/1)をflipしてrdyとackがおなじになったら、送信機は次の値を送れる、というシステムの記述です。言葉だけだとわかりにくいですが、テキストを読めば単純。

前置きとして、どのレベルまで抽象化すべきかは経験で学んでいくしか無いから頑張ってね、とランポート先生のありがたいお言葉。

3.1 The First Specification<執筆中>