2014-04-25

超会議3の前日の手記

さて、明日は超会議3だ。ドワンゴ社員である筆者もスタッフの一人として参加する。

すでに告知されている通り、超会議スタッフとしての筆者の割り当ては、超チューニング祭だ。

筆者、江添亮はドワンゴ社員であるが、公式Webサイトに載っているルール以外、未だに何の情報も得ていない。したがって、競争のための条件は公平である。

公式Webサイトのルールは、公開後に更新されて追加されたので、もし参加者の中で、現在公開されているルールを閲覧していない者がいれば、閲覧すべきだろう。とはいっても、漠然とした情報しか公開されていない。

競技の参加者に関係がある情報を、念の為に書いておく。

多くの人間の集まるイベントであり、WiFiは不安定になることが予想される。有線による安定したネットワークに接続するため、参加者はLANケーブルを持ってくることが推奨されている。また、競技参加者には電源が提供されるので、バッテリーが6時間持たないコンピューターを持ち込む場合は、ACアダプターを忘れないように注意されたい。

当日の計測環境へのファイルのアップロードは、sftpプロトコルで行うということなので、sftpクライアントを用意する必要がある。

筆者のさしあたっての問題としては、明日、迷わずに幕張メッセにたどり着けるかどうかということだ。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。筆者は今、ECMAScript Edition 5.1を読むのに忙しい。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-24

Ubuntu 14.04のリリースと、Ubuntu 14.10のコードネーム決定

Ubuntu 14.04がリリースされた。そして、ようやくMark Shuttleworthが、Ubuntu 14.10のコードネームを発表した。

Mark Shuttleworth » Blog Archive » U talking to me?

[訳注: タイトルは「タクシードライバー」の名セリフが元ネタ]

[訳注: この文章はやたらとUで始まる英単語が多く使われている]

この浮上したる約束されしUbuntuは、同僚のMPTが明言したるごとく、パフォーマンスのアアトなり。ただにアアトなるのみならず、こはdeadlineを行わざるべからず。かかる最新のリリースを成し遂げ、Trusty Tahrを14.04 LTSとして固めたりし諸氏に感謝感激雨あられ。そしてこの湧き上がる歓声とリリース後の休息を経て、今こそ水門を開きて種々の改良を成し遂げ、いでいで次の晴れ舞台の準備をせん。

[訳注: Ubuntu 14.04はI/OスケジューラーをCFQからdeadlineに変えた]

LTSに向けた努力は我々をして創造性を発揮せしめる。我々のユーザーは、パフォーマンスと安定性と保守性に特化した開発の結果を喜んでいる。そして、我々としても、技術的負債を一掃するための春の大掃除がやってきたことには喜ばしいものがある。しかし、春の大掃除の目的は、新しいアイディアと新しい技術を取り入れる余地を生み出し、もって次のリリースを屋根から飛び立たせることにある。Ubuntuで創造性を発揮するにあたって、今は絶好の時期である。我々は基本原理として革新の精神を備えている。我々のコアアプリ開発部が、例えば、フォンやタブレットやPCで輝かしい業績を示したように。そして、我々は同様に素晴らしい革新的を有する。LXC 1.0は、この地球で最速、最軽量の仮想環境であり、Ubuntuで生まれ育った。LTSが発表された今、まさに次のLinuxの世代の基礎を更新すべき時だ。より速く、より軽く、よりよくスケールし、よりよく保守できるように。我々はすべてのUbuntu開発者に、先駆的開拓者たりえる有益な変更をもたらすことができる唯一の立場を得ているのだ。

未来のUbuntu開発者は、アプリのアップデートをすべてのユーザーに一瞬で提供せんことを願う。我らはその願いを実現するものなり。Ubuntu開発者はすべてのクラウドとすべてのハードウェアに対して、デプロイを華麗に発行せんことを願う。我らはその願いを実現するものなり。Ubuntu開発者はPAASSaaSモノのインターネットを簡単に扱うことを願うによって、いざ実現せんとす。もし、自由ソフトウェアがその真の約束を果たさんとすれば、実務に使っている人々に役立つものでなければならぬ。我々はUbuntuを、開発や運用に携わる自由ソフトウェア開発者にとって最も役立つものにすべく活動しているのだ。

愛すべき我らの地に迫る必然の荒波を察すれば、今こそ、日陰を照らすときである。Ubuntuにsystemdをもたらす時である。Python 2.xから解放される時である。高地に、すなわち上流(Upstream)に歩みを進める時である。今こそ汚れを払い落とし、無益物を切り落とす時である。このクソコードを目の前にして、今こそ協力して、非協力性より有益性を高め、意地をすてて利点を考えよ。発狂や盲信はお呼びではない。いつも通りの仕事への注意深い検証と考察をすべき時なのだ。

[訳注: Ubuntuの今後の予定では、Upstartからsystemdに移行し、Python 2からPython 3に移行する予定である。また、自前で保守している自由ソフトウェアのパッチを本家に取り込んでもらうのはいいことである]

さて、最上のものを卓上に、あるいはフォーラムで、あるいはメーリングリストに置いた上で、なにか素晴らしい物を作ろうではないか。何か統一されていてすごいものを、何か世界に誇れるものを。今、我々は新規に始められる二年に一度の機会にいて、未来がどうなるかということについて制約を受けぬ野望を夢見ているのであるから、そのまま突き進んで、何か夢見がちな名前をつけよう。utopia unicornで始めよう。批評するがいい。vUDSで会おう。

いつも通り、Mark Shuttleworthの文章を訳すのは、死語となった言語を研究しているかのような難しさを覚える。

さて、Ubuntu 14.04がリリースされた。筆者の環境でのUbuntu 13.10からのアップグレードは、問題なく成功した。

まず、Linux Kernelは3.13になった。

Pythonは3.4だ。Ubuntuは、まだすべてのコードをPython 3に移行出来ていないが、いずれ移行する予定である。

gccは4.8.1から4.8.2になった。あまり代わり映えはしない。gcc-snapshotは2014年4月5日のものとなっている。

clangはclang-3.4が正式リリース版になった。どうやらlibc++も更新されたようで、-std=c++1yオプションを使っても、getsで失敗しなくなった。これにより、ローカルでC++1yを使える環境が、Ubuntuならば自前ビルドせずに構築できる。新たにスナップショット版のclang-3.5が付け加えられた。

vimは7.4.000から7.4.054になった。

さて、Unityにはいくつか変更が加えられている。まず、高DPIをサポートするためのスケール設定ができるようになった。また、メニューをウインドウごとのタイトルバーに表示できるようになった。また、Super+Wで各ウインドウを表示した時に、アプリケーション名をタイプすることでフィルターできるようになった。

そして、新しいウインドウデコレーションに変わっている。ウインドウの左右下のボーダー部分が完全になくなっていて、ウインドウ外にすこしシャドウがかかるUIになっている。黒背景のターミナルウインドウを黒背景のデスクトップの上に置くと見分けがつかない。私はあらゆるウインドウを全画面で切り替えて使うので問題はないのだが。

iBusは1.5.3から1.5.5になった。キーボードショートカットがうまく認識されない問題が解決されている。また、アプリケーションごとにIME有効無効の状態を保持できるようになった。

また、Ubuntu 14.04では、ブート、シャットダウン、サスペンドからの復帰が早くなったように感じる。特に、シャットダウンはとても早くなった。

現在、筆者が遭遇している問題は、たまにWiFiが使えなくなることだ。最も手っ取り早い解決方法は・・・再起動。ネットワーク関連のデーモンを再起動しても治らないので、ドライバーの問題だろうか。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。ところで、次のC++WG論文集の発表は6月頃なので、しばらくはC++以外の記事が多くなるだろう。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

ドミニオンの拡張が送られてきた

筆者の住む妖怪ハウスの私宛に、ドミニオンの拡張が3箱送られてきた。すでに基本セットを購入済みだったので、実にありがたいことだ。

送られてきた拡張は以下の通り。

  • ドミニオン:海辺 (Dominion:Seaside)
  • ドミニオン:収穫祭 (Dominion:Cornucopia)
  • ドミニオン:暗黒時代 (Dominion:Dark Ages)

まだ実際にプレイしていないので、感想を書くことはできない。いずれ妖怪ハウスでボードゲームパーティでも開きたいものだ。

ドミニオンとは、実に商業的に素晴らしいゲームである。というのも、拡張を売りやすいゲームなのだ。これがカタンとなると、基本があまりにも完成されているために、拡張は蛇足になってしまう。ドミニオンは、新しい効果が追加されるほど面白くなるゲームである。

ただし、単純なルールが複雑にして、面白さを損ねてしまったドミニオン拡張もあると聞く。

2014-04-23

JavaScriptのオブジェクト初期化子

JavaScriptでは、オブジェクトをリテラル風に式の中に書くことができる。これは、オブジェクト初期化子(Object Initialiser)とか、オブジェクトリテラル(Object Literal)と呼ばれている。その文法は、{ }の中にプロパティを記述する。

var a = {} ;
var b = { PropertyName : AssignmentExpression } ;
var c = { A : 1, B : 2, C : 3 } ;

プロパティ名とその値のペアを、コロンで区切って指定する。そしてカンマで区切る。

オブジェクト初期化子は、{}内の最後をカンマで終わらせることもできる。

{ A : 1, } ;

これは、やや気持ち悪い文法だ。

PropertyNameには、識別子と文字列リテラルと数値リテラルを書くことができる。

var x = {
// 識別子
IdentiferName : 0,
// 文字列リテラル
"StringLiteral" : 0,
// 数値リテラル
3.14 : 0 
} ;

さて、オブジェクト初期化子のプロトタイプに文法には、もうひとつ、getter/setter、あるいは、アクセッサーなどと呼ばれているものを記述する文法がある。文法は関数式に似ているが、functionキーワードのかわりに、get/setを用いる。

function X( val )
{
    this.value = val ;
}

X.prototype = {
    get value() { return this._value ; }
    set value( val ) { this._value = val ; }
} ;

var x = new X(0) ;
x.value ; // 0
x.value = 10 ;
x.value ; // 10
x.value += 10 ;
x.value ; // 20 

アクセッサーは、通常の関数呼び出しの文法を使わずに、同じ識別子で、値の設定と取得を、単なる参照と代入というわかりやすい文法で行うことができる機能である。これは、例えば以下のように書くより、格段にコードがわかりやすくなる。


function X( val )
{
    this.value = val ;
}

X.prototype = {
    function get_value() { return this.value ; }
    function set_value( val ) { this.value = val ; }
} ;

var x = new X(0) ;
x.get_value() ;
x.set_value(10) ;
x.get_value() ;
x.set_value( x.get_value + 10 ) ;
x.get_value() ;

ちなみに、Where's Walden? » More SpiderMonkey changes: ancient, esoteric, very rarely used syntax for creating getters and setters is being removedによれば、アクセッサーの文法には、実に様々な歴史的な非標準の方言があったようだ。特にMozillaのものだが。

まず、__defineGetter__/__define_Setter__がある。これは、Object.definePropertyを使うべきである。

かつて、SpiderMonkeyのJavaScriptのパーサーに問題があったため、以下のようなコードが通ってしまっていた。

var x = { get a b() { return "get" ; } } ;

また、アクセッサーの生みの親であるNetscapeの当初の文法は、以下のものであったらしい。

function g() { print("gotten!"); return "get"; }
var o1 =
  {
    property getter: g,
    property setter: function(v) { print("sotten!  " + v); }
  };
var v1 = o1.property; // prints "gotten!", v1 === "get"
o1.property = "new"; // prints "sotten!"

SpiderMonkeyはこれをしばらくサポートしていた。

また、アクセッサープロパティを付け加えるSpiderMonkey独自の文法として、以下のようなものもあったらしい。

var o = {};
o.property getter = function() { print("gotten!"); return "get" };
o.property setter = function() { print("sotten!"); };
var v = o.property; // prints "gotten!", v === "get"
o.property = "new"; // prints "sotten!"

うーん・・・。

SpiderMonkeyの独自文法はまだある。

getter function foo() { return "foo getter"; };
var v = foo; // "foo getter"
var q = setter function bar(v) { };

うーむ。

そういえば、strict modeのとき、PropertyAssignmentの中のPropertySetparameterListの識別子として、"eval"と"arguments'が現れると文法エラーというのは、どういうことだろう。コード例で言えば、以下のようなものだが。

"use strict" ;

// SyntaxError
var x = { set setter( eval ) { } } ;

なぜ、数あるキーワードの中でevalとargumentsだけが特別に禁止されているのか。ちょっと調べただけでは出てこない。もうすこし規格を読み進める必要がありそうだ。

ドワンゴ広告

この記事はドワンゴ勤務中に、十分な昼寝とカタンをした後に、書かれた。睡眠は重要である。カタンも重要である。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-21

JavaScriptの誕生と終焉

The Birth & Death of JavaScript — Destroy All Software Talks

あの、Watのスピーカーとして有名なGary Bernhardtが、JavaScriptの誕生と終焉についてスピーチしている。

このスピーチは、2040年に行われているという設定である。JavaScriptが10日でやっつけ設計されたというところから始まり、JavaScriptが開発された地は、すでに放射能汚染されているという、2040年からみた歴史的事実を交えつつ、話は続く。

JavaScriptはあまりにも一般化してしまったため、皆JavaScriptで書くようになった。ただし、JavaScriptは遅いので、JavaScriptをネイティブコードにコンパイルしやすいようにする制限的な記法が流行した(整数型でいいところには、0をビット列論理和することにより、整数型であることのアノテーションとするなど)。

そして、他の言語からJavaScriptを生成することが流行した。もはや、C言語からすらJavaScriptを生成できる。

次第に、JavaScriptは移植性の高い共通のアセンブリの地位を確立させていく。

そして、核戦争が起きた。オーストラリアの辺境にでも住んでいる変人でもなければ、10年ほどプログラミングなど出来ない状況に陥る。

そして、ようやくプログラミング可能なほど状況が落ち着いたとき、人々はプログラミングできない間でも、潜在意識の中で、思案を続けていた。

そもそも、CコードがJavaScriptにコンパイルできるのである。OSはなんで書かれているか? Cである。OSをJavaScriptにコンパイルすればいいではないか。

OSは、ハードウェアの特権モードの支援を受けて、ユーザースペースのプロセスを、お互いに干渉できないような隔離を保証する。この特権モードの切り替えは、非常に高くつく。しかし、Webブラウザーはタブでソフトウェア的に隔離を実装しているではないか。

なんと2040年では、JavaScriptは、極めて移植性の高い共通のアセンブリ言語として君臨している。もう移植性のない点でバラバラのハードウェアについて考える必要はないのだ。JavaScriptで動作する分、2割ほど遅くなるが、ハードウェアの特権モードを多用しない分、2割ほど速くなる。掛け算がどのように働くかということをかんがえれば、0.8 * 1.2 = 0.96であり、ネイティブで実行するよりも多少遅くはなるのだが、これは許容範囲である。

そして、JavaScriptは死んだ。JavaScriptは使われているが、もはや誰もJavaScriptを直接書くことはない。

そういった内容の、架空のジョークスピーチだ。とても面白い。

ドワンゴ広告

この記事はJavaScriptと関係があるので、ドワンゴ勤務中に書いた。超チューニング祭に役立つ記事ではなさそうだ。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

JavaScriptの配列初期化子

ECMAScript Edition 5.1を§11まで読み進めた。§11は、式だ。ようやく面白くなってきた。

§10は、この後の文面で使いまわすための、擬似的な処理を定義している。

さて、いよいよ具体的にコードとして書く、式のセクションを読んでいる。なかなか楽しいが、配列初期化子の文法が興味深かった。

配列初期化子、あるいは配列リテラルは、[ ]の中に要素を書く。

// 結果は要素数4の配列、[ 1, 2, 3, 4 ]
[ 1, 2, 3, 4 ] ;

配列初期化子には、Elisionという文法があり、途中の要素を省略できる。省略した要素は、undefinedである。

// 結果要素数4の配列、[ 1, undefined, 3, 4 ]
[ 1, , 3, 4 ] ;

