22
Microsoft 16 倍出し抜く C# WPF 開発手法 2回(1~4倍までの道) 山本礼貴

Msを16倍出し抜くwpf開発2回目

  • Upload
    cct-inc

  • View
    1.410

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Msを16倍出し抜くwpf開発2回目

Microsoftを16倍出し抜くC#+WPF開発手法第2回(1~4倍までの道)

山本礼貴

Page 2: Msを16倍出し抜くwpf開発2回目

誰のためか

対象者 C#と.NET Frameworkに対する大まかな知識を持つ人

WPFに対する大まかな知識を持つ人

第1回目のスライドをご覧いただいた人には、より効果的な

動機 WPFのプログラムの動作が遅いという懸念や不満

Page 3: Msを16倍出し抜くwpf開発2回目

頂上までの道

WPFの根本的問題を解決する

(16倍~)

WPFを制御する(4~16倍)

WPFを効率的に使う(1~4倍)

誤った使い方をしないこと(~1倍)

Page 4: Msを16倍出し抜くwpf開発2回目

アジェンダ

16倍っていかほど?

仮想化パネル自作という道

ちょっとしたデモ

まとめと次回予告

Page 5: Msを16倍出し抜くwpf開発2回目

16倍っていかほど?大変に思えますが、実のところはそうでもない。

大体の16倍の根拠について。

Page 6: Msを16倍出し抜くwpf開発2回目

大前提画面に収まらない規模のデータを扱うときの話です。

画面に収まる程度ものが遅いというのは何か別の問題と考えましょう。(例えば、第1回目で問題にしたようなこと)

Page 7: Msを16倍出し抜くwpf開発2回目

一般論で考える

量的な面から物を減らしていくというアプローチは正しい。データをグルーピングしたり絞り込んだりする。

遅延評価する。

表示を省略する。表示しないでいいUIを選択する。(折りたたんだツリーとか)

ただし、これらは多くの場合一覧性に対するアンチかも。

データ形式に特化されたアプローチの良し悪し再利用性が低いので、毎回毎回やる羽目になります。

とはいえ、速くなることは間違いない。

システマチックなアプローチは大切です。再利用ができるから。

簡素なコードが速く動くから。

他のアプローチと相乗効果が働くから。

Page 8: Msを16倍出し抜くwpf開発2回目

高速化を座標軸で考える

システマチックに考えてみましょう。

我々が認識できる軸は4つしかない画面の平面(X軸、Y軸)

コントロールの前後関係(Z軸)

描画に要する時間(時間軸)

だったら、1軸あたり2倍の速度にできたら、2の4乗・・・

すなわち16倍。いけそうな気がする。

そのうち4倍を勝ち取る、画面の平面への最適化。

それは仮想化パネルそのものじゃないか!

Page 9: Msを16倍出し抜くwpf開発2回目

本日のお題

水平方向の高速化(1~4倍)

仮想化パネルって何するの?仮想化パネルとは、画面外にあるものに対して、速度に影響しそうな処理を省略するパネルの事です。

例)画面内に入る前のコントロールを生成しない

例)画面外にあるコントロールをパネルから取り外す

例)使用の終わったコントロールをリサイクルする

MicrosoftはVirtualizingStackPanelしか用意してくれていません。この圧倒的な不足感は、自作するか、何かを買うしかなさそうです。

とりあえず、自作する路線にしましょう。

買ったものが遅かったとき理由がわかりません。

自分でメンテしているものなら大丈夫。

Page 10: Msを16倍出し抜くwpf開発2回目

仮想化パネル自作という道ひとまず簡単に作れる範囲から

Page 11: Msを16倍出し抜くwpf開発2回目

知っておくべきこと

ビジュアルツリーのことは多少知っておくと良い。

標準の仕様からどこまで離れることを許容しますか?

最小限、このくらいは変化します。 IsVisibleとか、VisualPanrentChangedのようなイベントが発生するタイミングは変わります。

