.NETはどのくらいAPLに近づくことができるか

.NET, .NET Core, monoのランタイム・フレームワーク・ライブラリ Advent Calendar 2018の1日目は「.NETはどのくらいAPLに近づくことができるか」というお題でお送りします。

APLとは何か

APL(audio programming language)というのは、主として音楽を作成したり音響効果を実現したりする目的で音声を処理するためのもので、主に非プログラマー(というか、「ガチの」プログラマーではない人々)でも「簡単に」書けるようにするために開発されています。ここで言うAPLというのはひとつの言語ではなく、さまざまな言語の総称です(固有名詞であるA Programming LanguageことAPL言語は、オーディオとは一切関係ありません)。類似の概念としてVPL(visual programming language)があると言ってもよいでしょう。

APLのガラパゴス

APLの例としては、Csound、ChucK、Pure Data、Alda、Faust、Tidalといったものが挙げられます。面白いのは、これらの多くがそれぞれ独自の言語を定義しているということです。もっとも、これらの少なからぬ部分がSchemeなどのLisp系の言語の体系を利用していることを考えると、独自の文法であるとまで言えるかは何とも言えないところです。とはいえ、最終的に実行するプログラムが独自の生態系を構築しているということは言えるでしょう。

これらの言語の一般的な傾向として興味深いのは、これらはほぼ間違いなくJavaや.NETのような仮想マシン技術を用いて実装されないということです。音楽や音響効果を記述するのは、たとえばゲームの開発などにおいては有用そうですし、これらがJavaや.NETで開発されていないというのは意外なことではないでしょうか? なぜ音声処理を行うのにユーザーたるわれわれが独自言語を学習しなければならないのでしょうか? 生オーディオや生MIDIを扱うAPIが存在しているように、音声オブジェクトのライブラリとして提供してくれれば、後は自分の好きなようにどうとでも生成するのに…

しかしAPL開発者には彼らなりの理由づけがあってそうしているのです。面白いことに、それらの理由づけのいくつかは論文化されており、各APLの公式サイトや関連コミュニティなどで紹介されていたりもします。

今回は、その中からExtempore言語の作者Andrew Sorensenによる "The design, implementation and application of a cyber-physical programming language" という論文が、「なぜ.NETではダメなのか」というような疑問に対して、さまざまな実装の可能性を検討しつつ論じていて面白かったので、これを紹介しながら内容を吟味していきたいと思います。

https://openresearch-repository.anu.edu.au/handle/1885/144603

(Extemporeは自称「サイバーフィジカル言語」で、音楽だけを対象とするものではないそうで、この特徴は割と多くのAPLに共通するものなのですが、ここでは踏み込まないでおきます。Impromptuという言語処理系をもとに誕生したようです。あと、この論文自体は.NETについて議論しているものではありません。CLRへの言及などはまれに登場しますが。)

おまけ。OSCON 2014のキーノートで行われたExtemporeのライブコーディングも見られます。

https://www.youtube.com/watch?v=yY1FSsUV-8c

音声処理の用途

一般的なAPLが「仮想マシンではダメだ」としながら担っている仕事は、主に音声の「リアルタイム」に近い処理です。「リアルタイム」とはなんぞや?という疑問は今はおいておいて、音声のリアルタイム処理がどのような場面で必要になるか、いくつかの例を分かりやすい順に挙げていきましょう。

(1) バーチャルなピアノの鍵盤をソフトウェアで実現することを考えてみてください。ピアノのキーを押すとそれに反応してピアノの音が出ます。押したキーの位置に応じて音階が変わります。キーを押してから音が出るまでに時間がかかっていたら、ユーザーはこれを使いたいとは思わないでしょう。

(2) MP3プレイヤーは、ユーザーが指定したMP3ファイルをデコードしてサウンドバイスに出力します。PCMデータのデコードにかかる時間は、生PCMを再生する時間よりは短いですが、再生するタイミングが適切に管理されて守られていないと、音が飛び飛びになってしまって、ユーザーは聴くに耐えなくなります。

(3) DAW(デジタルオーディオワークステーション)は、複数のトラックで音楽を編集して制作するためのものです。場合によっては、PCMとして生成されるオーディオトラックの他に、MIDIバイスにメッセージを送信するMIDIトラックが存在するかもしれません。オーディオトラックとMIDIトラックの間で時間差が生じてしまうと、リスナーにとってはちぐはぐな音楽として聞こえることになります。

(4) デジタル楽器を使ったライブ演奏を行うことを考えてみてください(冒頭で紹介したOSCONのキーノートスピーチのように、最近ではAPLを使った Live Codingと呼ばれる実演もあります)。ライブ中にアプリケーションが固まったり処理が一時的に遅くなってしまったら致命的です。

もちろん、「リアルタイムでない」(リアルタイムであることが要求されない)音声関連の処理もいろいろあります。たとえば生PCMデータをMP3にエンコードする仕事は、何もリアルタイムで行う必要がありません。音声に対してエフェクターとして機能するソフトウェアもいくつかあります。これらは(i)再生しながらエフェクトをかける場合はリアルタイムで処理する必要がありますが、(ii)単に変換して結果を保存したり他のソフトウェアに渡すような場合はリアルタイムである必要はありません。

また、前記(1)〜(4)で求められている要件は、厳密には「リアルタイム」とは限らないものもあります(たとえば(2)や(3)はタイミングが合っていれば即応的である必要はありません)。しかし観念としては処理時間の正確さが重要であるものであり、ここで列挙しておくべきものでしょう。

リアルタイム性

いずれにせよ、音声処理ではリアルタイム性が求められる場面が多数あることがわかりました。しかし「リアルタイム」とはどのような意味なのでしょうか? ピアノの打鍵から1秒経ってから音が出たら、誰が聞いてもおかしいと思うでしょう。100ミリ秒だったら? 10ミリ秒だったら? 1ミリ秒だったら? …こうなってくるとわれわれは直感的にYES/NOで答えることが出来なくなってきます。

同じような問題がVRなどで用いられる3Dアニメーションのフレームレートについても語られます。VRも60FPSとか120FPSといった要求数値が出てきてなかなか厳しいのですが、音声も割とシビアなほうで、20ミリ秒くらいだとそれなりに気づかれてしまうようです。50FPSだと思うとなかなか厳しいことがわかります。

ここでひとつはっきりさせておくべきことがありますが、リアルタイム性とは「コンピューターの処理能力を可能な限り上げることで高度な処理も期待された時間内に終わらせる」仕組みではありません。あるタスクが一定間隔の「期待された時間」に必ず呼び出されて処理できることが、リアルタイムの要件です。

リアルタイム処理は、パフォーマンスの最大化すなわち「コンピューターの処理能力を最大限に活用して、もっともコンピューティングリソースを必要とする処理に最大限のリソースを差し向けよう」という思想とは、むしろ真っ向から対立するものであると言えます(リアルタイムに呼び出される処理はむしろ大して仕事しないかもしれず、それでも定期的に呼び出すことは重要なので、タスクマネージャーはその優先度を上げたままで維持します)。

現代のマルチタスク・コンピューティング環境において、「期待された時間」の枠は、OSのプロセスとスレッドの管理に依存するところが大きいです。前述のSorensenの論文は、そもそも「OSが自動的にタスク切り替えを処理するプリエンプティブ・マルチタスクにするか、アプリケーションが手動でタスク切り替えを管理する協調的マルチタスクにするか」というところから、リアルタイム処理の可能性を検討するのですが、協調的マルチタスクは、もはや一般的なデスクトップ環境があらかたプリエンプティブである現代において現実的ではないので、すぐに検討から外されています。

いずれにせよ、プリエンプティブなマルチタスク環境においては、リアルタイム処理を実現するためには、リアルタイムの精度で必ず呼び出しが発生するプロセス/スレッドが存在することが求められます。一般的なスレッドには、そのような保証はまったくありません。スレッドは大量に生成されて、また多くは既存のスレッドをスレッドプールから使い回されます。全てのスレッドが期待された時間に必ず呼び出されるような理想的な世界があれば問題にはなりませんが、現実はそのようにはなっていません。せいぜい、リアルタイム処理のために特権的に許されたスレッドだけが、優先度の高い割り込みを実現できるのです。それもRTLinuxのような特殊なOSカーネルによって実現してきたのです。