なるほど、これはよく分かる。しかしよくわからないのは、「Elisionが配列の最後に使われた時には、配列の長さに寄与しない」という文面だ。つまり、最後のElisionは、無視されるのだ。

// 結果は3
[ 1, 2, 3 ].length ; 
// 結果は3
[ 1, 2, 3, ].length ;

たいていの言語ならば、文法違反とするところだが、実に不思議で例外的な文法だ。

しかし、それだけではない。要素が任意個のElisionだけの場合の文法も特別に定義されていて、その場合は、末尾のElisionも配列の長さに寄与するのだ。

[].length ; // 0
[,].length ; // 1, [undefined]
[1,].length ; // 1, [1, undefined]
[,,].length ; // 2, [undefined, undefined]
[1,,].length ; // 2, [1, undefined]

気持ち悪い。極めて気持ち悪い。例外に例外を重ねた文法で気持ち悪い。

さて、次はオブジェクト初期化子だが、どうもこれも、文法が気持ち悪そうだ。

文法の汚さ、パースしにくさでいえば、C++は悲惨なのだが、しかし、このような不思議な文法は多くない。JavaScriptの文法は気持ち悪い。

それでも、JavaScriptの文法や思想は、いまさら言うことではないが、面白い。

ドワンゴ広告?

この記事は超チューニング祭に向けてドワンゴ勤務中にECMAScript Edition 5.1を読みながら書いた。

そもそも、この超チューニング祭というのは、ユーザーによる企画だそうである。実は筆者も詳しいことを知らない。公式サイトが更新されて、基本ルールが追加されたが、この更新情報も事前事後に知らさるような特別なはからいは一切ない。そのため当日は、ドワンゴ社員であることによる不公平な情報差は発生しないだろうから安心してよろしい。

ところで、その更新されたルールによれば、当日編集できるソースコードは、HTML, CSS, JavaScriptだという。

「超チューニング祭 ~ニコニコを超快適にしてみた~ in ニコニコ超会議3」の問題点 - Webサイトパフォーマンスについてで指摘されているように、ボトルネックの大半はフロントエンドにないというのは、実際その通りだろう。複数のCSSやJavaScriptを結合したり、最小化したりといった小手先の技術は、小さな最適化に過ぎない。

では、勝利を狙うカギは、パフォーマンス以外の評価点、すなわちUIデザインだろうか。スマートフォン向けのデザインは、小さな画面サイズのため、とても単純にならざるを得ず、差別化を行いにくい。

ところで、現在、自由なスマートフォンがないので、筆者は携帯電話を所有していない。当日は極めて厳しい戦いを強いられることになりそうだ。

そして、そろそろ「広告」の定義について根本的な疑問が生じている。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-20

妖怪ハウスの水道事情

筆者の住んでいるシェアハウス、妖怪ハウスは、ひとつ問題を抱えていた。水道の水量が極めて少ないという問題である。

水量が少ないということは、水の節約になるとはいえ、あまりにも少ない。料理や皿洗いに時間が余計にかかるほど水量が少ないのだ。しかも、複数箇所の蛇口から水を出すと、どちらも実用に耐えざるほど水量が少なくなるのだ。水を出すというのは、たとえばトイレの水を流したあと、タンクに水をためるのも、水を出しているので、誰かがトイレに入ったあとしばらくは、皿洗いが難しくなる。

就中、問題なのはシャワーだ。シャワーの勢いが弱すぎるということもあるが、あまりの水量が少ないため、なかなかお湯が出ない。思うに、給湯器から風呂場まで距離があるために、水を押し出すのに時間がかかっているのだろう。

あるいは、給湯器も怪しい。なぜか途中で水になったりする。浴槽に自動でお湯をはる機能も、途中て勝手に停止する。故障しているのだろうか。

とはいえ、業者を呼んでみてもらう金もないので、仕方なく、妖怪ハウスに引っ越してからこの三ヶ月は、シャワーを諦め、浴槽にお湯をはる運用でしのいできた。

時に、妖怪ハウスにもともとついていたシャワーヘッドとホースの結合部分が劣化し、水が漏れるようになってしまった。

ひょっとしたら、シャワーヘッドをもっといいものに変えれば、少ない水量でも、すこしはマシになるのかも知れない。そう思って、大きなシャワーヘッドを買ってきた。

シャワーヘッドを取り付けるにあたって、水の元栓をしめる必要があった。住人はなぜか、水の元栓がどこにあるか把握していなかった。不思議なことだ。玄関の横にわかりやすくついているのだが、なぜ気が付かないのだろうか。

さて、さっそく水道の元栓を締めにとりかかったが、どちらの方向に回せばいいのかわからない。どちらにも回る。

ん? どちらにも回る・・・まさか、まさか水道の水量が少ないのは、元栓が開ききっていないためだったのか。

そのまさかであった。シャワーヘッドの交換作業を終えたあと、元栓をいっぱいまで開けると、水量は豊富になった。もう複数箇所で水を出しても、水量が不足することはない。トイレを流した後に皿洗いができなくなることもない。そして、お湯が短時間で出るようにもなった。

興味深いことに、お湯が勝手に水になったり、お湯はり機能が勝手に停止する現象に悩まされることもなくなった。ひょっとしたら、水量があまりにも少ないために、給湯器に実装された何らかの安全装置が働いて自動的に停止していたのかも知れぬ。

そして、新しい大きなシャワーヘッドから供給されるシャワーは、豊富な水量も相まって、極めて快適になった。

およそ、人間の人生の中で、食事と睡眠と入浴ほど重要なものはない。すでに東京のメシはマズいことは述べた。筆者は東京でろくなものが食べられない問題を解決するために、自炊をしている。筆者は平時は22時には寝て6時には起きる生活をしているので、睡眠も十分である。そして、入浴の問題も解決した。これでようやく、妖怪ハウスは人生において重要な三要素を満たしたことになる。

後は、住人に掃除の習慣が根付けばいいのだが。

2014-04-17

JavaScriptの自動セミコロン挿入

JavaScriptでは、多くの文は、セミコロンという終端記号を明示的に記述して、文の終わりを示す。

var i = 0 ;
++i ;
--i ;

しかし、JavaScriptでは、一部の文脈で、セミコロンの省略が許されている。あたかも、セミコロンが自動的に挿入されたかのように振る舞う。これを、自動セミコロン挿入(Automatic Semicolon Insertion)

ECMA-262 Edition 5.1 §7.9が規定する、自動セミコロン挿入の定義を、本記事では解説する。

まず、三つの基本的なルールがある。

  • プログラムを左から右にパースした時に、文法上許されないトークン(反則トークン, offending token)があった場合、以下の二つの条件のうちどちらかひとつ、もしくは両方を満たせば、セミコロンが自動的に挿入される。

    • 反則トークンと前のトークンが、ひとつ以上の行終端子で分かたれている場合

      // 例
      var x
      x
      x
      x
      

      これは、以下のようにセミコロンが自動挿入される。

      // 自動セミコロン挿入後
      var x ;
      x ;
      x ;
      x ;
      
    • 反則トークンが}である場合

      // 例
      function f(){ var x }
      
      // 自動セミコロン挿入後
      function f(){ var x ; }
      
  • プログラムを左から右にパースした時に、トークン列の最後に到達したが、正しい文法を構築できない場合、トークン列の最後にセミコロンが自動的に挿入される。

    // 例
    var x
    
    // 自動セミコロン挿入後
    var x ;
    
  • インクリメント、デクリメント、continue、break, return, throwの間で、行終端子が許されていない場所に行終端子がある場合、セミコロンが自動的に挿入される。

    LeftHandSideExpression [行終端子不許可] ++
    LeftHandSideExpression [行終端子不許可] --
    continue [行終端子不許可] Identifier ;
    break [行終端子不許可] Identifier ;
    return [行終端子不許可] Expression ;
    throw [行終端子不許可] Expression ;
    

最後のルールは、たとえば以下のようになる。

var i = 0 ;

i // 自動セミコロン挿入
++ ; // 文法エラー
i // 自動セミコロン挿入
-- ; // 文法エラー

function f()
{
    return // 自動セミコロン挿入、undefinedが返される。
    {
    // JSON的な何か
    } ;
}

ただし、自動挿入したセミコロンが空文に解釈される場合と、for文のヘッダーの中では、自動セミコロン挿入は行われない。

// 空文に解釈される場合
if( cond )
else

これは、もし自動セミコロン挿入が行われるとするならば、以下のようになる。

// 空文に解釈される場合
if( cond ) ;
else ;

このセミコロン挿入は、どちらも空文となるので、自動セミコロン挿入は行われない。

for文のヘッダーとは、for ( ... ; ... ; ... )のことだ。これにも自動セミコロン挿入は行われない。

さて、なぜ自動セミコロン挿入などという規則が存在するのか。思うに、ECMAScriptというのは、規格があって、しかる後にJavaScriptとして実装された言語でではない。JavaScriptという実装だけが先行して、あとからデファクトスタンダードとなった挙動を、ECMAScriptとして追認した形なのだ。規格の責任ではない。無秩序に進化した実装の歴史的経緯の問題である。したがって、既存の実装の挙動を、なるべく正確に規格に落としこんでいる。ECMA-262 Edition 5.1は、既存の実装の挙動を規格に落としこむという点で、非常にいい仕事をしたと思う。文面は読みやすい。JavaScriptは、C++より落とし穴が多い言語であるが、ECMA-262 Edition 5.1で、だいぶ救われている。

なお、規格では、自動セミコロン挿入には頼るべきではなく、明示的にセミコロンを書くべきだとしている。

ドワンゴ広告

この記事は、ドワンゴで最も怠惰な社員である筆者が、出社早々To Court The Kingで遊んだあとに、超チューニング祭に向けて準備をするふりをして書いた。まだバレていないようだ。

そういえば、昨日、珍しく時間の指定されて参加する必要のある社内会議があったので、予定時間の5分前に会議室に行った所、まだ誰も集まっていないどころか、会議室が別の会議で使用中であった。仕方がないので、一旦引き上げて、予定時間の2分後に会議室に行った所、前の会議の参加者は引き上げた上に、すでに全員集まって着席していた。一体、わずか7分間の間に何があったのか。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-16

JavaScript規格の正規表現リテラルの文面の疑問点

JavaScript規格、ECMA-262 Edition 5.1を読み進めていて、以下の文面が気になった。

A regular expression literal is an input element that is converted to a RegExp object (see 15.10) each time the literal is evaluated. Two regular expression literals in a program evaluate to regular expression objects that never compare as === to each other even if the two literals' contents are identical.

正規表現リテラルは、リテラルが評価されるごとに、RegExpオブジェクトに変換される入力要素である。プログラム中の二つの正規表現リテラルは、たとえ二つのリテラルの中身が同一であっても、===と比較されることのない正規表現をオブジェクトに評価される。

§7.8.5 Regular Expression Literals

つまりは、/./ === /./ はfalseになるということだ。正規表現リテラルが評価されるごとに別のオブジェクトになるということは、以下のようになる。


for ( var elem in [ true, false ] )
{
    var r = /./ ; // ひとつの正規表現リテラル 
    if ( elem )
        var a = r ;
    else
        var b = r ;
}

a === b ; // false

なるほど、確かに複数回評価されている。

しかし、文面では二つの正規表現リテラルとあるが、このプログラム中に、正規表現リテラルはひとつしかない。ひとつの正規表現リテラルが二回評価されるだけだ。と、屁理屈めいた疑問も生ずる。

筆者が規格を読むときは、文面は全て間違っているという前提で読むので、このような屁理屈のような疑問が生ずる。

ドワンゴ広告

この記事はドワンゴ勤務中にやんごとなき理由により自分の机を離れて書いた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

JavaScriptのコメントと改行

今回の記事は、JavaScriptのコメントの文法についての、とてつもなく些細な内容になる。

まず、「改行」の定義について

ECMAScript規格では、俗に改行と呼ばれているものは、正式には、行終端子(Line Terminator)と名づけている。行終端子は5個あり、これは4種類の文字からなる。なぜ4種類の文字で5個あるのか。ひとつは組み合わせなのだ。

行終端子を構成する4種類の文字は、\u000A(Line Feed), \u000D(Carriage Return), \u2028(Line separator), \u2029(Paragraph separator)である。

しかし、慣習的に、CRに続くLFを、ひとつの「改行」とみなすことが横行している。JavaScriptはこの慣習を追認する形で、CRLFの2文字をひとつの行終端子として認識する。

さて、本題に入ろう。JavaScriptのコメントには、一行コメントと、複数行コメントがある。

// 一行コメント

/* 複数行
コメント*/

コメントは空白文字とみなされる。

一行コメントは、//から行終端子までがコメントとなる。ただし、行終端子はコメントに含まれない。

複数行コメントの中に行終端子があった場合、複数行コメントは、行終端子とみなされる。

なぜ行終端子が残るのかというと、自動セミコロン挿入(automatic semicolon insertion)のためだ。


function f()
{
    var i = 0 ;
    i // 一行コメント
    ++ ; // エラー
}

一行コメントは、行終端子として認識されるので、自動セミコロン挿入が働く。したがって、上記のコードは、正しく文法エラーになる。

JavaScriptの自動セミコロン挿入については、このブログでも4年前に取り上げたが、当時はまだ規格の読解力が今ほどではなく、やや稚拙であるので、この機会に、規格を§7.9まで読み進めたあとで、解説しようと思う。

ドワンゴ広告

この記事は意識高い系ドワンゴ社員である筆者が、超チューニング祭のために、自発的に06:33に出社してECMA-262 Edition 5.1を読みながら書いた。

昨日は、実質七時間しか睡眠を取っていない故に「つれー」状態にある。実質七時間なのだ。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-15

Multipath TCPについて

Multipath TCPとは、複数の経路を扱うためのTCP拡張である。実は、以前、本の虫: MultiPath TCPのLinuxカーネル実装という記事で、その実装デモを紹介している。

従来のTCPは、IPとの分離ができない。TCPヘッダーの中には、ひとつのIPアドレスとポートがある。経路ごとにIPアドレスが割り振られるので、経路を変えるには、別のTCPコネクションを貼り直さなければならない。

しかし、複数の通信経路を持つという環境は、もはや珍しいものでも何でもなくなっている。たとえば、多くのラップトップにはEthernetとWiFiの二つの経路があるし、スマートフォンにも、WiFiと3G/4Gという複数の経路がある。特にスマートフォンの場合、経路が使えるかどうかが頻繁に切り替わる。

過去に、TCPで複数のIPアドレスを扱う拡張はいくつも出されたが、いずれも、IPアドレスを隠すという点で、非効率的である。

複数の経路を直接扱えれば、パフォーマンス的にも、冗長性的にも、利点がある。

実は、トランスポート層で、複数のIPアドレスを扱うプロトコルは、すでに設計されている。SCTPだ。

SCTPは単に複数のIPアドレスを使えるのみならず、ストリーム単位を混ぜあわせて送信し、受信側でストリーム単位に分解できたり、送信バイト数を通知して、全部受信するまで待機できたりと、従来ならアプリケーション層でやっていたことが、トランスポート層で面倒を見てくれるので、とても便利なのだ。

問題は、SCTPのその他の利点は、とてもニッチな分野でしか需要がない。古い歴史を持つTCPには様々な問題があるとはいえ、既存のTCPからの移行コストを支払ってまで置き換えるほどの利点ではない。

それに、既存のほとんどのルーターが、SCTPパケットを、単に破棄してしまう。卵と鶏の問題と同じで、SCTPの利用者がいないので、ルーターベンダーはSCTPをサポートしない。ルーターがSCTPをサポートしていないので、開発者はSCTPを使えない。

必要とされているのは、既存のTCPパケットとして流せて、既存の機器でも問題なく動く、TCPの拡張だ。それが、Multipath TCPである。

MTCPは、アプリケーションからは、従来のsocketによるTCPと同じように扱える。ただし、アプリケーションが従来のTCPと同じだと信じているものは、実はMTCPによるレイヤーを通した仮想的なもので、本物のTCPコネクションは、MTCPによって管理されている。MTCPは複数の経路をまとめて管理し、アプリケーション側には、従来のTCPのようにみせかける。

