指定バイト数ぐらいの長さの文字列を読み込む方法

IO から指定したバイト数以内の長さを読み込みたいが、多バイト文字の途中で切れてしまうのは嬉しくないのでそういうときはもう少し読む、というような処理を書きたいことがよくある。 これ、というメソッドは見当たらないので仕方がないから自前でバッファリングしたりしてなんとかしていたのだけど、 IO#gets にそういう機能があることが分かった。

IO#gets はseparatorに nil を指定するとseparateせずにファイルの最後まで読む。それからもう1つ、読み込むバイト数の上限を指定できる。この上限指定は1.9ではもちろん多バイト文字を壊さないようになっている。だからこれらを組み合わせて io.gets(nil, limit) とすると希望の動作をする。行操作でもないのに gets というのはちょっと思いつかないね。

余談

なぜ突然こんなのに気づいたのかというと、今書いているライブラリの関係で IO の挙動を細かくみているのだ。

IO クラスはもともと結構大きなクラスだったのだが、Ruby 1.9になってM17Nが入ったためにエンコーディングがらみでさらに挙動が複雑になった。もはや StringIO みたいに自前で IO もどきのクラスを書くのは容易ではない。そこで IO もどきを作るのを助ける IOable というライブラリを書いている。

性的保守主義と性同一性障害の親和性

性同一性障害の典型例、つまり 自己の性的同一性を明確に認識——身体との間には齟齬があるにせよ自分の人格の中核を成す性別には疑問がない——し、ヘテロセクシュアルで、性的自己認知と性別役割に葛藤が無く、その現象を「性同一性障害」として医療化することを受け入れている人にとって性的保守主義は甘い誘惑だ。

性的保守主義と抑圧

ここで性的保守主義とは、最も典型的な男、女という性に性現象のすべてを回収するものとしよう。彼らは例えば社会での男女の性別役割を自然で当然のものと考える。そこから外れる人を「男なのに○○」「女なのに○○」と自己の属する多数例を基準に評価する。同性愛は彼らに言わせれば例えば「女と寝るように男と寝る者」(レビ記18:22)だ。私が知人の男性同性愛者を見たり資料を読んだりする限りにおいて、これはたぶん不当なことだ。彼らの関係性が「異性愛ではない」のは自明なのに、なんで何もかもが異性愛と同じだと考えるかなぁ。フィクションによくあるような、レズビアニズムに男根主義を期待する心性もそうだし。

さてさて、これら性的保守主義は非典型的な性現象のあり方を抑圧する。それらを不自然であると言って攻撃したり、さも選択肢があるかのように「しかるべき場所にいるならいいけど、堂々と一般の場に出てくるな」という。特定の属性を持つが故に職業選択の自由を剥奪されたり自己の心情を表現することを禁じられたりすることの、どこが選択肢なのか。それはゲットーだ。だから、こうした保守主義は非典型的な性のありかた——性的少数者にとって脅威である。性同一性障害の典型例にとっても、基本的には。

誘惑

ただし、性同一性障害の典型例についてだけはこの抑圧からの逃げ道がある。

もともと性的保守主義は性差の本質主義と親和的だ。男と女は生まれつきある程度違っていてだから女がその母性によって子どもを育てるのは自然なことだし、男のほうが数理的能力に優れていて女のほうが感性が繊細で、とかいう。ここで、現代においてはこうした本質主義は、男女では遺伝子やそこからの脳機能の表現型が異なりそれが支配的なのだという主張に等価だ。この主張はある程度までは真実だろうけれども、本当に数理的能力やら言語能力やら、まして育児家事の分担までここから自然に導かれるのかどうかは議論を要する。性的保守主義はこの議論において高次能力や社会的役割にいたるまでかなりの程度自然に導かれるという立場に親和的なのである。そしてここに性同一性障害が登場する。