唐突に本題に戻りますが、.NETでこのようなリアルタイム用スレッドの作成が出来てコードが実行できるのであれば、.NETでAPLの要件を満たしたコードが書けるかもしれません。この論点は後でまた言及します。

(Sorensen論文は、さらに「時間をどう計測するか」というトピックについても一節を使って論じていて面白いのですが、さすがにそこまで紹介する意味はほぼ無いので、これだけの言及にとどめます。)

ガベージコレクション

仮にリアルタイム処理を行えるスレッドが利用できたとしても、それはあらゆるアプリケーションがリアルタイム処理に対応していると言える十分条件になるわけではありません。リアルタイム処理においては、1回の呼び出しサイクルが、1サイクル分の時間以内に処理を終えて呼び出し元(OS)に制御を戻すことが求められます。すなわち、この処理で予定外に長い時間がかかってはいけないのです。そして、これは処理時間の平均値の問題ではなく、WCETと呼ばれる「最悪の場合にかかる処理時間」 (worst case execution time)の問題なのです。

この観点で、.NETやJavaをはじめ、その他各種言語ランタイムで問題になるのがGCの処理です。GCの多くは確保されたオブジェクトの利用状態を安定的にトラッキングするために、よく"stop the world"と呼ばれる全アプリケーション・スレッド停止処理を施した上で、メモリをスキャンして、使用されなくなったオブジェクトをマークして、これをスイープします。

stop the worldはCLRのような世代別GCでは、一般的には第2世代以降のみに当てはまる話ですが、いずれにせよ、ここで重要なのはstop the worldが発生しうるということです。stop the worldは当然ながらリアルタイム処理を行っているアプリケーション・スレッドも止めなければなりません。…あれ? リアルタイム処理では、1回の呼び出しサイクルで行われる処理が1サイクル分の時間に必ず収まらないといけない、という条件はどうなるのでしょうか? はい皆さんご想像の通りです。これは満たせません。

実際には、ここには「力こそパワー!」が働く余地があって、極端な話、GCのstop the worldが十分に短いサイクルで実現できるのであれば、これは問題になりません。たとえばGoのGCはマイクロ秒単位で完了するらしいです。ビックリですね…! GC開発者が2016年に「10ミリ秒の停止なんてもう古い!」みたいなことを書いています。

https://groups.google.com/forum/#!msg/golang-dev/Ab1sFeoZg_8/_DaL0E8fAwAJ

あと全然関係ないところでHISEというプロジェクトがしれっと "Customized and real time safe Javascript Engine" などと書いていてたいへん気になるところです。ざっと見た感じでは、JS実装はどうやらインタープリタの独自実装で、一方でメモリ確保は自動で行わないように拡張したものであるようです。

http://hise.audio/

翻って、われらが.NETはどうでしょうか。2017年にMatt WarrenがまとめたGC停止時間に関する投稿がひとつの情報源として信頼できるでしょう。

http://mattwarren.org/2017/01/13/Analysing-Pause-times-in-the-.NET-GC/

Workstationで20ミリ秒強…これではオーディオのリアルタイム処理を任せられるとは言えなそうです。もっとも、この投稿ではGCLatency Modesに関する言及が何もなく、もしかしたら全く調整を試みずに測定しただけなのかもしれません。Low Latencyモードは.NET 3.5で追加されたもので、この記事がよくまとめています。

http://blogs.microsoft.co.il/sasha/2008/08/10/low-latency-gc-in-net-35/

もっともLowLatencyモードは「gen-2以降はGCしない」という剛毅な動作条件なので、長時間実行しっぱなしのライブパフォーマンスのような用途で使う余地はありません。

同じ2017年1月のこちらの記事では、もう少し悲観的な数値が出ています(最後のほう)。このベンチマークではbackground (concurrent) workstation GCとLowLatencyモードを明示的に対象としています。WCETが200ミリ秒を超えることがちょいちょいあるようです。これではやはり使い物にならないでしょう。

https://blogs.msdn.microsoft.com/seteplia/2017/01/05/understanding-different-gc-modes-with-concurrency-visualizer/

(少しだけGCの速度について補足すると、goはreified genericsをサポートする.NETに比べると、だいぶシンプルな要件に基づいて実装されているはずなので、実装の本気度合いの比較と考えてしまうのはフェアではないとわたしは考えています。ただし、言語の総合的な可能性を評価する要素にはもちろん含まれます。)

JITの予見できない動的コード生成

GCの話はここまでにしておいて、もうひとつ、この論文が取り上げるJITの話題に移りましょう。一般に、仮想マシンJITエンジンは、実行時にCPUネイティブの実行可能なコードを生成します。.NETプログラムを初めて起動したときにつっかかるような遅さを体感できると思いますが、その正体はJITコンパイルです。より正確を期するなら、JITコンパイル処理そのものよりは、JITコンパイラをプログラムとしてロードして実行するための遅さ、であると考えたほうがよいでしょう(コンパイル処理自体にあれほど長大な時間がかかるとまでは言えないので)。しかしそこまで極端に長い時間はかからないとしても、JITコンパイル処理自体には無視できないコストがかかります。

一般的には、ある仮想マシンコードのメソッドを実行するためには、まずJITコンパイルしてから実行することになります。ここで先般から話題にしているリアルタイム処理の要求事項の話を思い出してください。リアルタイム処理の呼び出しが行われたときに、初めて実行するコードがあったとします。このコードはまずJITコンパイルされなければなりません。このコンパイル処理はリアルタイム処理に期待される応答時間内に完了するでしょうか? …ちょっとこれは期待できそうにないですね。これがSorensenが提起するもうひとつの問題です。

ちなみに、これは.NETやJavaの問題というよりは、一般的な言語ランタイムに共通する問題です。Sorensenが論文で言及しているのはSonic PiのRuby、GibberのJavaScript、ImpromptuのScheme、OvertoneのClojureなどです。

Extemporeは、ではどのように設計され実装されているかというと、この言語はSchemeインタープリターとXTLangという独自の実行系のハイブリッド構成になっていて、XTLangではGCに依存しない、リアルタイム処理で期待されるコードを書く、それ以外はSchemeで書く、ということになります。XTLangで書かれたコードは、いったんコンパイルしてLLVM IRに変換し、それをネイティブコードに変換して実行することになります。

Extemporeは、ライブパフォーマンスなどの場面で、REPLのようにコードの断片を実行できることを、主目的としており(CやC++では実現できない課題としてこれを挙げています)、実際それがExtemporeコードの一般的な実行方法になります。ただ、XTLangのコンパイルには時間がかかるので、事前にコンパイルコマンドを実行しておくことで、実行時遅延の問題を回避します。

この論点ですが、2018年までにAOTやインタープリターのような、さまざまな.NET実行環境を見てきたわれわれとしては、「仮想マシンであればJITコンパイル」というのは、やや固定観念的であると評価せざるを得ないでしょう。古くからAOTをサポートしていたmonoランタイムだけでなく、.NET CoreでもAOT実行が可能になりつつあり(可能である、と言ったほうが良いでしょうか?)、この点での懸念は、少なくとも理論の上では無くなりつつあると考えられます。

もっとも、インタープリターで実行するのであれば、ネイティブコードのパフォーマンスは一切期待できず、何のために仮想マシン言語を使うのか、という話になるでしょう。その点AOTはまさにXTLangと同じことをやっているのであり、基本的にはリアルタイム処理を期待する場面ではAOTを適用するようにすれば良いと言えそうです。もっとも、Xamarin.iOSでも問題になるように、AOTでも不完全AOTになってしまうものは、JIT処理が発生する余地があるということで、リアルタイム処理に関する懸念をクリアできません。

いずれにせよ、ExtemporeはAOTに相当する静的コード生成をREPLのレベルで実現しているので、.NETでこれに相当するものを実現するためには、現存するC#のREPL環境では足りず、部分的に独自にAOTコンパイルを行えるようなREPL環境が必要になるでしょう(先ほど「少なくとも理論の上では」と留保した理由です)。