MTCPの実装には、TCPオプションを使う。しかし、これは現実的に問題になる。

今日のインターネットは、当初のインターネットとは大きく違う。経路上に、実に多数の、中間箱(middlebox)が存在する。ルーターやスイッチだけではなく、ファイヤーウォールやらNATやらロードバランサーやらDeep Packet Inspectionやらだ。多くの中間箱が、TCPパケットを書き換える。

そもそも、モダンなNICは、効率化のために、勝手にTCPパケットを分割する。この際、TCPヘッダーは、単にコピーされてしまう。そのため、MTCPがTCPヘッダー内で予約して使うデータシーケンス番号が、コピーされてしまう。

MTCPシーケンス番号のコピーは、従来のTCPシーケンス番号の範囲のマッピングにより対処した・・・つもりであった。しかし、これでも問題があった。なんと、多くのルーターが、シーケンス番号を書き換えているのだ。背景には、最初のシーケンス番号をランダムに開始しない脆弱性ある実装に対処するため、ルーター側でシーケンス番号を振り直すということが、広く行われているようなのだ。このため、マッピングを絶対的ではなく、相対的にすることで、対処した。

さらに、active FTPなど、複数のTCPコネクションを貼り、ASCIIでIPアドレスをエンコードするような特定のプロトコルに対し、中身を書き換える(すなわち長さも変わる)などの改変を行うルーターすら存在する。

Linuxカーネルに実装されたMTCPでは、チェックサムを使うことで、データの改変を検知し、従来のTCPにフォールバックする実装になっている。

研究者がインターネット上の中間箱(middlebox)について調査を行ったところ、どうやら今日のインターネットでは、TCPパケットのあらゆる部分は、中間箱により改変される可能性があるということが判明した。これは、将来のTCP拡張を設計する上で考慮に入れなければならないことである。TCPヘッダーの中身のあらゆる箇所は、改変されないという保証がないのだ。

さて、利用例であるが、Wifiと3G/4Gなどの複数の経路を持つスマートフォンやデータセンターが挙げられている。

スマートフォンは、短期間で有効、無効が切り替わる複数の経路でも、TCPコネクションを維持するために使われる。

今日、データセンターでは、複数の経路を使うことは当然になっている。ただしその実装は、複数の経路をロードバランサーなどでまとめて、ラウンドロビンで複数の経路にパケットを割り振り、あたかもひとつのMACアドレス、ひとつのIPアドレスを持つように見せかけている。これは非効率的である。また、通常の経路と、バックアップ用の待機経路を持って、冗長性を確保するという利用方法もある。MTCPならば、複数の経路がそれぞれ異なるMACアドレス、IPアドレスを持てる。直接MTCPが管理するので、パフォーマンス目的でも、冗長性目的でも、効率的に管理できる。

Multipath TCPは、従来のTCPパケットのまま経路上を流せるということと、安全のために従来のTCPへのフォールバックがある、既存のアプリケーションの対応が必要ないという点で、移行しやすい拡張だと言える。

現在、Linuxカーネルで実装されていて、FreeBSDでも実装する計画がある。

さて、流行るだろうか。理想主義者の筆者としては、むしろ抜本的な解決方法として、SCTPのような全く新しいプロトコルが主流になって欲しいのだが。

ドワンゴ広告

この記事は、たまたま、ドワンゴ社内にCOMMUNICATIONS OF THE ACM 04/2014 VOL. 57 NO.04が転がっていたので、興味を引いたMultipath TCPについての論文を読んで、勤務時間中に書いた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-14

Python 2.7のサポート期間が2020年まで延長

peps: 76d43e52d978

Python 2.7のThe End Of Life時間(EOL、日没の時間)は5年間延長されて、2020年になった。この決定はPython 2.7の状態を明確にし、まだPython 3に移行出来ない利用者の懸念を取り除くものである。PEP 466も参照されたし。

この表明は、バグ修正リリースが頻繁に行われることを保証するものではないが、Python 2.7のバグ修正を行いたいボランティアの貢献を可能にし、また、今後もしばらくPython 2をサポートする必要のあるベンダーを満足させるものであろう。

Python 2.8はない。

いかにプログラミング言語にとって、下位互換性が重要化が分かる事例だ。Python 3は、下位互換性をぶち壊す変更をすべきではなかった。たとえどんなに汚かろうが、一度使われてしまった文法は、いまさら廃止することは出来ないのだ。

ドワンゴ広告

この記事は、そろそろドワンゴを退社しようとしかけたところでニュースに気がついたので、急遽、勤務中に書いた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

JavaとJavaScriptの違い

JavaとJavaScriptには、Unicode escape sequenceというものがある。どちらも同じ文法で、\uに続いて4文字の16進数文字を指定することで、Unicode Code Pointを指定できる。あたかも、Unicode Code Pointを記述したかのように振る舞う。

ところで、JavaとJavaScriptは、このUnicodeエスケープシーケンスの使い方が異なる。例えば、行終端文字\u000Aを、以下のように書く。

// これは\u000Aコメント

これは、JavaScriptで解釈すると、以下のようになる。

// これは\u000Aコメント

以下は、Javaによる解釈である。

// これは
コメント

Javaでは、Unicodeエスケープシーケンスが、実際に行終端文字として扱われてしまう。したがって、行終端文字以降が一行コメントからはみ出してしまう。

これは、文字列リテラルの中でもそうである。

"これは\u000A文字列リテラル" ;

というコードは、Javaでは

"これは
文字列リテラル" ;

と解釈される。Javaの文字列リテラルは、途中に改行文字を記述してはならないので、これはエラーとなる。Javaで文字列リテラルの中に、リテラルの値として改行文字を入れたい場合は、\nなどと書かなければならない。

Javaは謎すぎる。ますますJavaはクソであるという認識を新たにした。

というわけで、ECMA-262 Edition 5.1を読んでいるが、まず、文法記法の丁寧な定義が書いてある。これはとても親切だ。ただし、丁寧な定義と引き換えに、いろいろと文法記法が複雑になっている。これは、JavaScriptのデファクトスタンダードな文法を、後から追認する形で規格化したので、どうしてもこのような複雑な記法にならざるを得ないのだろう。例えば、改行が意味を持つ文脈など。

次はLexical Conventionsだ。

ドワンゴ広告

この記事は超チューニング祭のために勤務中にECMA-262 Edition 5.1を読んでいて興味深かったので書いた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

超チューニング祭

超チューニング祭が告知された。

公式サイトから引用すると、

超チューニング祭開催のお知らせ

ニコニコ超会議3内で開催予定のチューニングイベント!
ニコニコ動画のスマートフォンサイトをHTML/CSS/JavaScriptでフロントエンドチューニングしよう!
(表示速度のみの判定ではありません!ユーザー投票あり!)

ニコニコ動画史上最速の座を賭けた白熱の2日間・・・
豪華賞品と名誉は誰の手に!?

超チューニング祭

とのことだ。超会議3の企画のひとつで、参加には、以下のイベント支援Webサイトから登録する必要がある。

超チューニング祭 - connpass

また、公式サイトによれば、

参加スターエンジニア

君はドワンゴの精鋭達に勝つことができるか!?

  • 戀塚昭彦 @koizuka / 世界で最初のニコ厨
  • 江添亮 @EzoeRyou / C++標準化委員会エキスパートメンバー
  • 山田将輝 @masarakki / Ruby界隈で著名なエンジニア
  • 水島宏太 @kmizu / 日本Scalaユーザーズグループ 代表

超チューニング祭

となっている。はて、江添亮とはどこかで見た名前だ。どこだっただろうか。

この疑問はさておき、この他称ドワンゴの精鋭達は、重大な問題を抱えている。誰もフロントエンドエンジニアではないということだ。そして、いずれも強いこだわりをもっているということだ。

筆者が思うに、@masarakkiは、Opalを、@kmizuScala.jsを、@koizukaemscriptenを、それぞれ使うのではなかろうか。@EzoeRyouは、どうせ規格でも読むのだろう。

ところで、超会議3で、筆者がこの超チューニング祭に割り当てられるというのは、つい先週、本人に伝えられたばかりだ。それも、この公式サイトに書いてあるより少ない情報量が伝えられただけだ(何かハッカソン的なもの、フロントエンドのパフォーマンス改善的な何か、HTMLとかJavaScriptあたり? パフォーマンスをテストするらしい、テスト環境の不備をついて高パフォーマンスに見せかけられないものだろうか云々)

幸い、C++WG論文も片付いたし、次の論文集の発行は6月になる見込みなので、月末までHTML5やCSSやECMA-262 Edition 5.1を読むことにしよう。これまでも断片的には読んでいたが、C++の規格ほど本気で読んだことはない。月末までには到底読みきれないだろうが、とりあえずECMAScriptの規格を読むことにする。

ドワンゴ広告

この記事は14:24に出社したら、出社にさかのぼること30分ほど前に超チューニング祭の告知Tweetが出ていたので、急遽、勤務中に書いた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-13

GCC 4.9リリース

GCC, the GNU Compiler Collection - GNU Project - Free Software Foundation (FSF)

GCC 4.9がリリースされた。少なくとも、公式Webサイトのトップページからは、リリースされたことになっている。ただし、なぜかリンクをたどると

GCC 4.9 Release Series — Changes, New Features, and Fixes - GNU Project - Free Software Foundation (FSF)

GCC 4.9がリリースされた。興味深い変更点を上げると。

大昔の、もはや保守もテストもされていないようなプラットフォームのサポートがobsolete扱いになった。もし、活発な活動が行われない場合、次のリリースでは取り除かれるそうだ。特に、Solaris 9が挙げられている。

Clangにある、AddressSanitizerが、ARM向けにも提供されるようになった。また、ClangにもあるUndefinedBehaviorSanitizerが、GCC 4.9にも実装された。これは、規格上の未定義動作を、実行時に検出して実行時エラーにしてくれるものである。

LTOが改良されたらしい。

Inter-procedural optimizationが改良された。これにより、virtual関数呼び出しをしなくてもいい文脈がよりよく判定できるようになったようだ。

プロファイルによる最適化にも改良があったようだ。

-fdiagnostics-colorオプションが追加され、Clangにもある、コンパイラーの出力する警告とエラーのメッセージに色を付ける機能が実装された。

C++に目を向けると、C++14の新機能が実装されつつある。C++14の新機能はまだ実験段階で、、-std=c++1yオプションを与えることで、有効にできる。

GCC 4.9では、通常の関数の戻り値の型推定機能が実装された。

// 戻り値の型はint
auto f(){ return 0 ; }

もちろん、decltype(auto)も実装された。

// decltype(auto)の例
int & f() ;

auto x = f() ; // int
decltype(auto) y = f() ; // int &

規格上、autoとdecltype(auto)は、ともにplaceholder typeと呼ばれている。autoは、初期化子から関数呼び出しのtemplate argument deductionのルールを使って、型を推定する。そのため、上記の例では、xの型はintになる。

一方、関数の戻り値の型推定に伴って追加された新しいplaceholder typeであるdecltype(auto)は、あたかも初期化子の式をdecltype( 式 )の中にいれたかのように振る舞う。つまり、この場合はdecltype(f())と同じように振る舞う。したがって、yの型はint &になる。

GCC 4.9では、lambda capture initializerが実装された。

// lambda capture initializerの例
auto f = [ x = 42 ](){ } ;

これにより、ムーブコンストラクターを呼び出すコピーキャプチャもできるようになった。

GCC 4.9では、C++14に提案されているruntime sized arrayをサポートするようになった。この結果、実行時サイズ配列がラムダでキャプチャーできるようになった。

// 例
void f( std::size_t size )
{
    int a[size] ;
    [&a](){} ;
}

GCC 4.9は、deprecated attributeをサポートした。deprecated attributeに記述できる文字列リテラルは、コンパイラーの警告メッセージに含まれる実装となっている。

// deprecated attributeの例
[[ deprecated ]] void foo() ;


[[ deprecated("bar(int) is deprecated. Use bar(bool) instead.") ]] void bar( int use_super_fast_algorithm ) ;
void bar( bool use_super_fast_algorithm ) ;

int main()
{
    foo() ;
    bar( 1 ) ;
}

GCC 4.9では、数値区切り(digit separator)をサポートした。

// digit separatorの例
int i = 123456789 ;
int j = 123'456'789 ;
int k = 0x10'000 ;

// 区切りは1文字以上なら何文字でもよい
int l = 1'22'333'4444'55555 ;

GCC 4.9では、ジェネリックラムダ、あるいはポリモーフィックラムダと呼ばれているC++14提案を実装した

// generic lambda
int main()
{
    auto f = []( auto x ) { } ;
    f( 0 ) ;
    f( 0.0 ) ;
    f( "hello" ) ;
}

その他、libstdc++も、C++11の標準ライブラリをサポートしつつあるようだ。

OpenBSDが2014年度の寄付金目標額に到達したため、文字通り腐敗したサーバーインフラを再構築できるようになった

OpenBSDが電気代を払えないほどの資金難に陥っていることはすでに報告した。その後、寄付が集まり、OpenBSDは持ちこたえた。さて、今回、OpenBSDの寄付金額が、今年の目標に達したそうだ。

'OpenBSD Foundation 2014 Fundraising Campaign.' - MARC

List:       openbsd-misc
Subject:    OpenBSD Foundation 2014 Fundraising Campaign.
From:       Bob Beck <beck () openbsdfoundation ! org>
Date:       2014-04-10 16:23:41
Message-ID: 20140410162340.GA15909 () hogfat ! obtuse ! com

OpenBSD財団は、2014年度の寄付金が、目標額である15万ドルに達したことを報告する。

我々は大小の貢献者に感謝する。我々は資金調達努力を、今年度と来年度に渡り、継続する。

今年の資金調達の成功により、本財団はOpenBSDプロジェクトが陥ってた問題を緩和することができるようになった。財団は電気代のような、プロジェクトのインフラに資金を回す責任を果たすことができる。

本財団は、プロジェクトのサーバーインフラを再構築する作業に着手できるようになった。このインフラには、文字通り腐敗しているものも含む。

2014年のハッカソンは開催可能となり、OpenBSDと関連プロジェクトに改良をもたらすこの重要なイベントを継続することがデキるようになった。

我々は財団に継続的に寄付している貢献者に感謝する。寄付は予算と計画をより効率的に行うことに使われる。

財団は今後も財務状況改善と、プロジェクトのサポートに向けて努力する。寄付を継続してくれ!

「文字通り腐敗しているサーバーインフラ」というのが気になる文面だ。

しかし、15万ドルというのは、有能なプログラマーを一人雇うのに必要な程度の金額である。OpenSSHのような超重要なソフトウェアも開発しているプロジェクトに有能なプログラマー一人分の給料ほども資金が集まらず、電気代すら払えない状況になっていたというのは、コモンズの悲劇に似ている現象だろうか。

2014-04-12

妖怪ネットワーク改善案

妖怪ハウス内のネットワーク、すなわち妖怪ネットワークの改善作業は続いている。

さて、まともなスイッチングハブとルーターを導入したことで、妖怪ネットワークはだいぶマシになった。しかし、まだ妖怪ネットワークのパフォーマンスには、不満がある。厳密に計測したわけではないが、京都に住んでいたときよりも、パフォーマンスが劣っているように感じられる。何十個ものブックマークしたURLをタブで開いて閲覧するのが遅すぎる。

これはなぜだろうと考えたが、ふと、DNS lookupが遅いのではないかと考えた。帯域的には、何の問題もないはずである。ルーターの性能も十分である。実際、Webサイトのダウンロードは十分に早い。ダウンロードまでがなぜかもたつく。

調べてみようと、digを使ったところ、なぜか動かない。動かない理由は、DNSキャッシュサーバーとして動作しているYAMAHAのRTX810は、EDNSをサポートしていないからであった。digコマンドに+noednsオプションを指定した所、digは動いた。

しかし、RTX810越しにDNS lookupをしたのでは、正しく計測できない。digコマンドは、@に続けてサーバーを指定することで、直接サーバーに対してDNS lookupを飛ばしてくれる。さっそく、ISPが通知しているDNSサーバーについて調べてみた。すると、奇妙な特徴が判明した。