高次の精神機能の性差が生物学的必然であるとすれば、逆説的にそこには必ず性同一性障害がなければならない。人間の精神、例えば性的自己認知のような複雑な機構が生物学的過程において一件のエラーもなく形作られるなどということはほぼあり得ないからだ。だから性差が生物学的必然ならばエラーによって必ず性同一性障害は発生し、それは本人の選択ではないし、本人に何の責任もない。 つまり性同一性障害の典型例は、性差本質主義を採用すれば厄介な性的保守派からの否定的な視線から保守派自身の主張によって逃れることができる。さらに保守派にとってもメリットはある。性同一性障害者が自己認知と異なる身体や性的役割を受け入れようとして失敗してきた葛藤の深さをして「男女の本質的差異の大きさ」の論拠とすることができる。「" ブレンダ "を見ろ、性同一性障害もそうだ。ただ表層的な身体の形に合わせて自己同一性と異なる性になろうとしても無理だったじゃないか。男は男、女は女、生まれつき決まってるんだ」というわけだ。

性同一性障害の典型例にとってこれは魅力的な誘いである。得られるものは性的保守主義の抑圧からの脱却である。対価は他の後天的・文化的(である可能性のある)性的少数派あるいは男女にくっきりと線を引くことを阻む例、たとえば趣味的異性装者や性的自己認知が男女いずれでもない人に対して保守主義と一緒になってに石を投げることである。つまり性同一性障害の典型例はある種の本質主義に与することによって、性的少数者への抑圧を放置したままに抑圧される側からする側に移ることができる。

性差の本質主義がどの程度真実かは議論の余地がある。そこで本質主義を主張するのは自由だし、主張する人がたまたま性同一性障害であるということもあるだろう。ただそれは非典型的な性現象に対しての差別性を肯定しないはずだ。そして、性同一性障害者が自己の信念に寄ってではなく単に生きるのに楽だからという理由で保守主義の抑圧に荷担するとしたらそれは悲しいことだ。

良い相続人であるために

翔泳社の「君のために選んだ1冊 ソフトウェア開発の名著」という企画に寄稿を依頼されて、以下のような文章を書いた。ブログ等で公開して良いとのことだったのでここに公開したいと思う。 この企画は他の人の分を読むのが楽しみだ。早く本ができあがらないかな。

ちなみに「 きっと何者にもなれないお前たちに告げる 一冊」というタイトルを最初に思いついたけれど、長く読み継がれる本であってほしいという企画の趣旨を鑑みて流行のネタを使うのは避けた。

yuguiがレガシーコードに絶望した人に贈りたい一冊 - 『レガシーコード改善ガイド』

レガシーコード改善ガイド (Object Oriented SELECTION)

レガシーコード改善ガイド (Object Oriented SELECTION)

振り返るに私のキャリアの大部分はWebアプリケーション業界のレガシーコードとの戦いであった。 多くのシステム開発者にとって全くのゼロからシステムを開発する機会よりも既存のシステムの拡張や保守に携わる機会のほうが多い。それは私にとっても同様であった。

これは恵まれたことであった。私は先人の遺産(=legacy)とともに仕事をしてきた。 現在私が暮らしている業界自体を作り出した黎明期の開発者たち、あるいはやんちゃな天才ハッカーたち、彼らの仕事に触れることができた。 Webアプリケーションの黎明期には出遅れた、論文を書けるような先端技術に通じているわけでもなく、競技レベルの優れたコーダーでもない平凡な私が彼らと同じ開発の場に立つことができた。

ここで問題は、それらのシステムの多くがいわゆるレガシーコードであったということだ。 適切なデザインのシステムにおいて、ある変更をするとどのような影響があり得るかは自明である。あなたがそのシステムを知って数日しか経っていなくとも自信を持って変更を行うことができる。しかしレガシーコードにおいてはそうではない。多くの情報が目に見えない形で埋もれていてそのすべてを知ることを要求し、新参者の貢献を拒んでいる。 レガシーコードは変更のコストを増やすのみならず、見通しが悪いためにリスク評価自体を困難にする。