言語ランタイムとサウンドサーバーのプロセス内通信

Sorensen論文が本当に面白いのは、この論文はExtempore以外のさまざまな他の実装のアプローチについても、彼なりの視点で検討を加えているところにあります。そのひとつは、言語ランタイム側はリアルタイム処理を行う音声処理部分と、FFI(foreign function invocation/interface)などによってintra-process communication(interではなくintraであることに注意)を行うことで、他言語実装によるメリットを得る、というアプローチです。ChucK、Impromptu、Fluxusはこのアプローチで実現しているようです。

このアプローチの問題は、アプリケーションがクラッシュした場合に問題を解決するのがとても困難である、とまとめられています。これは確かに事実ではあるのですが、「難しいかどうか」はどうしても主観的な判断になってしまうので、その妥当性も評価が難しいところです(というかこの論文ここはスルーしてもらえたのか…)。

プロセス間通信による実装アプローチ

intra-process communicationが困難ならinter-process communicationすなわちIPCではどうでしょうか。これもSorensenは検討しており、実際にこのアプローチで実現している例としてSuperColliderを挙げています。プロセスが分離していると、クラッシュするのはクライアントかサーバーのいずれかになるので、問題の切り分けが容易になりますし、ABIではなくプロトコルによってやり取りが決まるようになります。特にSC3は仕様の安定化を図ったことで、SC1やSC2のようなクライアント・サーバー間の厳密な同一バージョン依存が無くなった、と説明されています。

しかし一方で、安定した仕様になってしまった結果プロトコルへのメッセージの追加が容易に行えなくなったことが問題である、という議論を加えてもいます。仕様を簡単に変更できることがintra-process communicationの大きなアドバンテージである、とまで書かれています。

Extemporeもクライアント・サーバー方式であり、プロセスはクライアントとサーバーで分離しているのですが、tightly-coupledとloosely-coupledの2つのアプローチの間ではフラフラしていたようです。基本的には不可分のものとしているつもりであるようで、その機能の一部をCのライブラリとして分離したりしなかったりといったことを、後方互換性を気にせずに行ってきた、というような話も書かれています。

このあたりの事情をどう評価するかも悩ましいところですが、わたしの個人的な意見としては、実装のアプローチがクライアント・サーバー分離モデルであることと、仕様の安定化の有無は個別に判断すればよいことであって、仕様は正直「ここは安定」「ここは未定」みたいな宣言で押し切るしか無いように思います。安定仕様がダメだったら、非互換の別の仕様として立て直すしか無いでしょう(今「たぶんSwiftはこうやって現状のようになっていったんだろうなー」という考えが浮かびましたが多分気のせいでしょう)。

.NETの文脈でこれを考えるなら、intra-process communicationの方法はあまり考えつかないのですが、CLR hostingやmono embedded APIによるホスティングでしょうか…あまりメリットが無いような気がしますが可能と言えば可能でしょう。(前述のstop the worldと向き合わなければならない事に変わりはないのですが、ここでは個別に検討します。)

inter-process communicationのアプローチは、特段論じるべきことはあまり無く、強いて言えばIPCに必要な共有メモリのサポートなどは.NET Coreでもだいぶ最近になってクロスプラットフォームで実装されてきた機能であることに注意したほうがよい、という程度でしょうか。TCPなどの通信スタックを使ってしまうと、リアルタイム処理を期待しているのに…となってしまいそうです。

ただ、そもそも根本的な問題として、クライアントとサーバーを分けて、ではサーバーは.NETやJavaで実装・拡張したくないのか、と考えると、やはりやりたくなるんじゃないかなあという気はします(個人の主観の問題でしょうか…?)。そうなると結局stop the worldなどの問題に正面から向き合うことになるでしょう。

.NETのGCに挽回の余地はあるか?

さて、ここまで長々とSorensen論文を中心に、APLを.NETで実現する場合の課題にはどんなものがありうるか、検討してきました。やはり一番問題になるのはGCのstop the worldではないでしょうか。

実のところ、この点では.NETよりはJavaのほうが可能性が広がっています。Java界隈には、リアルタイム処理を実現するための手段としてRTSJ(Real-Time Specification for Java)という仕様があり、JSR 282として標準化されています。RTSJの主な特徴をざっくり列挙するとこんな感じです:

  • RTSJでは、リアルタイム処理用のスレッドをユーザーが作成できる
  • そのスレッドではメモリの確保手段が限定されている
  • そのメモリ領域はGCの対象とならない

これらの取り決めをしておくことで、リアルタイム処理を妨げられないスレッドが実現できるというわけです。

Javaにはこのような機構があるのに.NETには無いのでしょうか? .NETにはCER (constrained execution region) という機構があって、「GCをLowLatencyモードに切り替えるときはこれを使え」と言われるものですが、これは別にメモリ管理を別途行うようにするというほどのものではないので、RTSJのようなことは出来ません。このあたりの柔軟性の無さは、やはり.NETがずっとクローズドソースで閉鎖的に開発されてきたからでしょう。CLR/CoreCLRのGCもあまり柔軟ではなく、このようなメモリ管理機構に耐えうる設計になっているのかはわかりません。

一方、.NETや.NET Coreとは異なり、MonoはGCの実装を差し替える機構がそれなりに整備されているので、RTSJ的なGCとハイブリッドに協調するGCを構築できる可能性があるかもしれません。こちらはずっとOSSだったにも関わらず、RTSJのような試みはなかったと思います。何処かではあったかもしれません(わたしは聞いたことがありません)。

実のところ、RTSJも高価な商用製品による実装がほとんどであり、オープンソースの実装というものは無いように思います。そういう意味では、気軽な音楽アプリとは住んでいる世界が違うかもしれません。

この方面で一番現実化しそうなのはUnityとくにECSかもしれません(リアルタイムオーディオのリクエストは何年も前から出ているようです)。ECSで要求されるC#コードの制約がどれくらい問題になるかはUnityを使っていない勢のわたしにはわかりませんが、機構としては一番可能性がある領域かなと思っています。

まあこれはあくまでGCに関連する部分だけの話です。REPL環境が作れないんじゃないかという気もしますし、Unityのエコシステムは.NETのそれとは根本的に異なるガラパゴスであり、これとデスクトップ環境の標準的なコントロールに基づくUIを繋ぐのはだいぶ無理がありそうなので、頑張って機構を作っても、利用する側の開発体験が悪くなるだけになりそうですし、こういうのはMono Frameworkが一番向いていますね。

考察

さて、ここまでSorensenの論文を主な肴としつつ長々と書いてきましたが、最後にこれまでの話をもとに、どんなアプローチであればAPL開発者が納得できるような仕組みが構築できるのか、考察していきます。現時点では、次の2通りのアプローチがあると思います。

  • Low Latencyモードでメモリ不足で落ちないところまで頑張ってみる
    • and/or Low Latencyモードで解放されずに増え続けるメモリ使用は「リーク」とみなしてつぶす
  • クライアントとサーバーをIPCで繋ぐ。やりとりは共有メモリ。サーバも.NETで作るなら、Low Latency GCで「リーク」しないように作り込む

後者のほうが現実的かな?という気がしています。ただ、いずれも定性的に「リーク」を検出できる機構になっておらず、これでは不安である、と言われてしまう可能性はあります(まあそれを言い出したらGCの無い言語の上にコードを構築すること自体が不安ということになりそうですが)。

わたしがAPLを使ったり作ったりしたくなるような時が来たら、このIPCもどき方式で試してみようかなと思っています(個人的にはライブパフォーマンスに走る予定は無く、停止時間はほぼ重要ではないので、作るとしてもあくまで仮想的なクライアント/サーバーを分けておく程度で、アプリケーションは単一のままになりそうですが)。

なお、これは全て「アプリケーションがリアルタイム処理用のスレッドを作成できる」OSであることを要求事項としています。Androidなど、これが実現できない環境については、また別個の考察を必要とするものです。(本当はこの辺の話をDroidKaigi 2019でしようと思って準備していたのですが、セッション不採択になってしまったので他の機会に…)

"Android ネイティブライブラリビ ルド Tips" on "Trick or Treat" (TechBooster新刊)