私のよく閲覧するWebサイトのドメイン名を引くのに、400msはかかる。あるドメイン名に対して、DNS lookupをしてから数秒間は、8msほどでlookup可能なのだが、数秒を過ぎると、また400msかかる。これは、京都に住んでいたときのISPの提供するDNSサーバーに比べて、あまりにも遅すぎる。

RTX810のキャッシュに載っている限りは、1msでDNS lookup可能だが、大本がこんなに遅くてはどうしようもない。

とりあえず試験的に、Googleの提供するPublic DNSである、8.8.8.8と8.8.4.4をRTX810に設定してみた。これにより、利用者側での設定変更の必要はない。Googleの提供する公開DNSサーバーで、普段閲覧するWebサイトのドメイン名を引いてみたところ、どのドメイン名でも、38ms程度の、非常に安定した時間がかかることが判明した。ほとんどのドメイン名のDNS lookupに400msかかる、ISPの提供するDNSサーバーよりは相当に優れているといえる。

妖怪ネットワークのもうひとつの問題は、WiFiだ。今は、BUFFALOに変えて、NECの無線LANルーターを使っているが、これも複数人で接続すると、とたんに不安定になる。やはり、業務用のしっかりした無線LAN APを使うべきだろうか。問題は、そのような業務用機器は、値段も高いということだ。

私は基本的に無線は使わないので、今すぐに解決しなければならない問題ではないが、長期的には解決したいところだ。

2014-04-11

なぜTheo de RaadtはIETFに激怒しているのか

本の虫: OpenBSD、怒りのコミットで、OpenBSDのTheo de RaadtがIETFに対して激怒している。

src/lib/libssl/ssl/Makefile - view - 1.29

SegglemannのRFC520 heatbeatを無効化。

あのまともなプロトコルひとつ制定できないIETFの無能集団が、超重要なプロトコルで64Kの穴をこしらえるとか、マジであきれてものも言えねーわ。奴らはマジこの問題を本気で検証すべきだろ。なんでこんなことをしでかしたのか。こんな事態を承認した責任ある連中を全員、意思決定プロセスから取り除く必要がある。IETF、てめーは信用なんねぇ。

なぜTheo de Raadtは、OpenSSLではなく、IETFに対して激怒しているのか。IETFというのは、インターネット上の規格制定の団体である。今回、世上を騒がせているHeartbeat問題は、Heartbeatの実装のうちのひとつ、OpenSSLのバグのために引き起こされている問題である。設計上の問題ではない。なぜTheo de RaadtはOpenSSLを放置して、IETFを問題にするのか。これはいったいどういうことだ? ひょっとしてTheo de Raadtはバカなのか?

もちろん、Theo de Raadtはバカではない。もとより、あのTheo de Raadtである。どんなに人格的に彼が嫌いな人であろうと、Theo de Raadtの能力は認めざるを得ない。彼は問題の核心を指摘しているのだ。

Heartbeatと呼ばれているこの機能は、具体的には、RFC 6520 - Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) Heartbeat Extension(TLS/DTLS Heartbeat拡張)のことである。このTLSに対する拡張は、TLSにkeep-aliveの機能をもたらすものである。

ではなぜTCP keep-aliveではだめなのか。たいていのOSでTCP keep-alive間隔があまりに長時間に設定されているためか。それなら必要であると感じるものだけがOSの設定を変えれば良い話だ。なぜわざわざ同等機能の規格を重複して作るのか。そもそも、大多数の一般人にとって必要なのは、もっと上のアプリケーション層でのKeep-alive実装ではないのか。

このHeartbeatという機能は、基本的に誰からも必要とされておらず、事実、さっくりと無効にしても誰も困らない機能である。だからOpenBSDでもさっくりと無効にした。なぜそんな誰からも必要とされていない無用の機能を規格化するのか。規格化された以上、規格準拠のソフトウェアは実装しなければならない。新しく実装した機能には不具合が含まれる可能性が高い。誰からも使われない機能は、不具合が発見されにくい。無駄な機能を規格化するとは、いったいIETFは何をしているのか。

Hacker Newsでは、この背景事情を解説するコメントが投稿されている。

There are smart people working in the TLS WG, but there are also people there th... | Hacker News

TLS WGには頭のいい奴らもいるが、同時に、このインターネットの最高に重要な暗号通信を制定する資格のない奴らも多くいる。

さらに、ワーキンググループは、新機能に対してイエスと答える傾向が高い。否定論者こそ必要とされているのに。Heartbeat機能はこの問題の明らかな例だ。リファレンス実装がやっつけ仕事すぎるからだ。

そもそも、TCP TLS heartbeatを無効にしたという事自体に、もっと非難の声が上がるべきなのだ。誰も必要としていないし、だれも作ってくれと頼んでいない機能なのだ。なんで最初からデフォルトで無効になっていないのだ? デフォルトで有効であることに、いったいどんな意思決定がなされたのだ?

I have read all the TLS WG discussions I can find on this RFC. The picture that... | Hacker News

俺はRFCで探せる限りのTLS WGを全部読んでいるが、これはワーキンググループ事態の根本的な失敗だ。

俺の知る限り、「これ必要ないだろ」という主張をしたのは、たったの一人だ(GnuTLSの主要開発者のNikos Mavrogiannopoulos)。彼はこの機能が必要だという理由を提出しろと三度も要請した[0][1]。返事は二件、どちらも同一人物からの返答だ。これ以降、議論は一切ない。つまり、彼の反対意見は解決されたか、これ以上の議論は非建設的だと判断されたかのどちらかだ。いったいどちらなのか、非常に気になるところだ。GnuTLSではheartbeatが無効にされている。つまり、Nikosはこの機能に未だに価値を見出していないということだな。

しかし、このドキュメント[訳注: RFC6520か?]は、今ここで名前を挙げて辱めることはしないが、多くのセキュリティ専門家が関わっているのだ。彼らは皆、反対意見を出さずに、検証し、コメントを出し、ドキュメントを編集したのだ。

思うに、このワーキンググループの性質として、ある機能が欲しい勢力は、その機能が、ひょっとしたら、悪く実装されて脆弱性をもたらし、無関係の被害を被るような、大多数の勢力より、強い影響力を持つようだ。どうも逆NIMBYな状況だな。ソフトウェアコミュニティは、ぽこぽこ生まれるすべての新しいTLS提案に反対するだけの暇はないが、ボクの考えた最強の機能の標準化を押し通そうとする勢力には暇があるわけだ。

[0] : IETF - TLS - tsv-dir review of draft-ietf-tls-dtls-heartbeat-01

[1] : IETF - TLS - Working group last call for draft-ietf-tls-dtls-heartbeat-02

標準化のためのワーキンググループというのは、不思議な場所だ。標準化のための権力を持っていながら、提案されている規格に対する詳細な知識や理解を持たないものが大勢いる。これには仕方のない部分もある。あらゆる分野の専門家たることはできない。Theo de Raadtのような例外的存在を別にすれば、専門家たろうとすれば、専門範囲は狭く深くなる。したがって、自分の専門分野以外は素人同然というのは、不思議なことではない。

問題は、それでもワーキンググループのメンバーである以上、様々な提案の採決に意見表明しなければならない。自分の専門ではない分野は、自然と肯定に回ってしまう傾向がある。

否定論者は必要である。ワーキンググループのメンバーにすら、提案された新機能の必要性を説得できなければ、いったいどうやって世界中の利用者に価値を説得できるというのか。

ドワンゴ広告

この記事は、前の記事とは違い、ドワンゴ勤務中に書かれた。前の記事は自宅で書き、この記事は15時頃(ドワンゴ定義ではそろそろ昼飯時、部署によってはまだ朝)出社して書いた。どうやら勤務中でもやることは変わっていないようだ。

今夜は社内でボードゲームをする予定であるので、なおさら変わっていない。最近、To Court The Kingというとても面白いゲームにハマっている。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

OpenBSD、怒りのコミット

OpenSSLのheatbeatバグの対応のため、OpenBSDはOpenSSLのheatbeatを無効にするコミットをした。ただし・・・

src/lib/libssl/ssl/Makefile - view - 1.29

SegglemannのRFC520 heatbeatを無効化。

あのまともなプロトコルひとつ制定できないIETFの無能集団が、超重要なプロトコルで64Kの穴をこしらえるとか、マジであきれてものも言えねーわ。奴らはマジこの問題を本気で検証すべきだろ。なんでこんなことをしでかしたのか。こんな事態を承認した責任ある連中を全員、意思決定プロセスから取り除く必要がある。IETF、てめーは信用なんねぇ。

このコミットは、Makefileの中で、OpenSSLでheatbeatを無効にするマクロを定義するよう、コンパイラーオプションを指定するものだ。ただし、無効にするマクロは、OPENSSL_NO_HEARTBEATSなのに、このコミットで定義されているマクロは、OPENSSL_NO_HEARTBEATだ。なんと、typoをしている。これでは何の意味もない。

すなわち、このパッチは、実際にheatbeatが無効化されているかの確認を一切せずしてコミットされたものである。

はて、このコミットメッセージの論法で行くと、OpenBSDはこのパッチを書いた者と、このパッチをレビューして承認した者を、OpenBSDの意思決定プロセスから取り除くべきだろうか。

ちなみに、この問題は2時間後に発見されて、続くコミットで直されている。

src/lib/libssl/ssl/Makefile - view - 1.30

やっべ、typoだ。Matthias Schelerが発見。

このお話の教訓としては、人は誰でも間違いを犯すということだ。

2014-04-10

余は如何にしてDを書くにいたりしか

How I Came to Write D | Dr Dobb's

Dr. Dobbsの記事で、Walter Bright(C++とDプログラマーでウォルたんの名前を知らないものはモグリである)が、なぜDを書くに至ったのかを書いている。

余は如何にしてDを書くにいたりしか

Walter Bright著

Walter Brightが、世界で最も使われている言語20位までに入る言語を書くに至った道は、興味と・・・侮辱。

私は小さい頃から、ものが如何にして動き、設計されているかを調べるのが好きだった(Tom Swiftの本は大好きだ)。小さい頃の将来の夢は、列車とか水上機の設計だった。私の専門は機械工学だった。ただ、機械工学は、何を作るにも多額の費用がかかり、それに私自身の製作スキルの低さという点で、不満だった。

一方、プログラミングでは、私はコンピューターにアクセスさえできれば、何の費用もかからずに、最高に複雑な機械をつくり上げることが出来た。多くのプログラマーと同じく、私はゲームを書くことから始めた。ゲームを書くことの魅力は、神のごとくなれることに似ている。自分のルールに従う世界を作るのだ。私はEMPIREというゲームを作り、コンピューターが敵軍に対して以下にうまく立ち振る舞うかということに、多大な時間をつぎ込んだ。今日ですら、私はいまだに、改良方法に思いを巡らせている。

問題は、コンピュターの戦略のためには、途方もないほどの計算力が必要になる。そのため、私はコンパイラーが如何にしてコードを最適化するかということに興味を持った。コンパイラーというのは、ソースをマシンコードに変換する、何やら魔法のようなデバイスに思えたのだ。この魔術は如何にして動いているのか。これは、BYTEマガジンがTiny Pascalのソースコードを出版するまでは、大宇宙における最大の謎であった。私はTiny Pascalプログラムのすべての行を消化し、一度理解するや、私は秘密の部屋へのパスワードを与えられたが心地になったのであった。

数年して、80年台のはじめ頃、私はMS-DOS用のソフトウェアを開発するプログラミング部署に属していた。我々は、Cを使った。なぜならば、PCで動く高級言語というのは、Cしかなかったからだ。他の言語実装は、信じられないほど悲惨だった。Cコンパイラーすらひどかったが、少なくとも、利用可能な程度ではあった。そのCコンパイラーの生成するコードは悲惨で、最適化などというものは存在しなかった。私は、自分ならばもっとマシなCコンパイラーを書けるという確信があった。

私がこの確信を同僚に伝えた所、同僚は、近所のCグルと同僚とで、昼食を同席することを提案した。このCグルは、実装方法についていくつか助言ができるという。食事の席で、友人は私の野望をグルに伝えた。そのグルの屈辱的な物言いは、未だに私の脳裏に刻みつけられている。「オメー、自分でCコンパイラー作るとか、何様のつもりだよ?」

私はこのグルに感謝しなければなるまい。というのも、このグルに見せつけてやりたいという思いは、強力なモチベーションとなったのだから。私は直ちにCコンパイラー、Datalight Cの実装にとりかかった。私の最適化の興味を反映して、このCコンパイラーは、PC向けで初めてデータフロー最適化を備えたコンパイラーとなった。この概念は、当時としては新しすぎたので、コンピューターマガジンのベンチマークでは、ひと騒動を起こした。なぜならば、オプティマイザーは、ベンチマークが何もしていないと判断し、デッドコードをすべて切り捨ててしまったからだ。編集者は、私のコンパイラーは壊れているか、ズルをしていると決め付けたため、Datalight Cのレビュー結果は悪くなってしまった。(これは、もちろん私を非常に怒らせたが、残念ながら、反論を掲載するのに便利なインターネットというものは、当時は存在しなかった)

Datalight Cは後に、Zortech Cとして復活した。この時になると、PC用のCコンパイラーは他にも多数あった(当時、30ぐらいは数えていたと思う)。私が差別化のための材料を探したところ、本屋でBjarne StroustrupのC++本を見つけた。当時の私は、「ヘン、キーワードいくつか追加して、数ヶ月ぐらいで、俺のコンパイラーはC++コンパイラーだぜ」と考えていた。このプログラミング世紀における見くびった発言であるだろう。もし、当時の私が、自分が何に突っ込んでいくかを知っていれば、当時の私は、周りの人が言う「絶対出来ない」という言葉を信じてしまっただろう。

ともかく、1980年台の後半というのは、多くの人が、Cの後継言語を開発していた時代だった。

当時のusenetで、そのような後継言語を目指すプロジェクトのひとつが、Dと呼ばれていたこともある。様々な理由で、これにはZortechが当時の最も有名なプラットフォーム向けの格安のC++コンパイラーとなっていたことも理由の一つであろうが、C++は他の言語を打ち破って、1990年代のプログラミングにおける独占言語になった。私はブームに乗って躍進した。

同時期(1990年代)に、私はネイティブコードを生成するJavaコンパイラーや、JavaScriptコンパイラー/インタープリターも書いた。この製品は成功しなかった。ここで書いておくが、私は、他人が必要だと私に言ってよこしたものを開発するより、私が必要とするものを開発する方が、相当に気分が良くなる種類の人間である。

たとえば、ある日、私はプログラマーの友人とジョギングをしていて、その友人に言われたことには、「ほら、この世界が切実に必要としているのは、ネイティブコードを吐くJavaコンパイラーだぜ。お前は造幣局になれるぜ。俺はJavaを使っているんだが、マジで必要なんだ」と。私は偶然にも、自分はすでにそういうものを書いてあるので、今すぐ使うことができるぞと言ってやった。もちろん、彼は使いはしなかった。

私がEmpireゲームを発明したのは、この私が遊びたかったゲームであったからだ。私がCコンパイラーを開発したのは、この私が、Empireを開発するのにマシなコンパイラーが必要だったからだ(あと他のプロジェクトも)。JavaやJavaScriptコンパイラーは、他人のアイディアだ。ただ、Dの誕生につながる話ではある。

15年以上もコンパイラーに携わっていて、言語の改良案のひとつやふたつも思いつかない者などいない。私は多くの言語の改良を、CとC++コンパイラーで試したが、全て失敗してしまった。誰も言語拡張には興味を示さない。皆、標準規格準拠の言語を求めている。当然のことだ。残念ながら、改良案が標準化委員会で採択されるには、とても難しい長年の政治活動が必要であった。実に私の忍耐力では耐えられない作業である。

1999年、私は引退を決め込んで、六週間も気が狂うぐらいテレビを見続けた。