先駆者や天才たちは前人未踏の領域ですばやく動いて生き延びるためにこのコードベースを作り出した。あるいは抽象化や分割統治、すなわち複雑と多量を凡人が取り扱うための工夫を必要としない故に。 そして先駆者にだけ通じる暗黙知を前提とした拡張や、天才が次の挑戦を求めて旅だった後の担当者による生半可な保守行為がレガシーコードを静かに腐らせていた。 拡張しづらく、複雑で理解に苦しみ、ちょっとした変更が予期せぬ副作用を産むレガシーコードに私は絶望した。 あなたもまたレガシーコードに絶望してきたのではないだろうか。そうでなくともあなたが先駆者や天才でないならば、いつかレガシーコードに出会いその中で開発することだろう。そんなときにどうすれば良いのか。

最悪の選択はレガシーコードに向き合うことをやめて、適当に目に付いたところに拡張を施しては壊れませんようにと祈ることだ。そうした半端な仕事こそがコードをますます腐らせる。それは先人の遺産を食い潰して生きることに等しい。その果てになんの望みがあるだろう。

いっそ初めからやり直したくなることもある。レガシーコードを捨てて新たに同じ機能を書き下ろす。それが適切なときもある。けれども先人の知恵が詰まったそのコードを、大体は完璧な仕様書など存在しないというのにどうやって漏れなく再実装するのか。こうしたリスクを取れないこともある。

だから、朽ちていくレガシーコードに出会ったならばそれを殺さぬまま再生に導かねばならない。 生まれたてのシステムのように適切なモジュール化を施せ。考古学を行なって暗黙の知識を発掘しコードに明示化せよ。 『レガシーコード改善ガイド』はこうした作業をなすための知恵を説く。

まず本書は独特の意味でレガシーコードを定義する。「テストケースの無いコードはレガシーコード」である。これは過激なようだが上手な定義だ。 適切にテストケースを書こうとすれば自ずとシステムは適切にモジュール化され、前述のような欠点はなくなる。つまりまだテストケースのないシステムはそのような欠点を抱えている可能性が高い。

次に、いかにしてテストケースを取り付けるか、それから著者が「テストハーネス」と呼ぶテストでソフトウェアを固定してリファクタリングすることを述べる。 更にいくつもレガシーコードでの開発によくある状況を挙げて対処法を教える。

私はレガシーコードを多く見てどのようなときに何が悪い設計なのかを知った。多くの本を読んでは実践し、あるべきソフトウェアデザインを考えた。 しかしレガシーコードをどうやってあるべき姿に導くのかは手探りを続けていた。そんなときに本書を読んだ。自分のやり方が正しかったことを知ったり、思いつかなかった大胆なやり方に息を呑んだりした。

あなたもレガシーコードに出会うだろう。そんなときに本書から知恵と勇気を得て欲しい。

rubykaigi.orgの歴史

whoisしてみると分かるようにrubykaigi.orgドメインは現在私が所有している。

元々RubyKaigiは独自のドメインというのは持っていなかった。その頃、確か高橋さんか角谷さんにだったと思う、rubyconfみたいにドメイン取らないのかと聞いてみた。取るつもりはないというお答えであった。思うに、当時は今にも増してイベントの継続性は神のみぞ知るところだったわけで、ドメインを取ってそこで継続的にサイトをメンテナンスするのはそぐわないということだったのだろう。

それにしても、RubyKaigi 2007が行われようかという時点で既にruby-talkruby-coreでも"RubyKaigi"という文字を目にするようになっていた。と、すればいずれここに目を付けるスパマーもいるだろう。みすみすこのブランドをスパマーにスクワットされるがままに放置しておくのは惜しいように思われた。そこで私が勝手にrubykaigi.orgを登録してRubyKaigi 2007のサイトに転送するように設定して運用していたのである。

その後、実行委員会は方針を変えたようで角谷さんから「rubykaigi.org持ってるよね?」と連絡があった。必要ならいつでも引き渡すよーとは言ったのだけれどもなんか特に必要にも迫られなかったので、結局所有者兼ドメイン設定担当者みたいな形でずるずるとここまでやってきている。角谷さんから要請があるとその都度私がDNSレコードを変更したりしていた。