10/8の技術書典5が近づいてきて、例によって台風が押し寄せてきて、スタッフ業がてんやわんやしていますが、進捗どうでしょうか? 最悪でも致命傷で何とかすませたいところですネ。

さて先日のエントリではわれわれのサークルの新刊のお知らせを出しましたが、今日はTechBoosterの新刊 Trick or Treat に記事を出したのでお知らせです。

techbookfest.org

今回はAndroidネイティブライブラリビルドTipsというタイトルで、特にAndroid向けに書かれているわけでもないLinux用ネイティブライブラリを、Android NDKを使って、ちゃんとAndroid Studioからデバッグできるようにビルドする方法をまとめました。内容はほぼそれだけですが、全部で12ページくらいあります。

NDKでndk-build以外のやり方で書かれたライブラリをビルドするには、NDKのツールチェインをクロスコンパイラの流儀に沿って使わなければならないのですが、Android NDKで公式にサポートしているcmakeに基づくビルドであっても手こずったりしますし、autotoolsなどが使われているとさらに面倒です。部分的にクロスコンパイルできていなくてハマったり、x86ビルドがなぜかAndroidに無いglibc依存になっていたり、あるいは共有ライブラリで依存関係があったりとかすると沼です(Linux環境では共有ライブラリは大概Androidでサポートされないシンボリックリンクになりますし)。

さらに、ビルドだけ何とか出来ても、デバッグシンボルをちゃんと埋め込むようにビルドする、さらにはビルド中に依存ライブラリがある場合はそれらもデバッグシンボルを埋め込んでビルドする…といったふうに、さまざまなポイントでデバッグシンボルが抜け落ちることがあります。

というわけで、さまざまな落とし穴に言及しつつ、Android Studioデバッグできるような*.soをビルドできるように、12ページでまとめています。あとついでにJavaやXamarin、Kotlin/Nativeなどから呼び出す時に困りそうなAPI設計のパターンについてもちょろっと言及しました。

本当はこの辺をメインに書いてうちの新刊のネタにするつもりだったわけですが、Xamarinっぽくなかったのでボツとして、ちょうどAndroidネタを募集していたTechBoosterの方で再利用したというわけです。

そんなわけで、Android NDKネタですが、割と珍しい切り口になっているのではないかと思います。興味がわいてきたという皆さんはぜひ10/8の技術書典5に買いに来てください。TechBoosterは「あ11」です

Awesome Xamarin (技術書典5新刊情報)

無職になっても生活が在職時とほとんど変わらないatsushienoです。それって単に給料が入ってこなくなっただけじゃないか…?自由な生活たのしい!!!1

戯言はさておいて、9月は多くの時間を10/8の技術書典5に向けて費やしていました。そのうちのひとつは今日お知らせするXamaritans名義の新刊です。

Xamaritansの配置は「う-78」です。詳細は技術書典Webサイト上のサークルページをチェックしてください。

タイトルは「Awesome Xamarin: この素晴らしいXamarinの世界」です。

f:id:atsushieno:20180925205124p:plain

(今回はまたイラストをお馴染みの(?)絵師に描いてもらいました。今まではアナログ絵の取り込みだったのですが今回はペンタブで描いたらしい…)

内容ですが、今回は完全に1人で書くことにしました…というと何やらそのような意図でやったように聞こえるのですが、単純にまともに原稿募集を出していなくて(もうしわけない…)、結果的に1人で全部書くことになったのでした。本当は30ページくらいのコピー本にしようと思っていたのですが、最初に出来たクロスプラットホームGUIの話がデスクトップ中心でイマイチだったので、もう1本書いてみたらあまりにもXamarinと関係ないNDKの話になってしまって、ビミョイかな…とますます困ったのでした。そうこうしているうちに、mono project blogからクッソおもしろいネタが投下されたんですね。

これはmonoランタイムのJIT相当部分をC#で実装できる、という話なんですが、これはちょうどいいと思って、ついうっかりこの話を理解するために必要そうなJITというかコード生成エンジンの話を書き始めてしまったんですね。

割といい感じにまとまったと思ったんですが、ここで出来上がった原稿は(1)x-plat GUI(しかも割とデスクトップ中心) (2)NDK (3)JITXamarin要素ほぼゼロじゃんAwesome Xamarinとは何だったのか…

…というわけで、急遽(4)「Xamarin.Androidバインディングを極める」を書いて何とかそれっぽく誤魔化し(!?)、NDKの章は削って他で再利用することにしました(こっちは告知できるようになった段階で出します)。

そういうわけで、今回のネタは次の3本です。

(1) Xamarin.Android バインディングを極める

自分が一時期主に開発していたAndroidバインディング・プロジェクトについて、実用的なプロジェクト構成から細かい説明、各種ビルドエラーの対策(この辺は去年シンガポールでやったセッションの焼き直し)などを30ページくらい書いてまとめました。本当は個人的に構想していた未来形の話も書きたかったのですが、今後それを推し進めることになる気があまりしないので、ほぼ現状の話でまとめてあります。

(2) Mono.Compiler API を理解するためのMono JITエンジン解説

去年のde:code2017でもある程度コード生成エンジンの話をしましたが、アレはJITの話としてはほんの序の口です。JITが何をしているのか、miniとは何なのか、llvm実装とそうでない実装はどう繋ぎこまれているのか、CILはどのように実際のマシンコードに置き換えられているのか(Linear IR)、コードはどう最適化されているのかといった話を「もう少しだけ」掘り下げます。SSAレジスタアロケーターのspillingに言及はするが深入りはしない、という程度です。AOTも関係あるんだけど、最終的には「JIT」って章タイトルに入っているほうが分かりやすいだろうと思って「JIT」としました。自分で言うのも何ですがこの章が一番おもしろいです。

(3) Mono ・ XamarinクロスプラットフォームGUIの軌跡

MonoチームがXamarin.FormsのようなクロスプラットフォームGUIフレームワークを実装したのは、これが初めてではなく、大昔にはWindows.FormsをLinux/Mac向けに実装したり、その後今でも現役で使われているXwtを開発したりしてきました。またGtk+も今や…というか10年以上前から…クロスプラットフォームGUIツールキットであり、実装上の知見を得てきたフレームワークです。これらをきちんと振り返った上で、今Flutterのような新しいGUIフレームワークをどのように捉えるのか、Xamarin.Formsには何があって何がないのか正しく語るために知っておくべきことは何か、といったことを考察するための起爆剤として書いた章です。一部はde:code2018でXamarin.Formsについて語った内容も含まれています。

最終的におよそ90ページという、予定の3倍くらい厚い薄い本になってしまったのですが(完全に予言されたとおりになってしまった…)、いつも通り1000円で頒布しようと思います。技術書典5、スタッフとしても作業していますんで(こっちも大変…)、ぜひ皆さん来てください。Xamaritansは「う-78」です(サークルページ)。

"language server protocol explained" at COSCUP2018

台湾でおそらく一番でかいオープンソースのカンファレンスCOSCUP 2018でlanguage server protocol (LSP) explainedというセッションをしてきたので、その辺に関係する話を軽く書きます*1。当日は英語のセッションなのに30-40人くらいの人に来てもらえたので、それなりに関心が集まるトピックだったのかなと思います。

speakerdeck.com

もはやスライドのテンプレートすら選ぶ気のない感じのGoogle Slidesですが。

LSPがざっくり何のためにあるのか、language serverが何をするものなのか、何でprotocolなのか、どんな命令があるのか…といった部分は以前にqiitaにまとめた通りですが、今回は応募したセクションの趣旨が "read the source code" だったこともあって、少しvscodeで実装するやり方を説明しました(もちろんvscodeに固有のものではないことはたびたび言及しました)。vscode自体、まだLSPはJSONCSSみたいなおもちゃレベルのものしか提供していないので*2、引用するのもvscode-languageserver-cssが中心だったのですが、まあ逆に現状使えるのはこのレベルの言語かなという雰囲気が伝わったほうがいいかなと思って(自分の中では)納得しました。

