6/28に「CLR/H in Tokyo 第3回」の勉強会に行ってきました。
岩永信之さんのセッション「C#や.NET Frameworkがやっていること」で、メモしたことを書いておきます。メモリ管理
- ヒープ(スタックと比べて)
- 空いてる領域を探すのが大変
- 確保に時間がかかる
- 一般的にスタックに比べて確保する領域は多い
ガベージコレクション
- Gen0のメモリ領域が全部埋まったら、ガベージコレクションが実行される
- Backgroundスレッドで実行
- UIが重くなるのを防ぐため
Mark&Sweep方式と参照カウント方式
- 参照カウント方式の変数のコピー
- ポインターのコピーに加え、参照数のカウントアップ
- スレッドセーフにするため、意外と重たい
- ポインターのコピーに加え、参照数のカウントアップ
- サーバー
- Mark&Sweepが有利
GCあってもメモリーリーク
- 辿れるところにオブジェクトを持ったら、そのオブジェクトはずっとGC対象にならない
- 例:イベント購読
- メモリーリークを避ける方法
- ビューが消えるタイミングで忘れずにイベント購読を解除する
- 弱参照使う
- 内部で複雑なことをやってるのでパフォーマンス的にはおいしくない
- WPFでイベントバインドを使う
境界チェック
- 配列は常に境界チェックしているので、パフォーマンス的にはそれなりに負担
AppDomain
marshal by value
BinarySerealizer
- privateフィールドまでシリアライズするので、要注意
- privateフィールドの実装変えたら動かなくなる
- monoで動かなくなる
その他(マーシャリング以外)のコスト
- ライブラリ読み込み
- 同じライブラリでも、別ドメインの場合、別イメージが作られるので、メモリが倍必要
他の言語
- プロセス分離してプロセス間通信するものもある
- 例:Apache(1リクエストにつき1プロセス)
スレッド
- スレッドは高コスト
- 1スレッドごとに1スタック確保される
- 処理に時間がかかるのは、I/O-boundのケースが多い
- 解決策:I/O完了ポート
- .NETでは、*Asyncメソッド
- 解決策:I/O完了ポート
UIスレッドへのメッセージ配送(Dispatch)
- JavaScriptはDispatchを勝手にやっている
メタデータ
動的リンク(ダイナミックリンク)
- アプリ起動時に全ライブラリロードする
LINQ
- LINQのメソッドチェーンを途中で切るかどうかは、戻り値の変数に適切な名前を付けられるかどうかで判断するとよい
dynamic
- パフォーマンスはよくない