この度、日本Rubyの会が法人格を取得すると言うことで、関係する個人ではなく会そのものがドメインを所有することもできるようになる。そこで「近いうちにrubykaigi.orgは日本Rubyの会に引き渡そう」という話をしたりもした。それで、思い出話を書いてみた。

Googleによるトランスセクシュアルへの配慮の事例

先に報告した ようにこのたびGoogleに転職した。

ここで、Googleトランスセクシュアルへの対応に感心したので書いておく。

履歴書

まず、US系の企業としては当たり前の慣習であり法的自己防衛でもあるのかもしれないけど、履歴書に性別を書かされない。

背景

履歴書に書くべき何か簡潔な性別の記述というものが存在するのであれば私にとっては問題ないのだけれども、実際のところはそうではない。

この話は 以前も書いた

人は性別という単一の二値属性が存在することを信じるが、残念なことに自然はそういう風にはできていない。人の信じる仮構は単に、少数者を例外として排除してしまえば幾つかの性別要素にまつわる量が成す数ベクトル空間について2つの同値類が存在し、それを「男」「女」と呼べるというだけの話に過ぎない。

残念なことに最初に省いた特異点を含めると単純な同値類は成立しない。都合の悪い例から逃げずに一般にこの空間の性質について話をするならば、性別というものは「今どの切り口におけるどういう定義での性別を必要としているのか」「仮に性別属性を二値に落とすとして、二値の境界をどこに置くか」を与えなければ記述が困難だ。

上掲記事のように数ベクトルを成す個々の値についての話を羅列して、これが私の性別であると述べることは可能かも知れない。しかしおよそ、一般に簡潔な表記が得られるとは限らない。そして見ての通り、私が試みた自己の記述は簡潔ではない。あれでも、あんまりみんなを煩わしてはいけないと思って多少の不正確は覚悟の上で若干の情報をそぎ落としてあるんだけどね。 *1

大抵の書類は受付者が必要としている性別の定義を書いていない。だから私は上のようなことを毎度毎度考えたあげくに、この人はどの定義における性別情報を必要としているのだろうか、私にとってはこれは面倒で下手をすれば性別違和感を喚起される甚だ不快なことなんだけれども、そもそも私の辛抱に見合うほどこの人はこの情報を必要としているのだろうか、また、この場面においてこの切り口の性別情報を提示させることは政治的に適切な態度だろうか *2 と悩むことになる。

Googleの場合

Googleの採用ページ には、「性別、生年月日、年齢、門地、兵籍、国籍、個人識別番号等を書くな」とある。

これらは確かに採用に当たって能力を測るには必要がない。またこれらの情報を知らなければ、性差別をするつもりなのではないか、年齢差別をするつもりなのではないかと勘ぐられずに済む。合理的である。

以下で見るように入社前後の手続きで性別にまつわる何らかの属性情報を必要とする局面は確かにあるのだけれども、そんなものは血圧やコレステロール値と同じく、採用を決めて必要になってから必要な限度において収集すればよい情報である。

労務系

社会保険に健康保険、雇用における男女共同参画の資料やらなんやら、労務系の資料では「法律上の性別」が必要となる局面が存在する。

Googleでも入社するとこれらの手続きのために必要な情報を提供するように求められる。今回私はこの段階になって担当者に次のようなメールを送った。

レジュメから参照可能なオンラインリソースにも明記してありますのでご存知かも知れませんが、私はトランスセクシュアル(MtF-TS)です。このため、現在の戸籍/法律上の性別と社会生活上の性別は異なります。入社手続きフォームは主としてlegalな手続きのためのものとお見受けしましたので性別欄は戸籍上のデータ(男性)を入力しましたが、もし社会生活上のデータが必要でしたらご相談ください。

フォームの趣旨に関する私の推量は適当だったようで、その旨返信があった。当たり前だけれどもGoogleはこの点ではフェアな会社である。上のような申告で特に問題は無かった。

性同一性障害に関する判例の中では、大きな問題となって「選考過程で虚偽の申告があったため解雇」とかいうことで係争になった事例もある。その点でGoogleはまともな会社である。