わたし自身も、C#で自作MMLコンパイラのLSを(途中まで)作ったので、一応それが動いているのを見せつつという感じでした。C#のサーバが動いているのはどうでもよくて、vscodeデバッグコンソールのようなところにJSON-RPCの生メッセージが出てくるのを見せた感じです。これが出てくると割と面白いです。

ただ、LSPの仕様自体がまだ割といいかげんで、特にlocationやrangeみたいな情報の要求が、どこまで求めるべきものなのかを記していなかったりするので(たとえばトークンのrangeのendなんて割とどうでもいいと思うのですが、無いとvscodeがまともに処理してくれなかったりします)、まだまだ真面目に相互運用性を期待して手を出せるものじゃないなあという印象です。

あとC#のLSPライブラリに関して言えば、MSが出しているライブラリは依存関係にMicrosoft.VisualStudio で始まるプロプラエタリなパッケージがあってNG、omnisharp-vscodeはまだ激しく発展途上で実際ビルドしてテストを通そうとしたら通らないレベルだったのでNG…という感じで、いのまたさん(id:matarillo)の実装を使わせてもらったりしています。将来的にはもしかしたらomnisharpの実装の完成度が上がるのかもしれませんが、現状ではいのまたさんの実装がベストです。vscode-languageserver-nodeなどはもう少し実装ヘルパー的なものも持っているので、この辺はわたしがC#版のコンパイラまわりを本気でやることがあれば貢献できるといいなあという感じです。*3

というわけで、ひと段落ついたので、いろいろ残件を片付けつつ遊びに入りたいと思います(!)

*1:本当は「後編」を書こうと思っていたのだけどなかなかまとまらなかったというのは内緒です

*2:CSSパーサーをおもちゃレベルというのはちょっとひどい気もしますが、LSPにユーザーが期待するのはこのレベルではないはずですよね

*3:いまこのコンパイラvscode拡張は優先度が高くないので後回し状態ですが…

Leaving Microsoft

f:id:atsushieno:20180731024436p:plain

7月30日を実質的な最終出社日としてMicrosoftを辞めることにしました。と言っても「出社」なんてしていないので*1、業務でXamarinの開発に携わるのはこの日が最後だった、という意味合いです。社員としての最後のcommitはコレになることでしょう。

プロジェクトに参加したのが2002年、Novellに入社したのが2003年、それ以来15年間も業務でMono Projectおよび関連プロジェクトの開発に携わっていたことになりますが、それにひと区切りを付けたということになります。長いですね。Microsoftでの2年と1ヶ月など自分の経歴ではオマケでしかないですし、Xamarinの開発ですら2011年からの7年間なので、それでもこの仕事の半分以下ということになります。

何で辞めるの?

いろいろありますが、今日はクリーンでポジティブな話だけを取り上げて書きたいところですが、「Microsoftに」所属して活動する意味はほぼ無い、と判断したからです。これまでMonoを生業の中心としてきたわけですが、Monoはオープンな開発コミュニティであり、MSに所属して関わっていく必要性は全くありません。まあもちろんMSから給料は払われなくなるわけですが、今でもMonoにコミットしているのではなく、Xamarin製品の仕事をやらされているわけで、その意味ではどこでどうしていようが変わりはないと思っています。

人はおよそ「自分を雇用する資格のある会社」に所属すべきです。

巨大企業の官僚主義に利用されることなく、伸び伸びと自分のやりたいことを最適なやり方で実現するためにcontributeするなら、自分のみの意思でできることが重要ですし、自分のコードに集中する自由もしっかり確保しておく必要があります。

あと、自分の周りで「気持ちよく」「楽しそうに」仕事している友人が増えてきたので、自分も「仕事だから…」と思って我慢して踏みとどまるのは良くない、と思うようになったことは大きいです。その意味では、Miguelと一緒に「仕事」しなくなるのはちょっと残念ではありますが、それはMonoコミュニティにcontributorとして参加していれば大して変わらないかなと思っています(Androidチームとしては彼との関わりも現状ほとんど無いですし)。社内のメンバーの何割かは同様にむしろ同僚というより友人なのですが、これからも続く縁はあるでしょう。

しかしいずれにせよ、やることをリセットするのであれば、すぐに仕事につくより、むしろ満を持して無職をエンジョイする勢になっておかないと…!というわけでまずそこからスタートです。Xamarin.Forms本の作業などもそうですが、今の立場にいると無駄に雑多なタスクが入ってきて趣味の活動を妨げるので、そういうものをひととおりリセットして*2、自分のやりたいことに使える時間を大事にしようと思っています。まあ別にそっちに全振りするわけではなく、全振りしなくても無理なく継続していけるライフスタイルが重要です。

これからどうするの?

8月以降の仕事の予定はありません。とはいえ、8/11には台北のCOSCUP 2018で登壇しなければならないので台湾に渡りますし、当日まではいろいろ準備しなければならないでしょう。それが終わったら技術書典5の手伝いなどをしながら、音楽ソフトなどをいじって遊んで暮らす予定です。

XamarinにはMonoDevelopの商用アドインやデバッガーなど、プロプラエタリに提供している部分がそれなりにあり、それらはわたしの興味の範囲外なので、非OSS部分が無いとコードが維持できないレベルになってきたら、他の言語やフレームワークに乗り換えてやっていくつもりです。特にわたしは中の人特権でLinux上でIDEアドインを無理やり動かしていたわけですが、それが使えなくなるので、これは早々にそうなるかもしれません。

モバイル以外の、MonoやMonoDevelopGtk# 3やXwt、Workbooksなどはオープンなので、そういった懸念は小さく、引き続き使っていくつもりです。作っているものによっては他の言語に移る可能性ももちろんありますが。.NETはみんなが思っているほどオープンソースではないので今後やっていくかどうかは分かりません。

今後も(Xamarinも含めて)Monoコミュニティに一番縁の深い日本人として、日本で起こっていることなどをXamarin本家にいろいろ連絡したりしながらやっていくでしょうし、コードなどにcontributeしたいけどどう参加したらいいかわからない…! みたいな人がいたら、これまで通り(?)サポートしますんで、お気軽にご相談ください。基本的には暇人になりますんで。

*1:ごめんなさい、こういう時何て言えばいいかわからないの…

*2:幸い書籍の方は出版の目処が立っています

GitHubの買収とオープンソースコミュニティについて

6月2日にmicrosoftgithubを買収する噂が流れて、3日には確定情報として流れて、4日には正式発表があった。これに対しては歓迎する声から悲しむ声、非難する声などさまざまな反応があった。この反応の一部が、どちらの方向についてもあまり良くないと思っているので、可能な限り問題のある反応を潰しておこうという意図でこれを書くことにした。

ちなみに、笑える反応としては、githubにアクセスするとClipperやカイル君が出てくるようになるみたいなジョーク画像の類があるけど、これを集めているとキリがないし今回はきちんと論じたいことがあるので、その辺は他所に任せたい。

それはさておき、これは長い文章(になる予定)なので、最初にふたことで要約しておきたい:

  • 新CEOのNatは割と信用できるやつで、きっとGitHubを上手くやっていってくれるので、もしMSというだけで疑っているだけならちょっと人柄を知ってほしい
  • OSSにはさまざまな立ち位置で関わってくる人がいるのだから、それぞれの立ち位置にきちんと思いを巡らせてから発言するべきであって、買収に否定的な向きを「アンチMicrosoft」などと単純化して物事を見誤ってはならないし、それに基づいてOSSコミュニティを攻撃するようなことは決してするべきではない。

新しいCEOについて

今回はポジショントークになる部分があるのでハッキリ書いておきたい。わたしにとっては基本的に他人事だけど、他人事気分でいられない事情として、新しいCEOとしてXamarinのCEOだったNat Friedmanが就任する。NatはもうXamarinを率いておらず組織上も関係ないのだけど、当然ながら彼がCEOとして手腕を発揮しているところをこの目で見てきたので、完全に身内の主観的な立場にしかならないので、彼が優れたCEOであることを喧伝するし、読者にはわたしがそういう目線で書いていることを意識して一歩引いて評価してもらいたい。彼の功績の例については5年前に詳しく書いている。

