昨日のDesign Notes祭りとはまた別件なんですが、こんな提案が。

メソッド単位でAsyncMethodBuilder属性

corefx/coreclr方面でガッチガチのパフォーマンス改善をやりまくってる人からの提案。

タイトルからは内容がちょっとわかりにくいんですが、非同期メソッドの際に必要になるヒープ確保量を0 (no-allocation)にするためにこの機能が必要とのこと。

背景としては、

  • C# 6.0: 非同期メソッドの戻り値は常にTaskTask のヒープ確保が必須でつらい → C# 7.0: ValueTask<T>を認めた
  • ValueTask<T>、同期で終わるときにはヒープ確保0だけど、実際に非同期だとどうしてもTaskが発生 → 最近Mergeされたコミット: IValueTaskSourceってインターフェイスを使うことで、Taskを介さず非同期処理できるようにしたよ。うまく使えばTask分のヒープ確保がなくなる
  • IValueTaskSourceで、await毎のヒープ確保はなくせるけども、AsyncStateMachine の1インスタンスはどうしても残った → そのインスタンスをキャッシュして持ちたい

という感じ。

最終的に、ヒープ確保せざるを得ないインスタンスをキャッシュして、プログラム中で1個だけ(メソッド呼び出しのたびには新規ヒープ確保しない)とかにしたいわけですけども、キャッシュはうまくやらないと効率が悪くて困ることになります。

なので、メソッド単位でどういう非同期メソッド生成するかをカスタマイズできたり、AsyncStateMachine にthisを渡せたりしないとこれ以上の最適化が厳しいみたいで、やっと提案のタイトルにつながります。

AsyncMethodBuilder属性をメソッド単位で指定して、メソッドごとに非同期メソッドの挙動をカスタマイズできるようにしたいっていう話は昔からあったんですけども、需要が低いということで実装されずにいたんですけども。 こういう方面から改めて需要が出てくるとは…

UTF8文字列がらみ

去年の9月くらいにGo (Unicode Code Point のことを rune って呼んでる)に倣って Rune 型を作らない?みたいな提案が立っていましたが。 Rune って名前の評判悪すぎて、まあ、別の名前に落ち着きそう。

あと、C# のキーワードも用意したいみたいです。

C# キーワード 実際の型名 サイズ(Byte) 概要
ubyte System.CodeUnit 1 UTF-8エンコーディングされてる文字列の1バイト1バイト
uchar System.CodePoint 4 Unicode のコードポイント
ustring System.Utf8String 内部的に UTF-8 でデータを持つ文字列クラス
uspan System.Utf8Span ReadOnlySpan<ubyte>で、ustringの一定区間を参照する構造体

まあまだ正式な API の提案になってる段階ではないので、まだ変わると思いますが。