医療系など

これだけであれば私は特にこの記事を書こうと思うことはなかったろう。その後、人事の方からフォローがあった。曰く、

  • USではトランスセクシュアルの従業員もそれなりにいるが、東京ではまだ事例が少ないので今後のために何か改善してほしい点などがあれば教えて欲しい。
  • 今後、特に健康診断などで不愉快な思いをさせないかと心配しているが、どのような対応を希望するか

    • 基本的には契約した病院の集団検診に参加して貰っているが、これは不愉快な思いをさせるのではないか
    • 契約した病院に個別の健康診断を依頼したほうがよいか
    • その他の方法があるか

これについて、私は次のように答えた。

  • 入社手続きフォームの性別(Sex)という記入欄は、どのような性別を意図しているのか推察可能ではあるけれども明瞭ではないので法的性別(Sex in Law)などのように明確にしてほしい
  • 健康診断については配慮して頂いて有り難い

    • 集団検診についても、事前に病院に話を通して頂いてちょっとだけ配慮を頂けるならば(個人的には、検診のやり方の詳細をその場で訊いた限りでは)問題ないように思える
    • 個別に依頼してもらえるのが最も良いように思える。その場合も会社から病院に話を通しておいて頂けると有り難い。
    • 埼玉社会保険病院のように、性同一性障害者の健康診断の事例の豊富な病院もあるので、健康診断で必要な検査項目をリストして貰えればこちらで検診を受けてくることも可能である。(私は塚田攻医師に相談して、以前の健康診断はこちらで受けた)
  • 私は性同一性障害者であることをオープンにしているが、すべての当事者がそうであるとは限らない。ヘイトクライムの危険性などもあるので性同一性障害であることの情報は本人の判断に沿って管理されるべきである。今後オープンにしないことを希望する当事者が入社したらそのように対応して欲しい。

  • ここでの私の回答はあくまでも私の場合の個人的な回答であって一般化はできないので、個々の事例ごとに対応して欲しい

日本の医療は健康保険を通じて法的性別と医療上の性別とが接する場であるので、両者が一致しないケースや医療上の性別を単純に男性もしくは女性と記述できないケースでは問題になりやすい。一方、トランスセクシュアルであっても完全にSRSを終え、法的性別の変更を済ませてしまっている場合はあまり問題にならないと考えられる。

その他

また

  • 社内のLGBTIのためのコミュニティとしてGayglersというのがあるので見てみてはどうかと案内してもらった
  • ここでは伝え忘れたけれども、労務系のための法的性別の収集と社内のプロフィール設定における社会的文化的性別(Gender)の入力が独立しているのは素晴らしいと思った。
  • 開発合宿や研修旅行の目的でで温泉などを利用する場合、浴室設備が大浴場だけだと、SRSを受けていないトランスセクシュアルの利用に際して摩擦が発生しやすい。以前に提唱された解としては近場にビジネスホテルの部屋を別途用意するなどの対応が考えられる。これにしても問題が無いわけではないけれど、間に合わせの回避策としてはとりあえず機能するだろう。

考察と展望

このように、プロフェッショナルな仕事をする人事がいれば従業員がトランスセクシュアルであることは問題にならない。

トランスセクシュアルと労働というと、日本では何かと暗い話題もよく耳にする。やれ、面接で侮辱的な扱いを受けただの、性同一性障害であることを理由に解雇されただのと。しかしWeb業界は、全体に若い業界であることも手伝って既に「トランスセクシュアルかシスセクシュアルかなど、仕事に当たって気にする方がおかしい」という流れである。少数の変な信念を持った差別的な企業があってもじきに淘汰されよう。

これから職に就こうとする若いトランスセクシュアルに特に伝えたい。あなたは何にでもなれる。もう時代は変わった。だから、トランスセクシュアルであることで何か職業選択上の可能性が制約されるとは考えないで欲しい。