NatはもともとMiguelと一緒にLinuxデスクトップの会社であるところのHelix Codeを立ち上げてNovellに買収されるところまで成長させたfounderであり、彼自身もdashboardというデスクトップ検索のプロジェクトを立ち上げたりしていたし*1Novell時代にもOpenSUSE Build ServiceやSUSE Studioのようなビルドサービスを立ち上げてきた人間だ。VS AppCenterとやっている/やりたいことは近い。

Natはgithubを現状と同様にオープンな状態を維持していくと語っていて、これは抽象的な言い分だからどれくらい信じるか、何を信じるかはわたし自身も全面的に肯定することはないし*2、誰しも「他人がMSを信用しないこと」に対して文句を付ける筋合いは無いと思っている。Natもそう思っていて "I'm not asking for your trust" と言っている。言葉ではなく実績で信頼を維持していくというやっていきの姿勢だ。

Xamarinは商用製品で成功した会社だし、その成功モデルは別にOSSの成功モデルではないから、Xamarinで成功したからといって直ちにGithubの信頼を得られそうだということにはならない。コミュニティの信用の見込みの期待値を過剰に高めることについては、わたしは適切ではないと思っている。

githubに関するいろいろな前提の説明

gitの非独占

githubは、ソフトウェアの設計図ソースコードをgitリポジトリで公開したい人たちのためのコミュニティサイトであり、gitリポジトリで管理したい人たちのためのサービスである*3

gitはソースコードのいわゆるバージョン管理システムで、「リポジトリ」が開発開始時からの全てのソースコードの履歴を保持する。gitの大きな特徴は、リポジトリが簡単に複製でき、複数のリポジトリ上で分散管理できるということにある。gitというソフトウェアの立ち上げ人はLinuxを立ち上げたLinus Torvaldsであるが、彼がgitを作ることになったのは、Linuxソースコード管理ツールとして使われていたBitKeeperというソフトウェアがプロプラエタリで、さまざまな不利益をコントリビューターに強いていたからである(詳しくはWikipediaの説明などを参照されたい)。git以前にはSubversionというものがあったが、これはLinux開発に耐えるものではないとされていた。

gitはBitKeeper依存への反省をもとに、リポジトリのあらゆるクローンが単独で完結する仕組みとなっている。githubにあるリポジトリは、アクセスできるユーザーが全て複製してローカルで再現できる。githubリポジトリをいったんクローンして、githubの競合企業であるgitlabにpush(アップロード)のは、完全にgitが想定している使い方である。git自身もOSSとして公開されていて、Webサーバーさえあれば誰でもリポジトリをWebに公開することができる。

githubの"openness"

githubは、そこで管理されているソースコードを、本質的には独占できない。独占していると言えるのは、最新版の開発拠点になっているということと、他のソフトウェアへの依存関係(後述)があることと、変更修正依頼(pull request)や問題報告(issues)などgit以外の開発支援機能があるためである。githubはissueなどもエクスポート可能にしていて、実際gitlabはこれらを取り込むことが出来る。

githubで公開されるソフトウェアはいわゆるOSSである必要はない。ソースコードを公開することは、それが「オープンソース」の定義に準ずるライセンスで公開されていることを意味しない(Microsoftは、過去に「OSSではない」と指摘された"Shared Source" CLIを、githubで公開することができる)。しかし、公開されているソースコードは誰でもcloneしてコピーを個人的な範囲で自由にでき、あるいはgithubの登録ユーザーがforkして自分の管理下に置いて公開することが出来る(これは利用規約にそう書かれているので、たとえばソースを公開しつつ「転載禁止」とすることはできない。少なくともgithub上には転載されうる)。プライベートリポジトリを作成しておいて、そこへのアクセスを別途登録ユーザーに対してのみ開放するようなトリッキーなこともできる(たとえばEpicGamesのUnrealEngine)。もう少し補足すると、githubでは課金ユーザーがプライベートリポジトリを持つことが出来るし、無課金ユーザーでもorganizationを作って複数アカウントでグループを運用することも出来るが、organizationのプライベートリポジトリはEnterpriseなどの契約を結ばないと作成できない*4

githubはもとより営利企業であって、github.comはプロプラエタリなサーバーソフトウェアによって動作している。GitHubMicrosoftになるからといって、オープンであったものがプロプラエタリになったりするわけではない。GitHubはもともとOSSコミュニティに対してそれなりに積極的な支援の姿勢を見せてきたが、これはあくまで彼らの主観的な方向性であって、Natが指揮するGitHubも同様であると言われている(主観的な議論なので、客観的な成果は今後を見て評価するしかない)。Natが過去にOSS方面で一定の活動をしてきたことは考慮してもよいし、しなくてもよい。会社や立場が変われば事情も変わるはずだ。

オープンソースステークホルダーについて

developers, users, promoters, and co.

わたしがたまにセッションスピーカーとして参加していた台湾のカンファレンスにCOSCUPというものがある。正式名称を Conference for Open Source Coders, Users and Promoters というもので、長々しくて面食らうかもしれないが、オープンソースのコーダー(開発者)、ユーザー、広告屋(プロモーター)を参加者とするイベントである。まあ名前が幅広く「ユーザー」や「広告屋」(つまり非技術者)までカバーしていても、実質的には開発者向けイベントの側面が強い*5。しかし、ここで気付いてもらいたいのは、「オープンソースのコミュニティ」にはさまざまなステークホルダーが存在する、ということである。githubの運営会社が変わると、開発者が歓迎することであっても、そのユーザーにとっては面倒が発生するということがありうる。

OSSのソフトウェアは多数公開されているが、単独で完結していないものが多い。ソフトウェアには依存関係がある。ソフトウェアは割とソーシャルにできている。だから、自分がGitHub社やMicrosoft社と特に無関係であっても、自分のソフトウェアが依存しているソフトウェアの開発者や、あるいは逆に自分のソフトウェアに依存している開発者が、何かしらの利害関係を有していると、自分も無関係ではいられないことになる。

Are OSS people really opponent?

githubの買収に否定的なのはOSSコミュニティである、みたいな言説がよく流れていて、これが正しいかどうかはおそらく誰も検証していないと思うが、いくつか指摘しておくべきことがある。まず「オープンソース」は「フリーソフトウェア」とは違っていて(概念的にはフリーソフトウェアOSSに含まれる)、フリーソフトウェアの開発者や支持者のうち原理主義的なユーザーは、以前からプロプラエタリなGitHubも拒絶しているのである(たとえばRichard Stallmanはこうだ)。少なくとも利用していることがライセンス上矛盾しているとまでは言えないので、そこまで求めない関係者も多い。AGPLの思想とは相容れないとは言えそうだ。

フリーソフトウェア原理主義的であるかは別として、OSSコミュニティでgithubのようなサービスを使って「いない」ところも実はかなり多い。gitサーバーは自前で立てることもそれなりに簡単にできる。過去にはsourceforge.netがOSSのハブとして機能していたこともあって、今でもsf.netを使っているプロジェクトもまれにある。もっともsourceforgeマルウェア組み込み事件など多数の問題を起こして、だいぶ信用を失っていった。他には、GNU Projectではsavannahというサービスを提供している。githubの競合相手でもあるgitlabは、自分たちのソースコードを公開していて、これはgithubよりはフリーソフトウェア支持者の思想と相性がよい。GNOME ProjectはLinuxデスクトップの大手だが、github買収騒動のほんの数日前に(記憶が正しければ、自前ホスティングから)gitlabに移行した。

githubそのものは、特に技術的な「色を付ける」ことをしていないが、実際には「githubリポジトリがある」エコシステムとそうでないエコシステムがあって、githubだけを見ていても実際の技術トレンドが正確であるとは言い難い。ざっくりとした評価にしかならないが、旧くからあるUnix系のライブラリやツールはgithubを使っていないことが多い。Web系の技術ではよく使われている。githubに一番コミットしているのは今回の当事者であるMicrosoftらしいが、では.NETが開発の主流かというとそんなことは無い(MSはvscodeやTypeScriptも公開しているので、これらも大きな割合を占めている)。しかしいずれにしろ、GitHubMicrosoftのものになって、Microsoftが.NETのリポジトリを特にプロモートするようなことになったら、githubからある程度の技術トレンドをフェアに推測することすら出来なくなる。Microsoftには会社全体として統計を偏らせるインセンティブがあることは否めず、githubは不信感を持たれないように機能を実装していく必要があるだろう。

