++C++; // 未確認飛行 C ブログ

http://ufcpp.net/

Archive for 10月 2011

Roslyn CTP – October 2011 を触ってみた

with 4 comments

先日インストールしたRoslyn、ちらほら見始めています。公式サンプル、ドキュメント、Walk-Throughや、フォーラムtwitter(ハッシュタグ #RoslynCTP)等々。

Codename “Roslyn”とは

Roslynは、C#とVBのコンパイラーをManagedコードで書き直して、コンパイラー内部の中間的な情報に誰でもアクセスできるようにします。

今までは、文字列のC#ソース コードを与えて、バイナリの.NET Assemblyを出力する一枚板(monolithicな)ブラック ボックスでした。一方、Roslynでは構文パーサー、意味解析エンジン、ILコード生成部、スクリプト エンジンなどを公開していて、ソース コードの静的解析やリファクタリング ツールなどを作りやすくなります。

Roslynの最終目標

Roslynの説明でよく使われるのが以下の絵。

「BUILD 2011 TOOL-816T: Future directions for C# and Visual Basic」より

つまり、目標は以下のようなものです:

  • 独自のコード解析ツールや、リファクタリング ツールを作りやすくする。
  • REPL(いわゆる対話的実行環境で、1行1行実行しながらコードを書く)利用。
  • C#/VBへのDSL(domain specific language: 特定領域向けの独自言語)の組み込み。

そして、提供されるAPIには、大まかに、以下のようなものがあります。

Whitepaper: Roslyn Project Overview」より

それぞれの意味は以下の通り:

  • Compiler: 前述のような、コンパイラーの内部で使う、構文木や意味解析結果を参照するAPI。
    • C#とVBそれぞれで専用のAPIを提供
  • Scripting: C#やVBをスクリプト環境(アプリへの組み込みを想定)用のAPI。
  • Workspace: ソリューション(複数のプロジェクトを持つ場合も含めて)全体にわたって情報を得るためにAPI。
  • Service: Visual Studio IDEの機能(IntelliSenseやリファクタリング)と連携するためのAPI。

October 2011 CTPの現状

現状のRoslynは、Visual Studioが前提/最優先な感じですね。

まだ最初のCTPなので、優先事項がはっきり表れています。

Workspace/Service API

まず、Workspace APIの、ソリューションの下にプロジェクトがあって…というような構造が、Visual Studioのそれそのもの(そんなに変なことはしていないので、「Visual Studioに依存」というほどのものではないですが)。

Service APIに至っては、そもそもVisual Studioを拡張するためのAPIという感じです。

そして、October 2011 CTPで、サンプルの比率が一番多いのはService APIになります。明らかにここが優先事項になっている感じ。

Visual Studio拡張の例(公式サンプルの説明)はこちらのブログ(MSDN, Visual Studio Blog)などに:

Scripting API

次点でScripting API。サンプルやWalk-Throughもそこそこあります。ただし、現状はC#のみ。

一応APIはそろっているので、自分で作ったプログラムにC#スクリプトを組み込むことは可能。

Host Object Model(スクリプトのトップ レベルがどういうオブジェクトになっているかを指定。スクリプトで使ってもらいたいメソッドなんかの文脈を与えられる)を指定してC#スクリプトを実行できます。

一方、(プログラムを作ることなくC#スクリプトを実行できる)Roslynに含まれている実行環境としては以下の2つです。

  • rcsi.exe:
    • (対話的でなく)スクリプトを一気に実行する。
    • \Program Files (x86)\Microsoft Codename Roslyn CTP\Binaries にあります。
  • C# Interactiveウィンドウ:
    • Visual Studio内のウィンドウでC# REPL。
    • IntelliSenseやコードの自動整形など、通常のC#エディターでできることはこちらでも働きます。

つまり、(Visual Studioの外で動く)単体のC#スクリプトREPL環境はまだありません。

Compiler API

とりあえず、C#/VBの機能のうち、主要なものだけは実装できたというレベルです。(参考: 未実装項目一覧

まして、組み込みDSL的な方面の機能は全然。通常のC#/VB(のサブセット)をパース/意味解析できるだけです。

また、拡張性などを考えすぎることでパフォーマンスを落としたくないようです(C#/VBは、Visual Studioでリアルタイムに構文チェックして、ハイライトやエラーの指摘をする前提なので、コンパイラーのパフォーマンスはVisual Studioの使い勝手に直結するため)。

DLRとRoslyn

Roslynと似たようなものに、DLR(Dynamic Language Runtime)があります。主目的は、以下のように差があるんですが、結局、近い部分もあるはずで。

  • DLR:
    • 動的言語を.NET上で動かすためのライブラリ。
    • Roslynでいうと、Scripting APIの部分が近い。
  • Roslyn:
    • 上記の通り、一番力が入っているのは、いかにしてVisual Studioとコンパイラーを連携させるかという部分。

構文木

DLRとRoslynの一番の差は、DLRがSystem.Linq.Expressions名前空間以下の式ツリーを使っているのに対して、Roslynは使っていない(直接ILを生成)ところですかね。

式ツリーは、どんな言語でも使いそうな汎用的で、比較的低レベルな構文にしか対応していません。たとえば、yieldステートメントに対応する式ツリーを持っていないのは当然として、ループも1種類(while(true) { }に相当。適宜breakする前提の永久ループ)しか持っていません。

DLRでは、例えば、IronPythonなら、Python専用の構文木から、一度、式ツリーに変換して、それを実行する仕組みをとります。

一方、Roslynでは、C#/VB専用の構文木から、直接IL生成します。これは、前述の通り、パフォーマンスを得るためと思われます。

DLR利用プログラムからC#スクリプトを利用

要望は出ていて、それに対する回答としては、「考えてはいる。今はまだ。」という感じのようです。

ちなみに、DLRからC#スクリプトを利用というのは、app.configへの設定と、以下のようなコードでC#スクリプトを実行できるようにしたいというものです。

var engine = scriptRuntime.GetEngineByFileExtension(“.csx”);

メタプログラミング

Roslynのスコープに入っているのは、組み込みDSL(C#/VBの内部に、独自の拡張構文を組み込む)です。

それに、現時点のOctober 2011 CTPでは、その手の機能は全くなさそうです。

独自のパーサー定義はスコープ外

つまり、MGrammarでやっていた様なことは想定外ですって。

MGrammar = SQL Serverチームのものだった

まあ、SQL Server Modelingという製品の一部として世に出たものですからねぇ…

SQL Server Modeling自体はお蔵入り、M言語は残すらしいけども、M言語の行く末はVisual Studioチームの知る由ではない模様。

世に出す場所を間違えたか…

DSLといっても、大部分は既存の言語の文法を使いたい

特殊な、独自の文法を使うに値する部分はそう多くないといわれています。DSLに条件分岐とかの制御構文を含めたいことも多々あるわけですが、その場合、C#使いならC#のifを、VB使いならVBのIfを使いたいわけです。

なので、独自パーサーのサポートまでスコープに入れるつもりがないんでしょうねぇ。

UnknownAccessor

現状、言語拡張できるポイントがないと思っていたんですが、1個、拡張に使えそうな点が。

案の定というか、まず真っ先に思いつくこととして、依存関係プロパティの自動実装のためにRoslynを使う人がいるわけですが:

で、サンプルのコードを見ていると、以下のようなものが。

[dependency] public int Widgetude
{
change { /* on-change logic here */ }
}

changeアクセサー!

どうも、これ、構文のパースまではできるみたいです。意味解析の時点でエラーになりますが、構文解析の時点のSyntaxTreeを書き換えることでメタプログラミング可能。ちなみに、構文木的には、ノードの種類がSyntaxKind.UnknownAccessorDeclarationというのになります。

Written by ufcpp

2011年10月21日 at 15:37

カテゴリー: .NET

Windows Phone 向けフィードバック

leave a comment »

フォーラムに↓このようなものを投稿するなど。

で、これに関して、ちょっと知っておいてもらいたい事柄をいくつか。

数字を伴うこと大事

日本と比べると米国自体がというのもありますけども、その中でも、マイクロソフトは数字を伴ったフィードバックを非常に重要視します。

よく問題になるのは、日本人は製品版が出てからバグを見つけて文句を言うとか、フォーラムが盛り上がらないから問題ないと思っていたとかそういうのです。

今まだ IS12T しか出てないし…とか、変な遠慮をしてちゃダメで、問題は早期に伝えないといけません。また、数字を伴うっていうのは、立ったトピックに対して「投票」とか「△」みたいなボタンがついてますが、あれの数、相当影響力あります。twitterの☆とかFacebookのいいね!程度の感覚で、共感したものはボタン押しまくりましょう。

現状と今後(今から手を打っておかないと)

特に、今回のこの問題は、Xbox Live インディーズゲーム(XBLIG)の頃からいまだ対処してもらえていない問題です。

これは、どの程度重大な問題かを認識してもらえていないということです。認識していない理由は、上記の通り、数字を伴ったフィードバックの不足というのが大きいです。

XBLIG の頃は、それこそもう、Xbox 自体の日本での状況が悲酸なものだったので、「数字」を出すこと自体が厳しかったです。

なので、状況を打開するなら今なのかなぁと思っています。WP7 の日本での敗着が確定的な色合いになってしまう前でないと手遅れになります。

また、放置しておくと、同様の問題は Windows 8 の Metro マーケットプレイスでも起きると思われます。その意味でも、早い段階で、数字を伴ったフィードバックが必要です。

複数言語混在: どういう問題なのか

日本語にアルファベット混ぜんなって怒られています。普通に日本人ならよく見るレベルの、簡単な英単語ですら、日英混在とみなされます。

ただ、きっちりしたアプリを作るのであれば、アルファベット混じりっていうのはあまり褒めれたものではなくて、できればちゃんと日本語に翻訳した方がいいです。

この辺り、マイクロソフトの社内規定的には、相当しっかり、徹底してアルファベットを残さないようにしているはずです。たとえば、マイクロソフト関連のウェブサイトをいくつか見てみると、残っているのは、基本的に、

  • Windows などの固有名詞
  • CRM など、訳しようがなくて、日本でもそのまま使われている3文字略語

くらいで、例外は「Web」と「Code Recipe」くらい。

ところが、世の中そんなかっちりしたものばかりではないというか…

マイクロソフトのサイトはこの辺りきっちりしているがゆえに、なんか堅苦しくて若い人に受けなさそうというか。

若者向けで緩い分野、ゲームなんかだと特にですけど、こういう堅苦しさを残しちゃいけない世界というのもあるわけですが、マイクロソフトはそういう言う方面に弱いです。

最近になって、Windows Phone 7 がらみの言葉(People Hub とか)を訳しかねて悩んでる辺りを見てもらってもわかる通り、最近ようやく手を出したところなので、勘所まったくないはずです。

日本法人の社員の方がいくら把握しててもダメで、米本社に、そういう緩い分野における日本の感覚を伝えないといけないです。(そしてそれも、ユーザーからの「数字」しか方法はないです。日本法人社員の個人の発言よりも、ユーザーの、数字を伴ったフィードバックの方が優先されます。)

Written by ufcpp

2011年10月20日 at 10:43

カテゴリー: 未分類

Compiler as a Service, コードネーム“Roslyn”

with one comment

やっときたー。

さすがに触ってる余裕ないのでとりあえずリンクのみ。

といいつつ、動画を1個:

Roslyn さっそく触ってみた

Written by ufcpp

2011年10月19日 at 19:15

カテゴリー: .NET, C#

Tagged with ,

今月は MSDN が非同期処理の記事だらけ

leave a comment »

非同期だらけだった BUILD の後というのもあって、MSDN Blog も MSDN Magazine も非同期だらけですねぇ、ほんと。

というか、BUILD のセッション内容がそのまま記事になった感じ。

いくつかの記事に関して、概要をメモ書き程度に:

Easier Asynchronous Programming with the New Visual Studio Async CTP

http://msdn.microsoft.com/en-us/magazine/hh456401.aspx

そもそも async が必要とされる理由に関して。応答性良くするために他にどういう手段が考えられて、その手段だと何が問題かを説明。

  • 解1: スレッドたくさん作る
    • 確かに応答性は改善
    • リソース無駄食い
      • (ほとんどは待ち時間なのに)客の数だけウェイター雇い、オーダーごとに2名ずつコック雇うような無駄遣い
  • 解2: DoEvents はさむ
    • これが解になりえるのは、小さい処理を大量にループする場合のみ
    • ループの合間に挟めない場合、無意味
      • (非同期 I/O だとそもそも絶望だし、ループであってもソースコードに手を入れれるとは限らない)
    • 最後のイベントから順にしかこなせない
      • 割り込みが入り続けたら、最初のイベント処理がいつまでたっても終わらない
    • 再帰的な再入(処理が終わる前に、同じ処理が呼び出される)される
      • この手の歳入があった時に、きちんと排他処理できる設計をする開発者あまりいない
  • 解3: 「これが終わったらこの処理を続ける」チェックリストを残して処理を中断
    • 旧来的には、コールバック(前段の処理が終わったことを通知)の登録
    • 元の同期版(ワークフロー図通りのコード)と比べてコードの見た目がぐちゃぐちゃに
      • 順序通りにかけなかったり、かけても再帰が深くなったり
      • 書くのも保守も大変 → 応答性というものに対して払うコストが高すぎる
  • 解4: そこで、C#/VB vNext の async
    • クラス ライブラリ(Task<T>)とコンパイラーががんばる
    • コールバック的な効率のいい非同期処理を、同期の場合と同じように書ける

Async Performance: Understanding the Costs of Async and Await

http://msdn.microsoft.com/en-us/magazine/hh456402.aspx

C#/VB の async を使えば、同期版のコードほぼそのままで非同期処理が書ける。もちろん、その分、多少のコストもかかるものの、ほとんどの場合は気にならないレベルのはず。

ただ、1歩進んだ視点としては、そのコストを気にかけ、必要に応じて(コストが見えるレベルになったとき)コストを避けれるというのも大事。この記事では、async で何も考えずに書いてて掛かる/やりようによっては避けれるコストについて説明。

  • Task をキャッシュしておく
    • Task のインスタンスの割り当てもそれなりにコスト
    • Task が完了してたら、Task.Result にすでに結果が入っているはずなので使いまわす
    • こういう場合、async キーワード使わずに、自前実装にして Task が自動生成されるのを避けたり
  • 同期コンテキストを意識する
    • await 読んだ時点で現在の同期コンテキスト(SynchronizationContext.Current)がキャプチャされる
    • その同期コンテキストを介して継続処理が呼ばれる
    • 結果として、意図せず、コンテキストの切り替え(多くの場合、スレッド間のマーシャリングにつながる)が増えることが
      • これを避けるための、ConfigureAwait っていう拡張メソッドも用意されてる
  • ガベージ コレクションよけ
    • async メソッドの中身は、内部的に一段階、ラムダ式でラップされる
    • なので、ただのローカル変数だと思っていたものが、匿名クラスのフィールドになったりする
    • 不用意にローカル変数増やすと、意図せずインスタンスを保持しっぱなしになって、ガベコレで回収されるのを遅らせる可能性がある
    • といっても、Sum(await a, await b, await c); みたいなことしても、どの道、一時変数が作られるんで、この場合は var ra = await a; で OK
  • 複数の Task を併走させる場合は WhenAll で await を1個に
    • 並列処理になる分、待ち時間減るはず

※同期コンテキスト

例えば以下のように、ある種の文脈(context)を持ってるフレームワークがある

  • WPF では、UI 操作は必ず UI Thread で行う必要がある
  • ASP.NET では、HTTP リクエストと処理が紐づいてる(紐づけが切れると正しくレスポンス返せない)

SyncronizationContext の Post メソッドとかで、必要な文脈で処理を行うことができる

  • WPF だと、DispatcherSynchronizationContex ってクラスがあって、ディスパッチャーを介して UI スレッドに処理を戻してくれる
  • ASP.NET だと、AspNetSynchronizationContext ってクラスがあって、ちゃんと HTTP リクエストとの紐づけを行ってくれる

Pause and Play with Await

http://msdn.microsoft.com/en-us/magazine/hh456403.aspx

async の内部実装について。

だいたい、「非同期メソッドの内部実装」で書いてるような内容。

Thinkin’ About Async

http://msdn.microsoft.com/en-us/magazine/hh456392.aspx

今月の MSDN Magazine は Editor’s Note すらも Async。

上記「Pause and Play with Await」の著者 Mads Torgersen と、Visual Studio のプログラム マネージャー Lisa Feigenbaum のインタビューの断片に。

インタビューのもっと詳細なのは、以下のブログで公開されていたり

内容を、いくつか断片的に拾うと

  • Q. 今から(すでに RTM な .NET 4 までの範囲で)できることは?
    • 非同期処理は全部 Task-based (Task を戻り値とするメソッド)で書いとけ
  • Q. C#/VB、いろいろ取り込みすぎでは?
    • 全部、C#/VB に適した形で取り込んでいる
    • だから、同じ機能でも C# と VB でずいぶん形が違う(たとえばラムダ式)
  • Q. async はもっと早くに提供されていてもよかったのでは?
    • 言語の設計は非常に慎重なプロセスで、正当性の確認が終わるまで新しい要素は入れない
  • Q. この新しい機能を広めていくのにどういう姿勢で臨みます?
    • もちろん、いろんな形態(サンプル、プレゼン、ハンズオン、フォーマル等々)で情報提供していく
    • 一方、言語設計のやり方にも影響があって、既存ユーザーを意識して製品作ってる(覚えやすく/受け入れやすくなるよう設計)

Task Exception Handling in .NET 4.5

http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/10217876.aspx

互換性が最優先なんで、Task の挙動も大部分は .NET 4 から変わっていないものの、一部、例外の挙動とかで留意すべき点が。

Unobserved Exception

Task は、別スレッドで起こった例外を、元スレッドに伝搬する前提なので、別スレッド中で例外がハンドルされなくてもアプリはクラッシュしない(だから、Unhandled Exception という表記でなく、Unobserved Exception になった)。

Task.Wait() や Task.Result、もしくは、Error プロパティで例外を「観測」できる。一切観測されなかった場合に限り、Task の Finalize 時に Unobserved Exception を出して、アプリがクラッシュするという挙動。

ところでが、C# 5.0 で async が入るとまたちょっとややこしく。例えば、

Task op1 = FooAsync();
Task op2 = BarAsync();
await op1;
await op2;

というコードで、op1, op2 が両方例外を出した場合、 await op1 の時点で op1 の例外は観測されるものの、await op2 が実行されなくなって、こっちの例外が観測されず、アプリがクラッシュすることに。

そこで、Unobserved Exception でアプリをクラッシュさせるかどうかを選択できるオプションがついたとか(デフォルトだとクラッシュしない方に変更されてしまったので、テスト時にはクラッシュするようにオプションを変えること推奨)。

Task.Result と await task

Task は Parallel クラスとかでも使いまくってて、並列処理前提(複数のスレッドで起きた例外をまとめる必要がある)。あと、スタック トレースをどうするかという問題もあるので、どんな例外だろうと、別スレッド側で起こった例外を別の例外でラップしてから元スレッドに伝搬させる必要がある。

なので、Task.Result したときに、例外があった場合、AggreageException が throw されてた。

ところが、await task の場合だと、並列性考える必要ほとんどない(WhenAll で並列 await できるけども、それも利用度合いは2割にみたないはず)。スタック トレースの問題も、System.Runtime.ExceptionServices.ExceptionDispatchInfo ってのを導入したんで解消した。

なので、実は、AggregateExpcetion でラップしちゃう挙動、変えてしまいたい。さもないと、どんな例外だろうと catch (AggregateExcetion) になってしまって、無差別 catch になってしまう。

で、実際ちゃんと、await task はラップ前の例外をそのまま throw するようになっているけども、それは“Awaiter”の層でやってる。task.Wait() の代わりに、task.GetAwaiter().GetResult() とやれば、ラップ前の例外を受け取れるようになる。

おまけ

Task クラスって、IDisposable で、MSDN にも「Dispose しろ」と書かれてるのに、Dispose 呼んでる例を見たことがないなーと。

MSDN Forum で、「どうやって Dispose すればいいの?ネスト深くなると大変だけど」みたいな質問に対して、回答で、「イベント ハンドル(小さいネイティブ リソース)握ってるだけ(しかも、Task の作り方によっては使わない)なんで、そこまで気にすることない。楽にできる範囲で Dispose すればいい。」とかついてた。

Written by ufcpp

2011年10月19日 at 07:15

カテゴリー: .NET, C#

Data Explorer、Drawbridge、等々

leave a comment »

家のメイン マシンを Windows 8 にしてしまって、いろいろ環境リセットしてしまったがためにいろいろ滞ってました。特に、先月ものすっごい忙しかったのも手伝って。

ようやくフィード消化するようになったので、久々に。

Written by ufcpp

2011年10月18日 at 16:21

カテゴリー: .NET

ウェブマトリックスマン

leave a comment »

ずいぶん前から描いてもらおうと思ってたのよねー、ウェブマトリックスマン

WebMatrix 2 Beta が出たタイミングにでも出せればよかったのだけども、やっぱり時期を外す…

WebMatrixMan

作画: Paese

ガンマ線浴びて緑の超人になったのよね?アヴェンジャーズ創設メンバーの1人で。

まあ、首のなさとかはむしろジャガーノート

Written by ufcpp

2011年10月13日 at 13:56

カテゴリー: C#たん

Windows Phone 7

with one comment

すごーく出遅れたような気がしないでもない、Windows Phone 7日本発売記念。

Windows Phone 7って、一応マスコットいるのよ、しかも立体物で

勢いで作っちゃった感満載。

ということで、C# たんに持たせてみる。

完成(指定サイズ)

作画: Paese

日本発売記念なのでドレスで。

Written by ufcpp

2011年10月10日 at 17:01

カテゴリー: C#たん

Tagged with ,