Web業界でLGBTであるということを理由に積極的に排除しようとする人はほとんどいない。日系の大きな組織になると、銀行系の妙な人材が経営層に流れ込んでいる関係か少しばかり硬直的な制度があることもある。けれども、それは交渉すれば変えられるものだ。なんと言っても現場の人たちは味方なのだから。 *3

それに企業は日系企業だけではない。たとえばGoogleもまた、LGBTに対してフェアである。採用時の差別は存在しないと思われる。よく分からないことについては相談しつつ、喜んで多様性に対応できる人事がいる。法的性別、医療における性別、社会生活における性別が必ず一致すると仮定した誤った設計の社内システムが存在しない。

世界はあなたに対して開けている。私はこれを理解しているつもりで、そして 私自身が一つの事例を提供し続けることで後の世代に伝えたい と思ってきた。しかし、私は理解していなかった。私が肩肘張って自力ですべてを変える必要もないのである。

今回Googleの人事はプロの仕事をして、受動的に必要な対応をしてくれるだけでなく積極的に動いてくれた。世界には優秀な人たちがいて、世界はこんなにも開かれている。

*1:具体的な数値はそれこそプライベートなことだし、記事を書くときに検査票を資料の山から引っ張り出すのも面倒だったので

*2:センシティブかつプライベートな問題であるので、社会的に適切とされている以外の軸についての性的属性の収集は一般的に言って性差別またはセクシュアル・ハラスメントである。例えば職場でパンツの色を聞いたり包茎かどうかを問題にするなど。勿論、性的なジョークが許される間柄ならば良いけれども、一般的に職場で性器の形態について問題にするのは望ましいことではない。トランスセクシュアルがしばしば直面する、社会生活上の性別が必要とされるべき局面で医療的性別情報を要求される類も同様にしてセクシュアル・ハラスメントに包括されると私は考える。「セクシュアリティに関する射影関数の不適切な選択」がセクシュアル・ハラスメントなのである。

*3:今回私は途中でうんざりしてきて日系企業の相手をするのはやめたからあんまり大きな口は叩けないけど

転職のお知らせ

世間は地震により慌ただしい。震源地近くの被災者の方にはお見舞いを申し上げる。 この最中に、個人的な報告を投下するのはちょっと憚られるものもあるのだけれども、あまり時期を外しても書く機会を逸するので思い切って書くことにしよう。

1月一杯で約3年務めた 株式会社スケールアウト を辞め、3月1日から Google Japan で働き始めた。twitterでは大勢の方に祝っていただき有り難い限りである。

Googleについては特に語ることはない。みんなが知っているし、私もまだみんなが知っているようなことの他は僅かしか知らない。だからスケールアウトについて語ることにしよう。

株式会社スケールアウト

スケールアウトは広告配信エンジン/広告在庫管理システム/広告入稿システム/広告案件管理システムをフルスタックの製品「ScaleAds」を提供するスタートアップである。

創業

創業者の山崎大輔さんは、元はYahoo! Japanの広告配信システムを構築した人である。一部では「 最速配信研究会のid:yamaz 」と言ったほうが通りがよいかも知れない。 まだ日本のネット業界が成立するかしないかの頃、彼はまだそれほど大きくなかったYahoo!に入って、今の巨大なサイトで高速にアクセスごとに最も適切な広告を選択して配信しているシステムの構築に携わった。

山崎さんはその実績もあってYahoo! Japanではそれなりに地位を得ることができたが、ある日自分の伸び悩みを感じて「このまま会社にしがみついて生き残ることは可能かもしれないが、それでは老害と化してしまう」と判断し、社外に挑戦の場を求めて武者修行に出ることを決心したそうである。そうして、スケールアウトを創業した。

そのスケールアウト社が作ったのがScaleAdsである。Webコンテンツを持っている会社が自社サイトに載せる広告を管理することを主に想定しているが、それに限らない。実際、メールマガジンでの広告の管理にも対応しているし、汎用のコンテンツ配信管理システムとして設計されている。 月間10億インプレッション程度であれば鼻歌混じりに捌き、サボらずにまともに設定すれば僅かなサーバー数で100億インプレッションを処理する。理論的には1000億PVもOKだ。

参加