何度でも書くが、いくらNatが「信用してほしい」と言っても、その信頼性が高いと言っても、それを信じない人には信じない正当な理由がありうる。だからこそNatは「信用してほしい、とは言わない」と言っているのである。彼はこの点とても率直で誠実に事に当たろうとしている、とわたしは考えている(もちろん「だからGitHubの運用も信用してほしい/したほうがよい/しないのは不当に疑り深い」などと書くと彼の言葉選びが台無しになるので、わたしも書かないし、そういう主張をしている人にはNatの真意を汲み取ってもらいたいと思う)。

gitリポジトリは複数のサーバーに複製できるので、githubに「ミラー」を作られていることが多い。AndroidLLVMGNU各種プロジェクトなど、ポピュラーなOSSプロジェクトは、たいがいgithubにミラーが置かれている。これらはあくまでミラーであって本家ではないので、それらのソフトウェアの開発者自身がGitHubからMicrosoftへの体制変更で影響を受けるということにはならない。しかし前述の通り、OSSにはさまざまな立場で関わってくる人がいて、その中には「githubにあるミラーを依存リポジトリとして活用している」という人もいる。彼らが体制の変更について文句を言って聞いてもらえる立場であるかどうかは別途検討を要するが、利害関係があることに変わりはない。

しかし、「OSSコミュニティが文句を言っている」という字面から想像されるような構図は、こういった実態を踏まえて考えると、実のところ違和感しかない。

立場が逆であったらどうなっていたか考える

XamarinはMicrosoftに買収されるまではGoogleサービスを使っていた。メールはgmailでやり取りされ、Calendarも自然にGoogleが使われていた。Microsoftになったことで、Googleは使えなくなってしまった。社外秘のメッセージをこともあろうにGoogleに読まれるようなことになったらまずい、ということがあろう*6githubではプライベートリポジトリを使って非公開のソフトウェアを開発してソースを管理できる。GitHubが競合相手だった会社は多くないが、経営主体がMicrosoftとなれば話は変わる。

AppleGoogleなどは、元来github以外でソースを管理していて、直接的な影響を受けることはないかもしれないが、いずれにしろ、利害関係者の幅が格段にひろがるのは紛れもない事実である。githubからリポジトリを撤収しなければならないという判断を下す会社もあろう。Wiredの記事では、cycle.jsの作者はリポジトリをgitlabに移行したというし、JetBrainsは今後もgithubを使い続けるとしている。今回の動きについては、間違いなくMicrosoftのアクションによって引き起こされたものであって、OSSコミュニティの一部の反応にも理がある。これを「MS嫌いの」OSSコミュニティが文句を言っている、と評価するのは筋違いである。cycle.jsが移動するなら、cycle.jsにまつわるライブラリのリポジトリも移動するかもしれないだろう。

もしMicrosoftではなくたとえばGoogleGitHubを買っていたら、Microsoftリポジトリを撤収したかもしれない(わたしはdotnetグループに属していないので彼らのorganizationのリポジトリは見えないが、.NET Coreの開発はgithubで行われているようだし、プライベートリポジトリがあって何かを準備していたとしてもおかしくはない)。立場が逆だった時に「MSは未だにGoogleに反感をもっているのか」と言われたらどう思うか、考えてみるとよい。

多様性の尊重と哲学の相違

直接の利害関係が無いとしても、SCMビジネスの世界におけるパワーバランスが極端に変化するのを、健全な競争社会のあり方として懸念して、少しでも以前の状態に近いかたちに戻そうとする人もいることだろう。わたしもそのような行動を取ることがまれによくある。Twitterによる独占を懸念したMastodonユーザーもいたはずだ。こういう声に対しては、わたしは引き止めるために言えることは何も思いつかない。リポジトリだけなら独占することは出来ないんだし両方使っていても別にいいんじゃない、くらいのことは言うかもしれないが、開発者としては明らかに無駄だろう。ミラーを用意するのは誰でもいいはずだ。

これですら、別に「Microsoftが嫌い」だからそうしているわけではない。わたしは好んでFirefoxを使っているけど、Googleが嫌いだからChromeを使わないわけではない。

Microsoftが嫌いだ/信用できないから使わない

もちろん世の中にはMicrosoftが嫌いな人もいるだろう。わたしは個人的にNadellaはとてもよくやっていると思っているし、彼が指揮している部分のMicrosoftは積極的に支持しているが、ハラスメントやスキャンダルに満ちた会社や組織は決して支持しない。MSに親を殺された人間*7に「2018年にもなってまだMSが嫌いとか言ってるのか」みたいな無神経なことは言えないだろう(少なくとも真人間であるわたしには出来ない)。各々には各々の理由があって好き嫌いがあるのであって、それが無知によるものなら具体的に啓蒙すれば良いことだし、個人的なものであるなら(法規範などルールに牴触するものでもないかぎり)他人があれこれ口出しするほどのことでもない。そもそも他人に口出しする前に自分を省みるべきである。

diversity and inclusionを維持していくために

長々と書いてきたが、GitHubから他所へ移行しようという人たちも、おおよそMicrosoftが「嫌い」だからそうしているのではないし、Microsoftが「嫌い」であるという人たちにも相応の理由があってそうしているということをわれわれは尊重しなければならない、ということを書いた。

今回わたしが観測した中には、OSSコミュニティに対する侮辱意識をもって誹謗中傷しているようなのもあったのだけど、こういう、非マイクロソフト的な態度の人間には噛み付く「マイクロソフト騎士団*8」のような姿勢は歓迎できない。Nat Friedmanが6/7に行ったreddit AMA (ask me anything)のこの回答は、自分たちに否定的な立場をとる開発者たちについても、真摯な姿勢を見せている:

"Developers are independent thinkers and will always have a healthy degree of skepticism, but I admit I was sad to see that some felt compelled to move their code. I take the responsibility of earning their trust seriously. (...) I hope those who have tried out other Git hosts in the past few days will keep an open mind and consider moving back once we’ve demonstrated our commitment to openness and made GitHub even better. If they choose not to move back, that’s their prerogative and we celebrate developer choice even when developers don’t choose us."

(強調筆者)

Natは開発者(特にOSSコミュニティに近い開発者)というものがどういう人種であるのか、よくわかっている。こういう姿勢を見習ってほしい。

Microsoftの社是はempower everyoneであり、それをもう少し具体化した指針のひとつにrespect diversity & inclusionというものがある。さまざまな立場の人たちを受け容れ、サポートしていくことが、現在ではMicrosoftらしいやり方なのである。

最初から中立的な存在であったGitHubに、今さら新しいMicrosoftの良いところを取り込んでもらいたいと思うようなおこがましいことはないが、新しい組織体系になっても「旧」に腐食されること無く、より価値をたかめていってほしいと思っている。

*1:この辺はわたしは遠巻きに眺めていた程度にしか知らないのだけど、その後Beagleに繋がっている。Beagleハッカーはその後何人もGoogleにさらわれてしまったのだった…

*2:たとえば、わたしはacceptableだと思っているけど、ページのトップに早速合併を報告するバナーが出てきたことを取り沙汰する向きはtwitterではそれなりに観測された。これを「良くない」というユーザーもいることだろう。

*3:公開は無償で、管理はプライベートであれば有償で、それぞれ行えるものなので、ここでは区別した。

*4:これは関係者にしか意味がないけど、Xamaritansの技術書典用のリポジトリがわたしの個人リポジトリになっているのはそういった事情がある

*5:この辺は「技術カンファレンス」を標榜しているのに実際には非技術者向けイベントと化しつつある日本マイクロソフトのde:codeなんかとは真逆の感じになっている。

*6:そこまでは言わないかもしれない。Googleは決してそんなことはしないだろうという一般的な推測がはたらくが、リスク計算はされる

*7:間接的な理由を含意するネットジャーゴンとして読むこと

*8:マイクロソフトシンパと書いたら主語がでかすぎるとコメントをいただいたので表現を変えた