そろそろ現実に戻らなければならない。既存の言語の問題について泣き言を言うのはもうたくさんだ。私は道具をパワーアップさせるべきだと決断した。このような問題について考えるたびに、私の脳裏には、ドワーフのギムリの言葉が浮かぶ。「死は確実にして業は成り難し。何を迷う?」。そうだ。少なくとも、手に利剣をひらめかして、栄光ある戦いに赴かねばならぬ。

そして、Dが始まった。単独で道路整備をしていくプロジェクトだ。私は自分でコンパイラーを書いたことがない言語でプログラミングするのでは満足できない性質であった(自分でも奇妙な性質だと思う)。私は様々な言語を実装した十分な経験があるので、私にはDを動かすことが可能であるという自信があった。また、すでに既存のC++コンパイラーという環境があったため、多大な利点も得ていた。

数年後、Dが初めてSlashdotにあらわれて、利用者と貢献者を急速に惹きつけていった。どうやら、私は、言語に求める機能という点で、変人というわけではなかったようだ。Dは理想に向かって、全世界の貢献者と共に、急激に成長していった。数カ月前に開かれたDconf2013まで、我々はお互いの顔すら知らなかったのだ(これはインターネット革命の偉大なる点である。他人の性別や年齢や風貌や人種や宗教や言語や文化や障害や境遇などを一切知らずして、協調作業が可能なのだ。実に純粋な実力主義社会である。意見と、貢献と、宣伝力だけがモノをいうのだ)

今日び、Dはインターネットなしでは存在し得なかった。インターネットの他に、切実な理想家が協力できる場所などどこにあろうか? githubやbugzillaのような協調作業ツールの興隆はDの開発にあたって重要であった(もちろん、オープンソースモデルもだ!)