現在のWeb業界にとって広告はオフラインとWebを繋いで経済を循環させる太い血管である。この血管の構築に携わりたいと思って、私もScaleAdsの開発に途中から参加した。そして、在庫管理システム/広告入稿・案件管理システムの継続的な改善に取り組んだ。

山崎さんの知識に基づく強力な配信エンジンを持つScaleAdsであるが、一方フロントエンド側や中間処理は私が参加した時点ではスパゲティであった。このレガシーコードとの戦いが私の仕事であった。あれを見たときにはコードベースを捨てることを提案したが、さすがにそれは山崎さんによって却下された。

レガシーコードを動いたまま移行させるのは書き直すことに比べて遥かに高く付く。それでも、そのコストに組織やメンバーが耐えることができたなら、危険な大きなジャンプをすることなく、機能のデグレードにも見舞われることもなく持続的なメンテナンスの可能なコードベースに移行することができる。 振り返って考えるに、恐らくコードベースを捨てて作業すれば半年で移行できたであろうが、代わりに一時的に大きな障害を引き起こした可能性もあったろう。Webシステムにあって最も金銭に近い *1 部分の1つである広告システムでは、資金的余裕の少ないスタートアップにはそのような失敗は許されない。こうして我々は3年間にわたる茨の道を歩くことになった。

十分にモジュール化されていないシステムを切り開き、テストハーネスを取り付けた。移行用のテストを書いてはモジュールを移行させ、テストを捨てた。いや、捨てるべきテストを捨てきれずに失敗した部分もある。幾つかのテスト戦略を試しては、幾つかは失敗した。これによりシステムから少しずつ腐ったコードが無くなっていった。拡張可能性を手に入れたシステムに、幾つか大きな機能追加を施した。

この時期この部分の開発に携わったメンバーを聞けば、東京のWeb開発者コミュニティ(特にRubyScala)にいる人ならば、この製品がどういうものであるのか分かるだろう。

一応、会社のサイトで公開している(いた)メンバーだけリストしたけれども、他にも一時期手伝ってくれた人は大勢いる。

転職

スケールアウトの長い戦いは今収束しつつある。安定性を更に増すために継続的インテグレーションで処理するテストケースはもっと増やすべきだが、それにしても主なモジュールのスパゲティは解消した。コードベースは継続的なメンテナンスが可能なものになった。継続的インテグレーションやその他諸々開発インフラも整えた。事業的にも顧客を増やして成功してきている。

一仕事終えた私はここでスケールアウトを一時離れることにした。これには2つ理由がある。1つには苦闘の日々が一時収束したので、次の大きな機能拡張の時期が来るまでは他でもっと面白いことをしていたかった。ただ、退職を決めた後になってから「次の大きな機能拡張」が思ったより早く来そうなことが判明したので、これについてはちょっと早まった判断だったかも知れない。

もう1つは、先に述べたようにスケールアウトはYahoo! Japanからのスピンアウト組を含んでいるということが関係ある。彼らが持っている大きな組織での開発者の政治的力学の経験や異分野の尖った専門家との繋がりというものを見て、興味を持った。そしてそれを体験してみたくなったのだ。 このため今回の転職ではチームでそれなりに大きな規模で開発している会社というのを一つのコンセプトとした。

このコンセプトに沿い、かつ 私が望むweb に貢献する会社を探した。そしてたまたまGoogleとご縁があった。こうして転職したのである。

*1:「金銭そのもの」であるオンラインバンキングやトレーディングを除けば

Understanding Go compiler tools (2)

Today I read memory management in go compiler.

There are go.y , y.tab.[ch] , lex.c and other files in src/cmd/gc/ directory. It seems that the go compiler has a lexical analyzer written by hand and a syntax parser generated by yacc ( bison ). lex.c also contains the main function for the compiler.

Here are the head lines of main function:

int
main(int argc, char *argv[])
{
        int i, c;
        NodeList *l;
        char *p;

        signal(SIGBUS, fault);
        signal(SIGSEGV, fault);

        localpkg = mkpkg(strlit(""));
        localpkg->prefix = "\"\"";

        builtinpkg = mkpkg(strlit("go.builtin"));

        gostringpkg = mkpkg(strlit("go.string"));
        gostringpkg->name = "go.string";
        gostringpkg->prefix = "go.string";        // not go%2estring

        runtimepkg = mkpkg(strlit("runtime"));
        runtimepkg->name = "runtime";

....

It is easy to guess what they do. They initializes signal handlers and bootstrap some standard packages.

Also we can see the declaration of NodeList *l . The parser must be going to store the result into the list.

memory management

I guessed that strlit function converts a C string into a String representation for the compiler. It was correct. The definition of strlit is in subr.c and it returns a pointer to Strlit . Strlit in go.h is commented as:

/*
 * note this is the representation
 * of the compilers string literals,
 * it is not the runtime representation
 */

Here I wondered how the go compiler manages heap memory for Strlit and others.

In general, memory management is an important part, although not a core topic. This is because there are many object to allocate during parsing sources and compiling. A parser must try to parse any input. It allocates some memory whenever it reads a term, and little by little constructs a syntax tree.

I heard that gcc uses garbage collection to mange memory on parsing and compiling. Ruby interpreter (CRuby) uses Ruby's garbage collector in order to manage heap memory for parser.

In the case of Go compiler, memory management seems naive.

Strlit*
strlit(char *s)
{
        Strlit *t;

        t = mal(sizeof *t + strlen(s));
        strcpy(t->s, s);
        t->len = strlen(s);
        return t;
}

strlit just calls mal and copies data into the allocated memory. mal must be a wrapper of malloc .

Here is the source of mal :

void*
mal(int32 n)
{
        void *p;

        if(n >= NHUNK) {
                p = malloc(n);
                if(p == nil) {
                        flusherrors();
                        yyerror("out of memory");
                        errorexit();
                }
                memset(p, 0, n);
                return p;
        }

        while((uintptr)hunk & MAXALIGN) {
                hunk++;
                nhunk--;
        }
        if(nhunk < n)
                gethunk();

        p = hunk;
        nhunk -= n;
        hunk += n;
        memset(p, 0, n);
        return p;
}

For large n it just calls malloc . For small n it adjusts alignment and returns a part of memory pointed by hunk .

This is the implementation of gethunk . There is nothing special.

static void
gethunk(void)
{
        char *h;
        int32 nh;

        nh = NHUNK;
        if(thunk >= 10L*NHUNK)
                nh = 10L*NHUNK;
        h = (char*)malloc(nh);
        if(h == nil) {
                flusherrors();
                yyerror("out of memory");
                errorexit();
        }
        hunk = h;
        nhunk = nh;
        thunk += nh;
}

Here is the implementation of remal , you know, a realloc equivalent.

void*
remal(void *p, int32 on, int32 n)
{
        void *q;

        q = (uchar*)p + on;
        if(q != hunk || nhunk < n) {
                if(on+n >= NHUNK) {
                        q = mal(on+n);
                        memmove(q, p, on);
                        return q;
                }
                if(nhunk < on+n)
                        gethunk();
                memmove(hunk, p, on);
                p = hunk;
                hunk += on;
                nhunk -= on;
        }
        hunk += n;
        nhunk -= n;
        return p;
}

It cares the case of extending the last part of hunk , however, that's all. It leaves heap memory leaked. The heap memory is collected by the end of process.

The go compiler seems to manage heap memory really naively and generously.

Here is another example. struct Node , which is the representation of a node in syntax tree, is just a concatenation of members which are necessary for each type of node. It is even not an union.

struct Node
{

....

        // if-body
        NodeList*        nelse;

        // cases
        Node*        ncase;

        // func
        Node*        nname;
        Node*        shortname;
....
}

Conslusion

The go team does not seem to care about this kind part of the implementation. They prerfer keeping the source simple to strictly implementing it.

I think they have a plan to make the go compiler self-hosted. Go have a garbage collector, a parser generator and even a parser for Go. So they can replace the go compiler with one written in Go itself.