Xamarin最新情報2018 (de:code2018) の補足情報

de:code2018が何とか終わりました。イベント自体にいろいろ問題はありましたが、とりあえずそれはおいておいて、わたしのセッションに来ていただいた方はありがとうございました。

スライドはこちらで公開してあります(イベント事務局側でも録画とpptを公開するんだと思います)。当日に「期待していた内容と合っていない…!」みたいな事故を防ぐために数日前にプレビュー版を事前公開していましたが、そもそもtwitterで事前チェックの発言を発見した人がいたかどうかは不明…

speakerdeck.com

事前に軽くしゃべってみたら80分くらいかかってしまったので、いろいろ削って、でもストーリーラインは何とか残しておこうとなった結果こんな感じでしたが、いろいろ端折ってしまったので、ちまちま補足しようと思います。

Ooui.Wasm

デモの手順はほぼOouiのwikiに書いてあるとおりです。Webサーバはこれと同様にdotnet-serveをインストールして使いましたが、Webサーバであれば何でも良いので、たとえばWeb Server for Chromeなんかでもいけます。

中に入っているmono.wasmやらmono.jsやらは、Oouiがmonoのwasmサポートのビルド済みアーカイブをダウンロードして使っていて、その場でビルドしているわけではありません(monoランタイムはでかいのでかなり時間がかかるはず)。ちなみに.NET Coreコンソールアプリで、Linuxからでもビルドして実行できます(Workbooksを動かそうと思ったのでMacにしましたが、そうでなければUbuntuでセッションやるつもりでした)。

デモで使用したバージョンは0.10.222でしたが、この中で使われているXamarin.Formsは2.5です。せっかくWebなのでFlexLayoutを試そうかなあなどと思ったのですが、実装されているかを確認する以前の問題でした。

ちなみに、wasmを使うものではないのですが、HTML5ベースのCanvasを使ってブラウザ上にGUIレンダリングしようというプロジェクトは他にも、というか大昔から存在していました。gtk-broadwayというやつです。これはクライアント1つにつきWebアプリのセッションを1つ使うもので、あまり現実的に使えるものではなかったと思います。PoC (proof of concept)としては面白いというやつです。あとUnityのWebGL projectなんかは概念的には近いものになっているんじゃなかろうか。

あとOoui.Wasmがこれだけ動かせるんならControlGalleryくらい動かせるんじゃねーの…?と思って自分でプロジェクトを作って移植してみたりしたのですが、実行時に謎のエラーになり、冷静に考えたらFormsのmasterからとってきたサンプルであるところのControlGalleryが2.5のやつで動くわけねーな…!ということになりました。試すまでもなくlimitationsがどこかにまとまっていたのですがちと今すぐ見つからない…

Workbooks

Workbooks。2006年頃から存在していたC# interactive shellを中心としたツールの現在の姿であるといえます(当時はMono.CSharp.dllでしたが、現在ではRoslynです)。C# interactive shellがVSに載ったのが3,4年前くらいだと思うと、この方面のmonoのイノベーションはRoslynの7,8年くらい前には起こっていた感じです。

ASP.NET Coreで作られたWeb版ですが、Reactアプリです。まだ鋭意開発中のやつです。デモでも再現したのですが、いったんコードの文法ミスなどでREPL実行がエラー評価になるとどこかで非同期処理がバグっているらしくdotnet runを再実行しないといけなくなる状態です。ちなみにmasterブランチで出来ます。トップディレクトリでdotnet buildを実行した後、Clients/Xamarin.Interactive.Client.Web/ ディレクトリでdotnet runするだけです。

WorkbooksはC#オブジェクトを結果として表示するとき、デフォルトではプロパティリストのようなかたちで表示することになるのですが、これをカスタムレンダリングすることも可能です。この場合のレンダリングとはHTML文字列なのですが*1、この辺の仕様はドキュメント化されているものの、まだプレビュー状態で、しかも開発者と相談していたら「これからReactコンポーネントに書き換える予定だから今はやめとけ」と言われたので、この辺で遊ぶ予定だったのですがあきらめました。

デスクトップ側も動かそうとして失敗したわけですが、agent側のアプリも終了しないとクライアント側だけ切って再起動とかやってもそのクライアント セッションでは二度と立ち上がらなくなるようなので、この辺の接続状態の試験シナリオが足りていないのでしょう(まあ普段agentを落とす必要は無いのですが…)。

ちなみにデスクトップ版ではFormsも試せるのですが、これはバージョン2.5固定です。3.0のnugetパッケージなどに更新したら期待通りには動作しません。これはWorkbooks agentが固定バージョンを想定して作られているためです(そうしないと挙動をうまく制御できなかったらしい)。WorkbooksでFlexLayoutのデモをやろうと思っていたのですが、これもあきらめました。ただ開発チーム的には2.5でないと困る理由はなく3.0にしたいと言っていたので、そのうち上がるでしょう。

FlexCSS

ReactNativeでyogaが使われていて云々については、Cheap Dive into React Native (booth)に書かれていた話で、これがR/Nの中身を知るのにはよさみがあるので、興味がある人は読むといいでしょう。

CSSをサポートに対してXAML至上主義者がネガティブだという話、具体的にはこういうのを見てもらえればわかると思います。わたしは今後一切XAML至上主義者を助けまいという気持ちになりましたが、これはあくまでわたしの意見なので、壇上ではそこまでは言いませんでした。ちなみにBuildのForms 3.0のセッションでも「否定的な意見も出てくるのだが…」くらいのニュアンスでそういう話を紹介しています。

XAMLまわりもWPFもそうなんですけど、Windowsチームが作っているものって、.NETチームが作っているものと違って、2018年になっても何もオープンソース化されないんですよね。.NET Core 3.0に追加されるというWindows desktop packもバイナリ配布ですし。VS/VSMac d15.7におけるXAMLサポートの拡充も、そういう状況のもとで行われているんだ、ということは、もっと知られてもいいのかも。

XAMLに生き残らせる価値があるのか、よく考え直す時期に来ていると思います。

LiveReload

hot reloadの類型である、という話をして紹介したのですが、stateとviewの分離が重要である、という話をもっと強調しても良かったかもしれません。FlutterのHot Reloadのページにも、"sometimes described as stateful hot reload,"と書かれているように、実行中のstateを維持したままviewの変更を反映する、という意味合いの強い機能であり、だからXAMLのLive Reloadなのであり、MVVMに準ずるviewとstateの分離が重要なわけです。

現状XAMLのみのサポートですが、理想をいえば、Elmish.XamarinFormsのようなXAMLAPI呼び出しもコード分析して反映できるとうれしいでしょう。まだコードを読んでいませんが、flutterのhot reloadはそういうDartの実装が含まれているのだろうと理解しています。

Android StudioにはInstant Runという機能があり、これにはcold swap / warm swap / hot swapという3段階の機能レベルがあるのですが(最近の状況はわかりませんが、hot swapまで行くとだいぶ動作が怪しかったものでした)、レイアウトリソースの更新はwarm swapのレベルで実現しています。これがhot reloadに近い存在です。ちなみにhot swapは実行中のコードの差し替えも行うもので、これはVisual Studio使いにはedit and continueと言えばわかりやすいでしょう。XamarinにもLive Playerという機能があります(de:codeでは川合さんのセッションで紹介されていたもの)。

所属とか組織とか

最後におまけですが…Xamarinは合併直後はAzureというかGuthrieの下に雑に統合されていたものが、VS/mobileチームということになって、グループとしてはVSということになったみたいです。それに伴って、Test CloudやらApp Centerやらといったサーバー関係のチームはXamarinからサーバー製品のチームの下に再編成されたようです。もともとtest cloudはless painfulを買収して成立したチームですし、独立性は高かったので、あまり違和感はないですね。

そういうわけで、App Centerなどのサーバー製品はXamarinとは無関係になり、個別に発展していくことになるでしょう。われわれは本来のXamarinとしてMonoを中心としたフレームワークの開発に注力していくことになりそうです。

*1:ちなみにこれはWeb版だけでなくデスクトップ版クライアントでも同様です。表示しているのはInspectorと同じWeb UIなので