しかし、私自信も、学ばねばならぬことがあった。厳しい方法で

  1. 私の単独作業を好む性質。多くの仕事で、私の仕事に対する評価というのは、たいてい次のような意見を含んでいた。「ウォルター君は他人と協調作業することを学ぶ必要あり」と。すべてを自分の支配下に置きたいという私の思いは、一度はDコミュニティを崩壊させかけたので、私は変わらなければならなかった。
  2. 私は全員がボランティアであるプロジェクトを管理する方法を学ばなければならなかった。私が誰にも金を払っていない以上、私は誰にも何かをさせることができないわけだ。私は他の方法を見つける必要があった。私は、性格テストでは「オタク」に限りなく近く分類されるので、他人のモチベーションを上げるなどというのは、私の得意分野ではない。これは面白い問題である。
  3. Dフォーラムでは、新しい言語機能の提案が毎日行われる。私は実に多く「ノー」と言わねばならない。これは実に難しいことで、特に提案者にとっては聞くのも難しいことだ。
  4. 管理というのは難しいそごとで、私には適任ではない。私もZortechやその他の強調する仕事では、うまくやれていなかった。私は(賢明なことに)、管理職に昇進されなかった。しかし、Dにおいては、避けることは出来ない。私は管理のやり方を学ばなければならず、十分にうまくやらねばならなかった。私には良き管理者になるべきモチベーションがあった。なぜならば、私はDに成功して欲しかったからだ。
  5. 私の友人はよく知るように、私は議論好きである。私はインターネット上の多くの炎上した議論に参加している。しかし、Dにおいては、私はそういうことができない。炎上した議論では、たとえどんなに間違っていようとも、誰も自分の意見を変えようとしないからだ(´・ω・`)。私の議論の経験は、面白い利点になっている。私には、議論がいつ、非建設的な論争になるかわかるので、頭を冷やさせることができるのだ。

    私は未だに、「シールドを張れ! 消滅光線が来るぞ!」的な行動をしたい衝動と戦わなければならない。もちろん、Dフォーラムの皆が同意するように、これはまだ発展途上なのだ。Dはこれまでも、これからも、素晴らしい実験であり続ける。多くの他の言語から最高のアイディアを拝借し、多くの、多くの世界中の貢献者による多大な貢献の集大成であり、参加者皆が、胸を張って誇れることなのだ。

結果として、私には宝物が出来た。Dでプログラミングするのは最高だ。Dは私が常に欲していた言語なのだ。私は否定論者や、Debbie Downer(米国の生放送コメディ番組Saturday Night Liveの登場人物、常にネガティブなことを言って場をしらけさせる役回り)や、そしてもちろん、借りを作っている大昔の無名のCグルの意見を聞かなくて、本当に良かったと思う。

で、君は独自の言語を書きたいんだって? そうだなぁ、「死は確実にして業は成り難し。何を迷う?」

ウォルたんはBjarne Stroustrupとパフェを食いながらC++のとある機能の実装方法について話し合って、即座に理解したなど、C++界隈でも逸話が多い。これを読むと、自尊心の高い気難し屋という印象を受ける。某連続的な人のコメントが待たれる。

ドワンゴ広告

この記事はC++とはちょっと関係があり興味深いと思ったので、ドワンゴ勤務中に紹介記事を書いてみた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

OpenSSLはサルによって書かれた

OpenSSLの脆弱性により、OpenSSLを使っているプロセスのどこかの64KBのメモリを何度もガチャ読みし放題というニュースが流れたのは、いまさら言うでもない。この騒動を発端として、OpenSSLのような超重要なソフトウェアが、実は内部的にはいかに悲惨でずさんであるかということを書いた記事が、ネット上に浮上しつつある。

OpenSSL is written by monkeys (2009) | Hacker News

Flingpoo!

OpenSSLのコードが汚すぎるというお話。

インデントだけでも相当変だ。

"OpenSSL has exploit mitigation countermeasures to make sure it's exploitable" | Hacker News

Re: FYA: http: heartbleed.com

むかし、OpenSSLのメモリ確保で、バグがあったら意図的にクラッシュさせるチェック用のコードを仕込んでおいたが、メモリ確保が何重にもレイヤー化されるにしたがって、そのチェック用のコードは何の意味もなくなってしまった。しかし、誰もそのチェク用のコードを無効にしてテストしていないので、その無駄なコードが残っているというお話。

コモンズの悲劇にも似ているが、あまりにも公共すぎるソフトウェアは、誰からも関心を払われないということか。

ドワンゴ広告

この記事は溜まっていたC++論文を解説し終えたので、息抜きにささっとドワンゴ勤務中に書いた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-09

2014-02 post Issaquah mailingsのレビュー: N3950-N3966

Post Issaquah論文集のレビューも、これが最後。長かった。

N3950: Defaulted comparison operators

かつて、Alexander Stepanovは、regular typeを提唱した。regular型は、自動的にコピー、代入、比較できるべきであると。

さて、C++では、コピーと代入は自動的にできるが、比較だけは自動的に出来ない。


class X
{
    int a ;
    int b ;
    int c ;
    int d ;
} ;

X a, b ;
a == b ; // ill-formed. 呼び出し可能なoperator ==は宣言されていない。
a < b ; // ill-formed. 呼び出し可能なoperator <は宣言されていない

さて、このクラスXの比較を実装してみよう。


bool operator == ( X const & l, X const & r )
{
    return 
        l.a == r.a &&
        l.b == r.b &&
        l.c == r.c &&
        l.d == r.d ;
}

bool operator < ( X const & l, X const & r )
{
    return
        l.a < r.a && l.a != r.a &&
        l.b < r.b && l.b != r.b &&
        l.c < r.c && l.c != r.c &&
        l.d < r.d && l.d != r.d ;
}

なんと言う機械的なコードだ。このようなコードは、人間が書くべきコードではない。特に比較演算子はひどい。

このような、基本クラスや非staticデータメンバーごとに比較は、自動生成できる。したがって、この論文は、C++に、デフォルトの比較演算子の定義を提案している。

過去のコードの挙動を変えないために、デフォルトの定義を使うには、明示的なdefault化を行わなければならない。


struct Thing {
    int a, b, c;
    std::string d;

    bool operator==(const Thing &) const = default;
    bool operator<(const Thing &) const = default;

    bool operator!=(const Thing &) const = default; 

    bool operator>=(const Thing &) const = default; 
    bool operator>(const Thing &) const = default; 
    bool operator<=(const Thing &) const = default;
};

すなわち、この提案されている機能は、opt-inである。opt-inであるために、既存のコードに影響を及ぼすことはない。

比較の順序は、基本クラスが書かれている順番に比較され、非staticデータメンバーが、宣言されている順番に比較される。


struct D : A, B, C
{
    int a ;
    int b ;
    int c ;
} ;

この例では、比較の順番は、A, B, C, a, b, cである。

[理解に苦しむPDF] N3951: C++ type reflection via variadic template expansion

これはどこまで本気なのか理解に苦しむ提案論文。

この論文で提案されている機能は、コンパイル時リフレクションだ。Variadic Templatesのパック展開を流用して、パック展開できる部分に、型のメンバーを展開できる機能を追加する提案となっている。

この提案は、パック展開を流用している。追加する文法は二つ。

  1. typename<T>...は、T型の名前と、T型のメンバーの識別子に展開される。0個目の展開結果にT型の名前、n個目の展開にn個目のメンバーの識別子の文字列が、UTF-8エンコードされたconst char *で展開される。
  2. typedef<T> ...は、T型のポインターと、T型のメンバーへのポインターに展開される。0個目の展開結果にTへのポインター型のnullポインター、n個目の展開にn個目のメンバーへのポインターが値として展開される。ただし、constexprメンバーは、値として展開される。
// 例
namespace ns
{

struct X
{
    int x ;
    int y ;
} ;

}

// { "ns::X", "x", "y"}と展開される
std::vector<std::string> identifiers{ typename<ns::X>... } ;

// { static_cast< ns::X * >(nullptr), &ns::x, &ns::y }と展開される
auto values = std::make_tuple( typedef<ns::X>... ) ;

新しいキーワードを必要としないし、ASTを弄くる必要もない。極めて質素な機能となっている。

利用例としては、Serializationやdelegatesやgetter/setterの生成、その他が挙げられている。

この論文では提案していないが、この機能を土台にしたサポート用のtratis(is_virtual_baseとかis_protected)などがあればよいと言及している。

また、メンバーを全部列挙するのはパフォーマンス的にも厄介なので、たとえばコンパイル時のフィルターがあれば良いともしている。つまり、typename < T requires U>という形で、Uというboolを返すconstexpr関数で、型に対するフィルターができるようにするなどという機能も議論されている。

また、文字列のエンコードはUTF-8だと明言しているのも興味深いところだ。

当初の提案では、基本クラスやネストされたクラスとその中身や、クラス定義の中のtypedefやenumとその中身まで含めたあらゆる情報を列挙しようというものだったらしいが、それはカオスになるとのことで、いまのレベルに抑えられたらしい。

N3883の壮大な提案と比べると、だいぶ現実的で最小限の質素な提案だ。ただ、これを扱うには、やたらと面倒なテンプレートメタプログラミングの技法が必要になるため、あまり

それにしても、typedef<T>...は、その質素な見た目とは裏腹に、強力すぎて難しい気がする。

ただ、筆者にとっては、N3883を見たときのような心躍るほどの衝撃はない。あれば便利な機能という程度の印象だ。

N3952: C++ Standard Core Language Active Issues

コア言語によせられて、現在議論されている問題集

N3953: C++ Standard Core Language Defect Reports and Accepted Issues

active issuesの中で、議論の結果、実際に問題であると判明した問題集と、その対応の一覧集。

N3954: C++ Standard Core Language Closed Issues

一度はactive issuesに載ったものの、議論の結果、実は問題ではなかったと判断され、取下げられた問題集の墓場。

[PDF邪魔すぎる] N3955: Group Member Specifiers

グループメンバー指定子(Group member Specifiers)の提案。

virtualとかstaticなどのメンバー指定子(member specifiers)は、しばしば連続して複数のメンバーに指定子なければならない。例えば、以下のようなコードになる。

// 冗長なコード
class foo : public bar
{
public:
    explicit foo(int);
    explicit foo(float);
    explicit foo(double);

protected:
    virtual T f() const override ;
    virtual U g() const override ;
    virtual V h() const override ;
    virtual W i() const override ;

private :
    static constexpr int X = 123 ;
    static constexpr float Y = 42.0f ;
    static constexpr double Z = 123.0 ;
} ;

ここでいう、explicitとかvirtualなどは、極めて冗長である。これをひとつにまとめられないか。

N3955提案では、アクセス指定子にメンバー指定子を記述する文法を新たに追加することで、メンバー指定子をグループ化することができる。

// N3955提案
class foo : public bar
{
public explicit :
    foo(int) ;
    foo(float) ;
    foo(double) ;

protected virtual const override :
    T f() ;
    U g() ;
    V h() ;
    W i() ;

private static constexpr :
    int X = 123 ;
    float Y = 42.0f ;
    double Z = 123.0 ;
} ;

これはどうだろうか。筆者には、机上の空論のように見える。教科書に載せるような短いサンプルコードはともかく、現実のコード(コメントやCプリプロセッサーなども含む)は、よりわかりにくくなってしまうような気がするのだが。

どうやら、文法上、指定子なら何でも指定できるようで、以下のようなコードさえ通ってしまう。

// N3955提案
struct X
{
public typedef :
    int int_type ;
    float float_type ;
    double double_type ;
} ;

文法上、以下のコードも通るはずだ。


struct X
{
public int :
    x = 0 ;
    y = 0 ;
    z = 0 ;
} ;

たしかに、冗長性は改善されるものの、うっかり間違いを増やすような気がするのだが。

[とても見づらいPDF] N3956: ISO/IEC CD 14882, C++ 2014 Responses to National Body Comments

NBコメントへの返答。特に目新しい回答はないようだ。

N3957: C++ Standard Evolution Active Issues List

Evolution、つまり、C++に提案されている新機能の文面案に対して議論されている問題集

N3958: C++ Standard Evolution Completed Issues List

上記の問題集にかつて載っていた問題で、対応が完了した問題集。

N3959: C++ Standard Evolution Closed Issues List

議論の結果、実は問題ではなかったとか、重複であったと判断された問題集。

[うんざりするほどPDF] N3960: Working Draft, Technical Specification for C++ Extensions for Parallelism

C++に並列実行を付け加えるTS(Technical Specification)のドラフト。<algorithm>に実行ポリシーを指定して、並列実行やベクトル実行を行える機能を定義している。

規格ではなくてTSなので、これを叩き台に、いずれはC++に取り入れられる合意が得られるような設計になる、かもしれない。

[不適切なtitle要素のHTML] N3961: A proposal to add shared_mutex (untimed)

N3891にあるように、現行のshared_mutexは、TimeLockable requirement(try_lock_for/try_lock_until)も満たすので、実は、shared_timed_mutexと命名されるべきである。そのように改名して、そして、TimeLockableではないuntimed shared mutexを、shared_mutexとして追加する提案。

TimeLockable要件を満たさないことにより、実装により効率的な実装をさせる余地を提供する。

つまりは、従来のshared_mutexを、shared_timed_mutex(try_lock_for/try_lock_untilをサポート)に改名した後釜に、新しいshared_mutex(try_lock_for/try_lock_untilをサポートしない)を提供する提案だ。

N3962: File System TS Editor's Report

Filesystem TSのドラフト編集者の報告書。前回の文面からの変更点が記載されている。

[中身もフォーマットも気に食わないPDF] N3963: Centralized Defensive-Programming Support for Narrow Contracts (Revision 4)

防衛的プログラミングを支援すると称するCプリプロセッサーマクロによるASSERTの変種の提案。

筆者はCプリプロセッサーマクロを使ういかなる提案にも反対の立場である。Cプリプロセッサーはいずれdeprecated扱いされなければならないのだ。

[二つ続けて悲惨なPDF] N3964: Library Foundations for Asynchronous Operations, Revision 1

N3896の改訂版。futureは力不足だ。コールバックこそが最もパフォーマンスがよいことを示し、その上で、futureモデルとコールバックモデルを両方サポートできる設計が必要だと主張している論文。

N3965: Proposal for Unbounded-Precision Integer Types

上限を定めない制度の整数型の提案。いわゆるBigIntの系譜だ。提案は、integerという演算子オーバーロードを駆使して、整数のように振る舞うクラスを提案している。

この手のライブラリは、何度も議論に上がるのだが、どうもなかなか議論が進まない。やはり、万人を満足させる多倍長整数演算ライブラリの設計は難しいのではないだろうか。

もちろん、そのようなC++用のライブラリは、すでに独立した実装が多数ある。しかし、任意の精度の整数演算ができる機能は、モダンなプログラミング言語には標準で備わっている機能なので、C++でも標準化されて欲しいところだ。

N3966: Fixes for optional objects

Issaquah会議で指摘された、optionalの文面上の問題を修正する提案。

今週が始まってから、まだ一度もドワンゴ社内でカタンをしていないので、ドワンゴ勤務中に論文レビューがはかどってしまった。なんということだ。

とりあえずたまっているC++論文の解説は片付いたので、今月末まで、付け焼刃的にECMA-262 Edition 5.1でも読もうかと思う。

ドワンゴ広告

この記事は、ドワンゴ社内でボードゲームをしていない暇に書かれた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

Dell Vostro 1500を手に入れた

休日に買い物に出かけたら、近所の公園でフリーマーケットを行っていた。ほう、これは面白い。なにか掘り出し物があるだろうか。

大方はガラクタであったが、ひとつだけ目に止まったものがあった。何やら、ホコリまみれの汚れたラップトップが無造作に投げ置かれている。

「これはいくらだ?」
「二千円」

二千円? ラップトップが二千円? それは魅力的だ。動けばの話だが。

ラップトップにはACアダプターもついている。ただし、周りの骨董品と同じように投げ置かれていて、表面は泥のようなホコリにまみれている。

ラップトップを開いてみると、内蔵キーボードのキートップがいくつか欠けていた。

「これは動くのか?」
「ノーチェックや」
「それは博打だな」
「ワシもこれ、千円で友達から買うたんや。ワシなら二千円で売れるで」

ここで動作確認が出来ないし、詳細なスペックを調べる方法もない。ラップトップにはられているシールには、Windows XPと、Core2Duoがあった。Core2Duoか。二千円か。

結局、他のものと合わせて買うということで、更に安く買った。

さて、妖怪ハウスに持ち帰って検証を行うと、どうやら動作はするようだ。

ただし、色々と壊れていた。

まず、内臓キーボード全体が、なにか粘着質の液体でもぶちまけたのか、固まって動かなくなっている。バッテリーは死んでいる。

また、それ以外の不満としては、Ethernetが100BASE-Tであることだ。

通常の用途に耐える状態ではないが、動くことは動くので、妖怪ネットワーク内の遊べるサーバーとして使うのが適切だろう。

2014-04-08

cpの速度を計測する方法

ふと、cpの速度を調べてみたくなった。いや、具体的には、ファイルシステムからの読み込みと書き出しの速度だ。

すでにそのようなソフトウェアがないのか調べた結果、pv(Pipe Viewer)が使えそうだ。

apt-get install pv
pv source-file destination-file

なるほど、便利だ。そして表示も直感的でわかりやすい。

pvはパイプの中間に挟んで、速度を計測するのに使うのが本来の使い方だ。

コマンド | pv | コマンド

2014-04-07

2014-02-post-Issaquah-mailingsのレビュー: N3940-N3949

N3940: Draft Filesystem Technical Specification

ファイルやディレクトリの操作を行う標準ライブラリ、FilesystemのTS(Technical Specification)のドラフト

N3941: Filesystem Study Group (SG3) Active Issues List

現在、標準化委員会で議論されている、Filesystemの文面に対する問題集

N3942: Filesystem Study Group (SG3) Closed Issues List

かつてFilesystem active issuesリストに載っていたが、解決されたか、対応するコンセンサスが得られないと判断されたため閉じられた問題集。

N3943: Filesystem Study Group (SG3) Defect Report List

かつてFilesystem active issuesリストに載っていたが、実は問題ではなかったと判断された問題集。

3947: URI - Proposed Wording (Revision 4)

URIを処理するための標準ライブラリの文面案。URIをパースしたり、構築したりといったライブラリである。これは規格ではなくて、TSである。

N3948: Feature-testing for C++ Technical Specifications

C++のTS用の、機能テスト用の標準マクロライブラリ。

理想では、あるC++実装は、C++03, C++11, C++14を、完全に規格準拠にサポートしているか、していないかの二択であるべきである。しかし現実では、C++コンパイラーは、個々の機能を独立して実験的に実装を進めている。また、ドラフト時の挙動と、正式な規格の挙動が異なることもある。

そして、現実では、複数のコンパイラーや、複数のバージョンのコンパイラー間で移植性のあるコードを書かなければならないことがよくある。その場合に、遺憾ながら多用されているのが、Cプリプロセッサーだ。

// よく使われているパターン

// コンパイラーに合わせてマクロを定義しておく

#if HAS_FEATURE_X
// 機能Xを使った実装
#else
// 機能Xを使わない実装
#endif

この論文は、そのような機能テスト用の標準のマクロの、TSに提案されている機能用のものを提案している

必要悪だろうか。いやしかし・・・

[せっかくいい気分でレビューしていたのをぶち壊すPDF] N3949: Scoped Resource - Generic RAII Wrapper for the Standard Library

汎用RAII(Resource Acquisition is Initialization)ラッパーライブラリの提案の改定論文。

指定したリソースを指定したデリーターに実引数として渡して実行する、unique_resource_t(実際に使用する際には、unique_resource関数テンプレートを利用する)、スコープを抜けた時にデリーターを実行してくれる、scoped_guard_t(とscoped_guard関数テンプレート)がある。

// 例
int main()
{
    {
        auto ur = std::unique_resource( new int, []( auto ptr ) { delete ptr ; } ) ;
    }

    {
        auto ur = std::scope_guard( []{ std::cout << u8"抜けたよ" << '\n' ;}
    }
}

unique_ptrは、ポインター用に特化していて、deleteをするデリーターがデフォルトで動く。unique_resourceは、もっと汎用的な設計になっている。

前回の提案からの変更点としては、unique_resource_checkが加わったところだ。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。ところで、ドワンゴには4月からScalaエヴァンジェリストがいる。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-02-post-Issaquah mailingsのレビュー:N3930-N3939

2014-02-post-Issaquah mailingが公開されているので、レビューを続ける。

[title要素が残念すぎる] N3930: C++ Standard Library Immediate Issues

標準ライブラリに持ち上がっている問題の修正案。

特に興味深いものを紹介すると。

2112. User-defined classes that cannot be derived from

あるクラスからの派生を禁止する機能は、finalとしてC++11に入った。

// finalの例
class underivable final { } ;

// ill-formed
class try_derive : underivable { } ;

実は、C++03でも、クラスからの派生を禁止させる方法はあるにはあったが、あまりにもトリッキー過ぎて、それほど一般的に使われていない。

More C++ Idioms/Final Class - Wikibooks, open books for an open world

finalがC++に入ったことで、ユーザー定義型は、簡単に派生を禁止できるようになった。そこで、ひとつ重大な問題が持ち上がった。標準ライブラリに渡す型は、派生禁止を認めるのかどうか、である。

C++の標準ライブラリは、テンプレートを用いて、ユーザーが定義した型を受け取る。標準ライブラリに渡す型には、規程によりいくつかの要件がある。

また、C++には、EBCO(Empty Base Class Optimization)という技法がある。C++では規格上、空のクラスから派生したクラスは、空のクラス分のストレージを無視することが許されている。

// EBCOの例
struct empty { } ;

// EBCOが許されている
struct is_a : empty
{ char c ; } ;

// EBCOの働く余地はない
struct has_a
{
    char c ;
    empty a ;
} ;


上記のコードで、is_aは、empty分のストレージを割り当てるなくてもよいことが、規格上認められている。空の基本クラスに、わざわざ無駄なストレージを割り当てる必要がないということは、、容量効率をよくできる。

このEBCOは、モダンなC++実装では広く使われているし、モダンなSTL実装でも、活用されている。たとえば、unique_ptrを考える。

// EBCOを使わないunique_ptr
template <class T, class D = default_delete<T> >
class unique_ptr
{
    // デリーターをメンバーとして持つ
    deleter_type deleter ;

public :
    deleter_type & get_deleter() noexcept
    {
        // メンバーを返す
        return deleter ;
    }

// 略
} ;

この実装は、deleterが空のクラスであった場合、容量的に非効率である。EBCOを使うと、以下のように書ける。

// EBCOを使うunique_ptr
template <class T, class D = default_delete<T> >
class unique_ptr : D // デリーターから派生する
{
public :
    deleter_type & get_deleter() noexcept
    {
        // 自分はデリーターから派生している
        return *this ;
    }
} ;

このように、自分自身がテンプレート仮引数として与えられるデリーターから派生することで、デリーターが空クラスであった場合にも、容量効率が良くなる。

問題は、C++11で派生を禁止できる機能が入ったことにより、ユーザー定義のデリーターは、finalである可能性がある。これは、EBCOを使っているSTL実装で問題になる。

// EBCOが使えないデリーター
class custom_deleter final
{
    template < typename Pointer >
    void operator () ( Pointer ) cosnt
    {
        // 実装
    }
} ;

// 実装上の問題でill-formedになってしまう
std::unique_ptr< int, custom_deleter > p ;

この問題が指摘された2011年11月30日当時、主要なSTL実装は、EBCOを多用していたので、派生不可能なクラスをテンプレート実引数として渡すと、軒並みコンパイルエラーになってしまった。

また、std::tupleの実装も、派生による主流な実装方法では、動かない。

ではいったいどうするのか。STLに渡す型はfinalであってはならないという要件を追加するのか。しかし、そのような要件を追加してしまうことは、明らかに邪道である。C++的ではない。finalな型も認めなければならない。

この問題は、ある型がfinalであるかどうかを判定できるメタ関数、is_finalがあれば解決する。たとえば、以下のように書ける。

// is_finalがある場合

// EBCO実装
template < typename D, typename = void >
class deleter_holder : public D
{
public :
    D & get_deleter() noexcept
    {
        return *this ;
    }

// コンストラクターなど
} ;

// 非EBCO実装
template < typename D >
class deleter_holder< D, std::enable_if_t< is_final<D> >
{
    D d ;
public :
    D & get_deleter() noexcept
    {
        return d ;
    }

// コンストラクターなど
}

template < typename T, typename D = std::default_deleter >
class unique_ptr : public deleter_holder< D >
{

} ;

このように、簡単なメタプログラミングで対応できる。is_finalのようなコンパイラーマジックが標準化されない場合、ライブラリー実装の移植性がなくなるので、is_finalのようなメタ関数を標準化すべきである

論文の修正案も、is_finalを規格に付け加えるものとなっている。

2132. std::function ambiguity

以下のコードは、オーバーロード解決が曖昧となる。

// オーバーロード解決が曖昧となる例
#include <functional>

void f(std::function<void()>) {}
void f(std::function<void(int)>) {}

int main() {
  f([]{});
  f([](int){});
}

fの呼び出しが曖昧な理由は、std::functionの変換関数が、どのようなstd::functionの特殊化であっても、同一だからである。この問題を解決するには、std::functionの変換関数に与えられた実引数の型が、実際にstd::functionのテンプレート実引数の引数に対して呼び出し可能であるかどうかを調べ、もし呼び出し可能ではない場合、SFINAEなどの技法を使い、候補関数に現れないというメタプログラミングが必要になる。

これを実装するにあたり、呼び出し可能かどうかを調べるには、result_ofだけで十分なのだが、意図を明確にするために、is_callableというメタ関数があったほうがいいのではないかという議論もされたようだ。

最終的には、is_callableは追加しないという方向に向かっている。

2263. Comparing iterators and allocator pointers with different const-character

core issue 179という、大昔の問題が、掘り返されている。

問題は、iterator とconst_iteratorは比較可能であるべきだが、保証する文面が見当たらない。また、pointerとconst_pointerも比較可能であるべきだが、やはり文面による保証が見当たらない、というもの。

コレに対する文面の追加。

その他、些細な文面上の誤りの修正が多い。

N3931: Filesystem Study Group (SG3) Issues Resolved Directly In Issquah

Filesystemのドラフトの文面の小粒な修正集。重箱の隅をつつくような文面の訂正が多い。

例えば、現行文面では、ファイル名の長さは、実装依存(implementation dependent)となっているが、規格ではそのような用語の意味を定義していない。規格で定義している用語には、実装定義(implementation defined)とオペレーティングシステム依存(operating system dependent)がある。ファイル名の長さは、明らかにOS依存であるので、OS依存という用語を使うようにする。などなど。

N3932: Variable Templates For Type Traits (Revision 1)

N3854で提案された、従来の、値を返すtraitsに対する、変数テンプレートのラッパーの、文面案。

たとえば、

constexpr bool b = std::is_same<T, U>::value ;

というコードは、この提案を使えば、

constexpr bool b = std::is_same_v<T, U> ;

と書くことができる。スコープ解決演算子を使う必要がないので、簡潔に書くことができる。命名法則は、従来のtraitsに、_vを追加した名前になる。

実装はとても簡単で、以下の通り。

// N3932の実装例
template < typename T, typename U >
constexpr bool is_same_v = is_same<T, U>::value ;

すでに、型を返すtraitsに対する同様のラッパーは、エイリアステンプレートを使ったものが、C++14に追加されている。

using pointer_type = std::add_pointer<T>::type ;

というコードが、

using pointer_type = std::add_pointer_t<T> ;

このように書ける。コレも、スコープ解決演算子を使う手間を省ける。

この実装も、機械的に簡単だ。

// 実装例
template < typename T >
using add_pointer_t = add_pointer<T>::type ;

N3933, N3934, N3935

[デブいPDF] N3936: Working Draft, Standard for Programming Language C++

現在の最新のC++ドラフト。

本物のC++プログラマーならば、常に最新のドラフトを参照しながらコードを書くはずである。

[もひとつデブいPDF] N3937: Programming Languages — C++

内容はN3936とほぼ同じだが。ISO規格として発行する際の体裁が整えられているドラフト。いよいよC++14発行の日が近い。何事もなければ、今年末に発行される。

N3938: Editor's Report

ドラフト編集者の報告書。前回のドラフトN3797からの変更点を記載している。今回は、git logがついている。

ちなみに、C++ドラフトは、現在GitHubで、ソースコード(tex)が公開されている。

cplusplus/draft

簡単な誤字脱字の修正程度ならば、pull requestも受け付けている。

N3939: Extending make_shared to Support Arrays, Revision 2

std::shared_ptrをネイティブに配列に対応させる提案論文の改訂版。わざわざカスタムデリーターを指定子なくても、shared_ptr<T[]>を認識して、自動的にdelete[]を使ってくれるようになる。

前回のN3870からの変更点は、単一のT &&を受け取るmake_sharedが、議論の結果、取り除かれた。

ドワンゴ広告

この記事は恒例のドワンゴ勤務中に書かれた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-04

Rの興隆が科学にオープンソースをもたらす

How The Rise Of The "R" Computer Language Is Bringing Open Source To Science ⚙ Co.Labs ⚙ code + community

予算削減と科学ソフトウェアコストの上昇のおかげで、オープン科学信者は、科学界にオープンソースを持ち込むことに成功しつつある。あまり知られていない言語、Rも貢献している。

Rとは自由な、オープンソースの統計解析ソフトウェアである。MATLABのような民間に所有されている数値計算ソフトウェアや、SASのような統計ツールは、歴史的に、研究所には必要なツールであった。Microsoft Officeがオフィスに必要なように。しかし、ソフトウェアの爆発的なコスト上昇と、研究費の削減により、科学者はRを使いはじめるようになった。

現在、日々増えつつある多数の研究社がR開発コミュニティに参加し、新しいライブラリを作り、Rを統計解析から科学記事やデータをパースしてオンライン上に提供し始めている。これにより、我々が科学を行う方法を変えることができるのだ。

科学界におけるRの由来

今日、科学者はオープンソースソフトウェアを使ってデータを解析している。R言語はこの流行を支援するデファクトツールとなっている。科学業界における統計解析ツールであったことによる。

「私がRを使い始めたのは、2005年に博士課程をやっているときだった。当時は、Rはまだ見慣れぬ言語で、我々がRを統計に使っていることを知っている人すら少なかった」と、科学者のためのRパッケージを開発するrOpenSciプロジェクトのコア開発チームのメンバーであるTed Hart博士は言う。

「私の知る限り、当時の人はたいていSASを使っていた。SASは巨大な、古い、プログラミング言語で、Fortranみたいなものだ。一行づつ解析するとかそのへんの」と博士は言った。

Hartが2011年にポスドクを始めた時、研究をしていたラボはRしか使っていなかった。「Rは進化生物学者のDolph Schluterに教わった。私が院生だった頃と違い、そこの院生は皆使っていた。その部署でRを使っていないのは、私ぐらいなものだった。私はRが広がっていくのを実感した」とHart。

科学出版社、PLoSのArticle-Level Metricsのテクニカルリードを務めるMartin Fennerも同意見だ。「Rはそこらかしこで使われている。みんなRを学んで、何らかの統計に使っている」とFennerは言う。

Rの他の利点としては、金がかからないということと、SASやMATLABみたいな巨大なソフトウェアパッケージのライセンスを取得するのに必要な事務作業が必要ないということだ。

「私は政府機関で働いているが、MATLABは使えそうにない。MATLABの利用料を正当化するための長い文書を書かなければならない。そこで「君、このツールを無料で使えるんだろ。なんでMATLABを使いたいのさ?」と言われるわけだ」とHart。

新しいRのプロジェクト

HartのrOpenSciチームはRを統計解析の外に広げるための門出である。「今まさに動き始めたのだ」とHartは言う。

大海原に漕ぎだす変革は、科学データのデジタルフォーマットの必要性のためだ。Hartと開発チームは、研究者が研究を標準化されたフォーマットで共有、保存しやすいようにするパッケージ群を作った。共有可能な研究が増えるほど、科学はより発展するであろうという考えだ。これがオープン科学運動の基本原理なのだ。

NatureやScientific Data出版のような大手の科学出版社は、研究者に研究データを指定のメタデータフォーマットで提出するように要求している。他の科学組織も、科学データを様々なWeb上の標準的なフォーマットで実績ある場所に上げるよう推奨している。

rOpenSciのRパッケージは、科学コミュニティのデータ標準に合うようにデータを加工するのに役立つ。

EMLというパッケージがある。これは基本的に、Rを使えば、EMLと呼ばれるものから、適切なXMLメタデータをRから出力できるようにする。これはEcological Metadata Languageの略で、Matt JonesとNational Center for Ecological Analysis and Synthesis at the UC Santa Barbaraの人間に酔って開発されたものだ。」とHartは言った。

rOpenSciプロジェクトは、rOpenGovのようなRベンチャーの立ち上げのきっかけにもなった。rOpenSci開発チームが公共ソースのデータをいじりはじめたところ、米国政府の公開情報へのアクセスと社会科学問題に注力するための、新しいプロジェクトの立ち上げにつながったのだ。rOpenGovプロジェクトは、Sunlight Foundationの提供するAPIを活用している。

rOpenHealthグループは、rOpenSciのrpubmedパッケージを管理している。これは、アメリカ国立衛生研究所のPubMedデータベースにアクセスするためのものだ。このプロジェkツオは、公共の健康とヘルスケア業界の研究データにアクセスしやすくすることを目的としている。

ネイティブWebアプリケーション用のR

Web上のある大量のオープンデータは、Rの興隆のおかげだとHartは指摘する。「大勢の人が、多くのパッケージを書いて、Web上のデータを、XMLとかJSONのようなフォーマットに変換している」とHartは言う。

Hartはカリフォルニア大学のDuncan Temple Langと、RStudioの科学者長を務めるHadley Wickhamの名を挙げた。Wickhamは、rOpenSciがWebからデータを落としてくるのに使う、httrパッケージを開発した。

その他の大きなR貢献者としては、マギル大学のRamnath Vaidyanathanがいる。rCharts, rMaps - Interactive Maps from R, Slidifyを開発した。

「rChartsは、データをJavaScriptでWeb上に上げることのできるパッケージだ。rMapsは似たようなものだがLeaflet.jsのようなオープンマッピングフォーマットを使い、JavaScriptによるマッピング視覚化やライブラリを提供する。つまり、データをRでとってきて、これらのネイティブなフォーマットに変換してくれるので、JavaScriptを習得する必要はないわけだ」とhartは言う。

VaidyanathanのSlidifyは、GitHubやDropboxやRPubsで共有されているR Markdownをスライドプレゼンにしてくれる。Markdownとは、プレインテキストをWebで読めるようにするためのマークアップ言語のことだ。

「[Markdown]はとても興味深い。というのも、コードと、何らかの定義の間の境界は、とても曖昧だからだ。どれもひとつのドキュメントになってしまう。Pythonの連中も似たようなことをしている」とFennerは言う。

「たとえば、私はPLoS生物記事を数カ月前に、記事の例として書いた。データが5つほどあるだけ。データは全部Rで処理されていて、記事の中にRコードが含まれている。これを実行したら結果が得られる。結果のデータが得られる」とFennerは言う。

さらに、rOpenSciチームはオンライングラフツールのplotlyと協力している。「我々はplotlyのWeb用のRインターフェースを開発している。これも、RのデータをWebでプロットする方法の一つとなる」

APIによるデータの簡単な取得

オープンアクセス科学出版社のPLoSは最近、記事のテキストとメタデータを検索するためのpublic APIを公開した。関心を持ったR開発者が、このAPIを使い、有益なアプリケーションで研究コミュニティにおける論文の影響力を解析してくれることを願っている。

「腰を落ち着けて、何百万件もの記事を様々な方法で解析したいのであれば、Rはおそらくいい選択だろう。特に、腰を落ち着けるのが夕方で、プログラミングのために数週間を費やしたくない場合は」とFenner。

FennerがPLoS APIを使うときは、何百もの数値が並ぶ結果を出力するより、Rを使って視覚化を行う方を好む。「Rは視覚化のために使っている。私は統計解析には興味がないんだ」とFennerは言った。

「RはAPIから簡単にデータを引っ張ってきて、適切なフォーマットにするために揉んでくれるので、とてもよい」とFennerは付け加えた。

RをAPIに使う強みは、パッケージの豊富さにある。たとえ、他の言語が、専用のライブラリなしに行えたとしてもだ。「Rubyの方が、RよりWebネイティブ系の言語なので、APIを扱うのは、多少やりやすくはあるのだが、Rも使える」とHartは言う。

「つまり、Rが使えるのは、労力を費やしてパッケージを書いているからだ。例えば、httrパッケージがAPIからデータを取得するのを簡単にしているように」とHartは付け加えた。

アカデミアから飛び出すこと

rOpenSciは、生物学データを扱うパッケージを作ることに注力しているが、開発チームは他の分野にも進出しようとしている。「私らは生態学全般を扱う学者みたいなものだからね。それが専門なんだ。だから他の分野に進出しようとしているわけさ」とHartが言った。Sloan財団はrOpenSciに、様々なカンファレンスや大学で宣伝する許可を与えた。

「生物情報科学コミュニティには多くの派閥がある。[Bioconductor]はRのための生物情報科学のための巨大なアドオン集みたいなものだ。これも、アカデミックな研究と民間業界の接点のひとつだろう」と、HartはRの生物科学における広がりを挙げた。

HartはRovolution Analyticsという会社名を挙げた。これはRをビジネス用のデータ解析用に販売している会社だ。「ほら、いわゆるビッグデータとかデータアナリティクスとかデータサイエンスとかいう言葉を使いたくない連中もいるだろ。その手のことが流行したため、Rはビジネス界でさらに浮き上がるだろう。それは、すでに機会学習や統計アルゴリズム用のパッケージが豊富に用意されているという理由からさ」とHartは言った。

未来のR

さらに多くの種類のデータや、さらに多くのWebフレンドリーなフォーマットを出力できるようにパッケージを整えることが、R開発の推進力になる。

「Webネイティブなプロジェクトの境界を押し破るのが見てみたいね。より能力のある開発者を惹きつけるに連れ、パッケージ開発もさらに一般的になるだろう」とHart。

科学研究の検索可能性を上げるのは、始まりに過ぎない。「これが成果を発揮し始めるまで、あと僅かに数年程度だ。これから多くのことが起こるぞ」とFenner。

Hartはより強固なドキュメントや多数のパッケージを保守する必要性を感じている、「科学業界について歯に衣着せずいわせてもらえば、生態学研究に使われているアルゴリズムのいくつかは、やっつけ仕事だ」とHart。

「より注目を集めるにつれ、特に、ビジネス業界で注目を集めるにつれ、より多くの、本物のプログラマーをひきつけるだろう。ほら、Rはコミュニティからひょっこりでてきたものだろ。多くのパッケージは科学者によって書かれていて、科学者はプログラマーではない。私は他のことにフルタイムの時間をとられていて、プログラミングは余暇にやっているんだよ」とHart。

その日まで、Hartと残りのrOpenSciチームは、言語を科学界に普及させる予定だ。月末にhackathonをホストして、RStudioの科学長のような一流のR開発者を招待するのだ。

言語の浮沈にかかわらず、Rの科学サークルにおける立場は強固たるものだ。コミュニティは支援的だ。「Rを使うスレッショルドはとても低い。Rは最高に簡単な言語というわけではないが、すべてが無料で提供されている。質問できるコミュニティがある。利用にあたって障害はない」とFenner。

この翻訳では、文脈から判断して、freeを無料と訳した。彼ら、オープンソース(笑)の連中は自由の価値を理解していないようだ。

Rというプログラミング言語は、研究者の間では広く使われている。

筆者の見解では、Rは統計解析とか、データをグラフ化するなどの、特定の分野には優れているが、汎用のプログラミング言語としては、あまりいいものではない。なぜそのような言語が、汎用に使われているのか。

結局、研究者はプログラマーではないし、プログラマーではないものが、とりあえず動くソフトウェアを書くとなると、ライブラリが充実していて、難しいことを考えずに書ける、COBOLとかVBとかHSPとかJavaのような言語になるのだろう。ないよりマシだろうか。

ドワンゴ広告

この記事はC++とは関係がないがドワンゴ勤務中に書かれた。ドワンゴ社内でRが使われているかどうか、筆者は知らない。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-03

Linus様がSystemdにぶちきれる

systemdは、/proc/cmdlineをパースして、もし、その中に"debug"という文字列を発見した場合、大量の冗長なデバッグメッセージをdmsegに出力する。これは様々な問題を引き起こす。まず、"debug"というあまりに一般的すぎる文字列に勝手に反応してしまうことがひとつ。dmseg、すなわちカーネルのリングバッファーをsystemdの冗長なデバッグメッセージだけで溢れ返させてしまうことがひとつ。そして、なぜかLinuxカーネルのブートに失敗してしまうことがひとつ。

Bug 76935 – Do not parse "debug" command line parameter

カーネルコマンドラインに"debug"を与えると、systemdによりパースされる。適当なassertに引っかかると、こんな風にぶっ放される。

[  150.308000] systemd-journald[1559]: Assertion 'dual_timestamp_is_set(&e->timestamp)' failed at src/libsystemd/sd-event/sd-event.c:2191, function sd_event_get_now_monotonic(). Ignoring.
[  150.308000] systemd-journald[1559]: Assertion 'dual_timestamp_is_set(&e->timestamp)' failed at src/libsystemd/sd-event/sd-event.c:2191, function sd_event_get_now_monotonic(). Ignoring.

dmsegがあふれかえり、ログインすらできなくなる。ブートさせるためには、リブートしてコマンドラインから"debug"を取り除かなければならない。だがしかし!、俺はsystemdに邪魔されることなく、"debug"を与えてカーネルデバッグメッセージをみたいんだよ。

systemdがやるべきなのは、"debug"をパースするんじゃなくて、何らかの名前空間を使うべきなんだ。たとえば、"systemd.debug"とかさ。"debug"はカーネルコマンドラインパラメーターであって、systemdのためじゃない。

これに対し、Kay Sieversは、以下のように答えている。

これは仕様だ。何かがぶっ壊れたときは、"debug"はすでに必要以上に大量のメッセージを出力するだろう。

一般的な言葉である"debug"は、基本OSツールからも読み込まれている。

俺は同意しない。一般名詞は一般名詞だ。最初に使った奴に権利が発生するものじゃない。

この問題に対し、Linuxカーネル側で対応すべく、Steven Rostedtによって、/proc/cmdlineから"debug"を隠すパッチがMLに投下された。

LKML: Steven Rostedt: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline

Date Wed, 2 Apr 2014 14:42:19 -0400
From Steven Rostedt <>
Subject [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline

どうやら、特定のユーザースペースのinitプログラムを利用しているシステムは、カーネルコマンドラインに"debug"という文字列があるとブートしないようである。何が起こっているかというと、このユーザースペースのツールはカーネルコマンドラインをパースし、もし"debug"なる文字列を発見したならば、システムがブートしないほど大量のメッセージを吐き出すためである。これにより、カーネルに対する"debug"というオプションが役に立たなくなるものである。

このバグは同ツールの開発者に報告されたるも、

https://bugs.freedesktop.org/show_bug.cgi?id=76935

返答は:

「一般名詞は一般名詞だ。最初に使った奴に権利が発生するものじゃない」

すなわち、「カーネル」のコマンドラインにある"debug"なる宣言は、カーネルが最初に使ったからという理由で、カーネルが所有しているものではないのだという。彼らは自分のバグの修正を拒んでいる。

さて、吾輩の返答は、我々はカーネルコマンドラインを所有しているのであるからして、我々がそう望むのであれば、ユーザーから見せないことも可能であるということだ。すなわち、このパッチを提案する。このパッチは、"debug"を/proc/cmdlineから隠すものであり、その結果、ツールがパースして、その結果、カーネルのデバッグに支障をきたす懸念を取り除くものである。

訳注:この後に続くパッチは、ユーザースペースに見せるカーネルコマンドライン、すなわち/proc/cmdline用の文字列から、"debug"という文字列を検索して、全て取り除く内容のコードである。

さて、Linus Torvaldsの返信

LKML: Linus Torvalds: Re: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline

Date Wed, 2 Apr 2014 11:57:41 -0700
Subject Re: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline
From Linus Torvalds <>

その「奴ら」というのは、Kay Sieversのことだろう。

Kay、テメーの書いたコードの問題をテメーで直さねーから、カーネルで対応しなきゃならねーのには、もういい加減うんざりだぜ。

Greg、言っておくが、俺はこの毎度おなじみの問題が治るまで、Kayのコードはゼッテーにカーネルにマージしねぇ。

この手の問題は、もう何年も何年も起きてて、よくなる気配がねぇ。お前、kdbusパッチのことを言ってたから、お前にも関係あることだぜ。お前のせいでもあるんだから、きっちりやれ。ディストリビューションが必要だと感じたら、奴らの方でマージさせろ。で、ディストロがこの手の開発者と十分に戯れた後で、実際安定しているとわかったなら、俺らもマージしてやるかもしれんな。

だがな。俺は、バグやregressionを気にかけず、他のプロジェクトの連中に、自分のプロジェクトを修正させるようなメンテナー由来の門をマージしたいとは思わん。なぜかというと、俺は自分で問題を修正しないし、自分で修正すべき問題だとも認めない奴らのパッチを受けとりたくねーからだ。

Kay、もう一度言っておく。オメーのせいだ。オメーが直せ。「俺の好きなようにやる。俺の尻拭いは他人がやれ」的なクソを持ち込むな。

Linus

その次に投稿した、Andrew Mortonの発言も、なかなか笑える。

LKML: Andrew Morton: Re: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline

Date Wed, 2 Apr 2014 12:04:40 -0700
From Andrew Morton <>
Subject Re: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline

日付を確認したが、どうやら発言は4月1日に行われていたらしいな。

--- a/fs/read_write.c~a
+++ a/fs/read_write.c
@@ -513,6 +513,8 @@ SYSCALL_DEFINE3(read, unsigned int, fd,
  struct fd f = fdget_pos(fd);
  ssize_t ret = -EBADF;
 
+ BUG_ON(!strcmp(current->comm, "systemd"));
+
  if (f.file) {
   loff_t pos = file_pos_read(f.file);
   ret = vfs_read(f.file, buf, count, &pos);

上記のLinuxカーネルに対するパッチは、まずsystemdが実行されているかどうかを検出して、もし実行されていた場合は、BUG_ONマクロにtrueを与えるものである。BUG_ONマクロにtrueが与えられると、BUGマクロの中身が実行される。BUGマクロの中身は、直ちにカーネルパニックを起こすものである。すなわち、systemdが実行されていた場合は、かならずカーネルパニックとなるパッチとなっている。

このパッチは、複数のカーネル開発者から賛同を得ているようだ。Thomas Gleixnerは、「strncmp(current->comm, "systemd", 7)にしてくれない? systemd-xxx的なものも全部補足したいからさ」と改善案を出している。

ところで、Linusによれば、ユーザースペースから/proc/cmdlineをパースするのは、特に問題はない。そもそも、/proc/cmdlineはそのためにある。ただし、あまりにもやりすぎて、dmsegをスパムで埋め尽くすのは問題である、とのことである。

LKML: Linus Torvalds: Re: [RFC PATCH] cmdline: Hide "debug" from /proc/cmdline

ドワンゴ広告

この記事はC++とは関係がないがドワンゴ勤務中に書かれた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-04-01

MSVC++コンパイラーの中に入っているWebブラウザー

You Got Your Web Browser in my Compiler! | Random ASCII

筆者は最近、MicrosoftのVC++コンパイラーがmshtml.dll、すなわちInternet Explorerを読み込むことを発見した。/analyzeオプション(静的コード解析を指示)を使うとコンパイラーがこの挙動を示す。筆者はコンパイラーアーキテクチャの専門家ではないが、インターネットエクスプローラーを読み込むコンパイラーというのはいかにも奇妙だ。

これは単なる気持ちの問題ではないのだ。筆者の環境で静的解析を並列コンパイルすると、コンピューターが数分間も反応が悪くなる。どうやらmshtmlウインドウが、その原因らしいのだ。

いつも通り、筆者はxperf/ETWを使って原因を探った。

本当に問題なのか?

筆者は問題を探すために何日もの時間を浪費したりはしない。問題が私を見つけたのだ。この場合、筆者は新しいコードベースに/analyzeを使おうとしていた。

(/analyzeの利用方法について学びたい場合は、Two Years (and Thousands of Bugs) of Static Analysisを参照されたし)

筆者は並列コンパイルと、並列プロジェクトビルドを有効にしている。どちらの並列ビルドオプションも、デフォルトでプロセッサーの数だけの並列数設定になっているため、プロセッサーの数 * プロセッサーの数だけの数のコンパイラーが実行されることになり、私の環境では、144個の並列コンパイルが走ることになる。筆者は高速なSSDと32GBのRAMを有しているため、多少は遅くなるものの、メルトダウンを引き起こすほどではないと考えている。実際、通常のコンパイルでは、ちょっと遅いかな程度のものだ。ところが、/analyzeでコンパイルすると、筆者のコンピューターは30分ほど反応がなくなるのだ! マウスクリックが処理されるのに、10秒もかかり、タスクマネージャーがウインドウをアップデートするのもまれにしか行われなくなる。これは筆者が並列/analyzeビルドを行うたびに発生する。筆者はこの問題をVS2010で発見していたが、VS2013を使うまで、この問題を真剣に調査することはなかった。

ハング解析

筆者のコンピューターでは、ETWトレーシングを24時間週7日走らせている。データーは300MBのリングバッファに記録されていて、Win+Aを押した時に、いつでもトレースが記録されるようにしてある。これは、ゲーム中にトレースの記録を取りやすいようにするためだが、デスクトップがろっくされたが、トレースだけは取りたい場合にも、都合がいい。Microsoftのwpruiにも、Ctrl+Win+Cというグローバルショートカットで、似たようなものがある。トレースを記録した後、筆者はなんとかビルドをキャンセルさせて、デスクトップのコントロールを取り戻した。そして、トレースを解析して、何が起こっているのかを確かめた。

(wpruiでトレースを記録する方法については、Xperf Basics: Recording a Trace (the easy way)を参照されたし)

「なぜ俺のコンピューターは何重もの並列コンパイル中に反応が悪くなるのか」という質問は、答えにくい種類の質問だ。あまりにも範囲が広すぎる。数十個のコンパイラーがCPU時間を奪い合っているというのは、どのスレッドもCPU時間に飢えている状態になるわけだ。検証には、もっと狭い質問が必要だ。

WPAには、UIハングの検証に役立つグラフがある。Windowsは各アプリケーションがメッセージを確認していない時間を把握していて、もし、アプリケーションがメッセージを確認していない時間が「長すぎる」場合、ETWイベントが発行される。適切なところ(Microsoft-Windows-Win32k)からデータを記録していれば、これらのイベントがトレースに入り、UIディレイグラフがSystem Activity areaに表示される。通常、このグラフは空であるが、筆者の反応しないシステムのトレースは、棒グラフの海となり、何十ものMsgCheckディレイイベントが、システムのあらゆるプロセスから発せされていた。これがその一部だ。

[訳注:画像]

興味深いことに、3/4ほどのハングしたプログラムは、cl.exeのインスタンスだ。Windowsはコンパイラーがメッセージポンプを実行していないと報告している。この事実は、ただちに、「なぜコンパイラーにメッセージポンプがあるのか!」という疑問を生じさせる。

この疑問は、ひとまず無視しよう。その背景事情を考えるのだ。

次のステップは、ハングしたアプリケーションをひとつ選び、なぜメッセージを処理できていないのかという原因を探ることだ。筆者はdwm.exe(Desktop Window Manager)を選択した。なぜならば、これは高優先度で実行されているからだ。このプロセスはシステムがオーバーロードした時もスムーズに動くべきであるので、何か悪いことが起こっているのは明らかである。

UIディレイイベントには、メッセージポンプに失敗しているスレッドのプロセスIDとスレッドID、メッセージが処理されていない時間といった情報が含まれている。これにより、ようやくまともな疑問を構築することができる。

なぜ、プロセスdwm.exe(4336)のスレッド19,308は、トレース開始から84847.551566180秒時点で、2.668秒もメッセージを処理できていないのか?

このしっかりとした疑問があれば、この疑問に答えることができる。

このまともな疑問の存在は重要である。なぜならば、適当にwait analysisをしても、多くのスレッドが何秒も実行されずに待っていることが判明するだけだからだ。wait analysisをするときは、アイドルスレッドは問題ではないという認識を持つことが重要である。コンピューター上のほとんどのスレッドは、たいていの時間はアイドルであるべきなのだ。問題なのは、反応していないスレッドだ。メッセージポンプを行うべきなのに行っていないスレッドだ。だからこそ、UIディレイイベントはとても重要なのだ。反応していないスレッドを抽出してくれる。

(wait chainをたどる方法については、Xperf Wait Analysis–Finding Idle Timeを参照されたし)

反応の遅いdwmスレッドは、ExAcquireResourceExclusiveLiteを、何度も待っていた。時として、何百ミリ秒も待っている。ここで解説されている、ReadyingProcessなどのカラムにより、誰がdwmスレッドを準備可能な状態にするのがが判明する。誰がロックをリリースして、dwmスレッドを実行させるのかが判明する。筆者はこのチェインを手動でしばらく追っていたが、数百回ものコンテキストスイッチの後には、いい加減に飽きた。

そこで、筆者はwpaexporterを使って、関心のある範囲のコンテキストスイッチをすべてエクスポートした。そして、結果をフィルターしてNewThreadStackの中のExAcquireResourceExclusiveLiteのある行だけ得て、Excelでコンテキストスイッチの時間差を計算した。これはlock chainのアタリをつけるためと、誰がロックを長い間握っているか調べるための、手っ取り早くて小汚い方法である。これらのロック所有は、通常はとてもすばやいものである。大方は、1ミリ秒以下である。しかし、大多数が、長い間ロックを握っていた。大方は、16ミリ秒か32ミリ秒だ。観測によれば、15ミリ秒以上もロック所有しているスレッドは全体の3%だというのに、この遅いロック所有は、全体の75%の時間を使っている。

コンテキストスイッチのデータをより詳細にみると、どうやら、遅いロック所有の原因は、スレッドがロックを所有しているのに、CPU時間が割り当てられていないからであるように思われた。そのため、ロックは、OSの次のスケジューリング期間になってCPU時間を割り当てられるまで、未使用のままだ。もしくは、ひょっとしたら、スレッドがロックを所有した後に、タイムスライスを失っているのか。どちらとも言えない。とにかく、これは優先順位の逆転のように思われる。もしくは、単にビジーなシステムで毎秒数千回もロックしたら必ず起こる現象なのだろうか。

訳注:優先順位の高いスレッドがロックの解放を待っているが、そのロックを開放するのは、優先順位の低いスレッドであり、優先順位の低いスレッドにはCPU時間がなかなか割り当てられずに、ロックの解放に無駄に時間のかかる現象。

ExAcquireResourceExclusiveLiteの呼び出しはすべて、SetWindowsPos, CreateWindowExなどの関数から生じているようだ。明らかに、奪い合っているリソースは、ウインドウシステムの重要な部分であるようだ。

lock chainの筆頭に存在するスレッドは、VC++コンパイラーの一部である。CreateWindowExWから呼ばれている。CreateWindowExWとは、コンパイラーにとっては奇妙だ。それから、CreateWindowExWはmshtmlから呼ばれているが、これはさらに解せない。実際、65%のウインドウシステムのロックへのトラフィックは、VC++コンパイラー由来で、ほとんどがmshtml.dllからだ。

つまり、/analyzeを実行すると、コンパイラーは多数のCPU時間をコード解析に費やすと同時に、ウインドウも開く(実際には二つひらく。COM目的にもうひとつ)というわけだ。コンパイラーを多数走らせると、多数のウインドウが開かれて、GPUに負荷がかかる。狂気お墨付き。

コンパイラーのインスタンスは、Visual StudioとかOutlookといった通常のウインドウ付きプロセスより、すこし低い優先順位で実行される。そして、この低優先度と高CPU時間要求と、ウインドウシステムのロックの多用は、問題の根本的理由のようだ。優先順位の逆転を引き起こすのだ。

技術的に、筆者はmshtmlと、ウインドウを開くといったことが、ハングの原因であるかどうかはわからない。筆者が分かるのは、ハングは/analyzeでコンパイルした時のみ起こること、/analyzeコンパイルはmshtml.dllをロードすること、mshtml.dllがwait chainに現れることである。相関と因果はちがうが、だいぶ怪しい

xkcd: Correlation

男「いままで、相関関係があると、因果関係があると思っていたんだ」

男「統計学の授業を取ったら、そうは思わなくなった」

女「授業は役に立った様子ね」
男「うーん、たぶんね」

もし、Microsoftがmshtml.dllをコンパイラーから取り除いたのならば、筆者は喜んで再びテストをして再報告する所存である。

でも、なんで?

ソースコードにアクセスできない以上、筆者には何が起こっているのか明らかではない。だが、これだけは分かる。コンパイラーを/analyzeで実行すると、コンパイラーはmspft120.dllをロードする。/analyzeのDLLだ。そして、mspft120はmsxml6.dllをロードして、XML設定ファイルを読み込む。そして、msxml6はurlmon.dllをロードして、ストリームを開く、そして最後に、urlmonはmshtml.dllをロードする。そして、mshtml.dllはウインドウを作成する。なぜならば、mshtml.dllはそうなっているからだ。

読み込まれてるXMLファイルは、

  • res://C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\mspft120.dll/213
  • res://mspft120.dll/300

この一連の処理は、ある場合においては当然のことであることは確かだ。ただしこの場合においてではない。思うに、だれもmshtml.dllがロードされていることに気がついていないのではないか。もしくは、問題が発覚するほど大規模な並列コンパイルを誰も実行したことがないのか。

訳注:原文ではMSVCがmshtml.dllを読み込むことを検証する方法が書かれているが省略

対処法

Microsoftが、自社のコンパイラーがWebブラウザーを読み込む問題を修正するまでは、大規模な並列ビルドを行う際にこの問題は避けられないようだ。筆者の知る唯一の解決法は、並列数を下げることだ。最大の並列プロジェクトビルドを小さな値に設定することで、ハングの度合いを、まだマシなレベルに抑えられる。

思うに、CPUコアが少なければ、問題を抑えられるのではないだろうか。自動的に過剰な設定が減るわけだから。しかし、筆者は多大な並列性がほしいのだ。やれやれ。

Microsoftにグローバルなコンパイラースケジューラーがあれば、このCPU多使用は回避できたであろうに。

追記

筆者に対して、なぜに段階の並列プロジェクトビルドをやめることで問題解決にはならないのかという質問が寄せられた。その理由は、もちろん、コンパイラーがWebブラウザーを開くなどということは、依然として馬鹿げているからだ。もうひとつの理由は、12並列並行プロジェクトビルドは、12スレッドCPUのデフォルトだからだ。デフォルトの挙動はもっとマシであるべきだ。

対処法が理想ではない最後の理由は、理想のビルド速度を得るためには、2並列並行プロジェクトビルド以上が必要な場合があるからだ。筆者が先週、並列コンパイルのブログ記事で示したように、並列コンパイルはデフォルトで無効になっている。たとえ有効にしても、多くのプロジェクトは、かなりの時間を直列ビルドに使っている。そのため、並列コンパイルと並列プロジェクトビルドを組み合せることが適切なのだ。

特に、我々はほとんどのプロジェクトでプリコンパイルドヘッダーを使っている。VC++はプロジェクトのビルドに際して、プリコンパイルドヘッダーをまずビルドする。プリコンパイルドヘッダーが用意できるまで何もコンパイルしない。そのため、プロジェクトビルドこそが、すべてのプロジェクトのフルビルドを開始時から並列できる方法なのだ。

VC++/msbuildが、144個ものコンパイルを並列実行するのを止めるために、グローバルスケジューラーを持っていないのは残念である。グローバルなコンパイラースケジューラーこそが、プロジェクト外部、内部で、過剰にならずに完全な並列化を達成するための方法であるのに。

それから、並列プロジェクトビルドはグローバル設定であるので、設定値を下げると、いくつかのソリューションが余計に遅くビルドされる。

ドワンゴ広告

この記事は自宅とドワンゴ勤務中の両方で書かれた。MSVCが本物のC++コンパイラーかどうかは議論の分かれるところである。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

Quake IIIを走らせる完全に自由な新規のRaspberry Pi用のGPUドライバーが公開

Quake III bounty: we have a winner! | Raspberry Pi

今年のはじめ、Broadcomは、VideoCore IV graphics coreのGPUドライバーの仕様とGPUドライバーのソースコードを公開した。このGPUはBCM21553に搭載されているものであり、すなわち、Raspberry PiのGPUである。

Android for All: Broadcom Gives Developers Keys to the VideoCore® Kingdom | Broadcom Connected

これにより、Raspberry PiのGPUスタックが自由になった。また、完全に独立した自由なGPUドライバーを作成するための情報が出揃った。

これを記念して、Quake IIIをRaspberry Piの新規のGPUドライバー上で最初に動作させたものに、1万ドルの賞金がかけられた。

この賞金を見事勝ち取ったのが、Simon Hallである。

リンク先では、実際にこの新ドライバー上でQuake IIIを動かすための手順が説明されている。

説明されている手順では、Raspberry Pi上でLinuxカーネルのコンパイルを行っているので、「コンパイルは12時間ほどかかるので、このためにPiをオーバークロックしておくと便利だ」などと書かれている。

この手順書に対し、Hacker Newsでは、

Quake III bounty: we have a winner | Hacker News

「あの、クロスコンパイラーというものがありましてですね」とコメントが付き、そこから、「GCCのクロスコンパイルがいかに大変か」や、「いや、Raspberry Pi用のクロスコンパイルはドキュメントが相当に整備されているので、まだ楽だ」などといったコメントがついている。