Loaded、Unloadedも変わります。

Childrenは「今表示されている子」のリストであり、所属している全ての子を表すようにならなくなります。

レイアウトパスの前に、画面外の要素を外したりする必要があります。

つまり、特定のイベント依存で処理をしてはいけません。

事前に読んでおくべきリファレンスコードはどこかひとまず、Panel.csとFrameworkElement.csかな。

Page 12: Msを16倍出し抜くwpf開発2回目

高速化のためにすること

仮想化はパネルの責務です。でも、コントロールが協力的なら仮想化は高速です。(専用のインターフェースくらいならあってもいいかなと思える理由)

まるで、すべてのコントロールが今までと同じように動かなければいけないという考え方は捨てます。(遅いものにいつまでもとらわれては速くなりません。)

レイアウトパスを上手に活用して、適切なタイミングで画面外のコントロールを低コスト化してやることです。

Page 13: Msを16倍出し抜くwpf開発2回目

ビジュアルツリーの居場所はこのあたり

ビジュアルツリーを知る

イベントユーザーコー

バインディングパス

レイアウトパス

描画パス

Page 14: Msを16倍出し抜くwpf開発2回目

例)ボタンのビジュアルツリー

Button

ClassicBorderDecorator(ボタンのスタイル)

ContentPresenter(ボタンの中身)

StackPanel

Image TextBlock

<Button><StackPanel><Image Source=“~.bmp” /><TextBlock>ボタン

<TextBlock/></StackPanel>

</Button>

XAMLとイコールではありませんが、構造は近しいものがあります。

Page 15: Msを16倍出し抜くwpf開発2回目

パネル側に実装するもの

子を追加、削除するメソッド Childrenとは別途管理します。

画面の表示範囲Viewportに応じてコントロールの着脱処理を行います。

Page 16: Msを16倍出し抜くwpf開発2回目

ちょっとしたデモ速度差の体感用です。が、あまり速くなった気がしなかったらごめんなさい。それは、次回以降のネタなのです。

Page 17: Msを16倍出し抜くwpf開発2回目

違い

初期表示は数十倍は高速

マウスのあたり判定も数倍高速

スクロールはちょっと遅い?(←理由は後ほど)

そんなことはいいから、ちょっとソースを見ましょうか。

Page 18: Msを16倍出し抜くwpf開発2回目

たったこれだけで仮想化(パネル)

Children候補を蓄積しといてViewportに入ったら着脱

Page 19: Msを16倍出し抜くwpf開発2回目

たったこれだけで(以下略)

スッカスカです

Page 20: Msを16倍出し抜くwpf開発2回目

違反があります

30分で書いたので、粗はごめんなさい。

実は1つ重大な違反してます。

ScrollChangedはレイアウトパス発のイベントです。そこで、子の着脱をするということは、ユーザーコードのパス、バインディングパスをやり直す可能性が生じます。(第1回目であれほどダメだと言っていたのに)

スクロールがさほど速くなっていなかったのはこれが理由です。

仮想化しても思ったほど速くならんなーという人が悩むポイントでもあります。(重要)

Page 21: Msを16倍出し抜くwpf開発2回目

まとめと次回予告

まとめ仮想化パネルは水平方向の速度を向上します。

ただし、標準とは異なる挙動をするようになるため、いくつかの禁止事項が生じます。

速さが最も際立つのは、生成時とヒットテスト

コントロールの着脱分、スクロールはちょっと遅くなります。

次回以降予告コントロールのリサイクリングによって、省メモリと高速化を同時に実現します。

Panelを継承するから発生する最大の問題について。

Zindex問題の解消方法。随一のトリッキーなパネル。

Page 22: Msを16倍出し抜くwpf開発2回目

ご清聴ありがとうございました。http://proprogrammer.hatenadiary.jp/

こちらもご覧ください。