Upload
cct-inc
View
1.410
Download
1
Embed Size (px)
Citation preview
Microsoftを16倍出し抜くC#+WPF開発手法第2回(1~4倍までの道)
山本礼貴
誰のためか
対象者 C#と.NET Frameworkに対する大まかな知識を持つ人
WPFに対する大まかな知識を持つ人
第1回目のスライドをご覧いただいた人には、より効果的な
動機 WPFのプログラムの動作が遅いという懸念や不満
頂上までの道
WPFの根本的問題を解決する
(16倍~)
WPFを制御する(4~16倍)
WPFを効率的に使う(1~4倍)
誤った使い方をしないこと(~1倍)
アジェンダ
16倍っていかほど?
仮想化パネル自作という道
ちょっとしたデモ
まとめと次回予告
16倍っていかほど?大変に思えますが、実のところはそうでもない。
大体の16倍の根拠について。
大前提画面に収まらない規模のデータを扱うときの話です。
画面に収まる程度ものが遅いというのは何か別の問題と考えましょう。(例えば、第1回目で問題にしたようなこと)
一般論で考える
量的な面から物を減らしていくというアプローチは正しい。データをグルーピングしたり絞り込んだりする。
遅延評価する。
表示を省略する。表示しないでいいUIを選択する。(折りたたんだツリーとか)
ただし、これらは多くの場合一覧性に対するアンチかも。
データ形式に特化されたアプローチの良し悪し再利用性が低いので、毎回毎回やる羽目になります。
とはいえ、速くなることは間違いない。
システマチックなアプローチは大切です。再利用ができるから。
簡素なコードが速く動くから。
他のアプローチと相乗効果が働くから。
高速化を座標軸で考える
システマチックに考えてみましょう。
我々が認識できる軸は4つしかない画面の平面(X軸、Y軸)
コントロールの前後関係(Z軸)
描画に要する時間(時間軸)
だったら、1軸あたり2倍の速度にできたら、2の4乗・・・
すなわち16倍。いけそうな気がする。
そのうち4倍を勝ち取る、画面の平面への最適化。
それは仮想化パネルそのものじゃないか!
本日のお題
水平方向の高速化(1~4倍)
仮想化パネルって何するの?仮想化パネルとは、画面外にあるものに対して、速度に影響しそうな処理を省略するパネルの事です。
例)画面内に入る前のコントロールを生成しない
例)画面外にあるコントロールをパネルから取り外す
例)使用の終わったコントロールをリサイクルする
MicrosoftはVirtualizingStackPanelしか用意してくれていません。この圧倒的な不足感は、自作するか、何かを買うしかなさそうです。
とりあえず、自作する路線にしましょう。
買ったものが遅かったとき理由がわかりません。
自分でメンテしているものなら大丈夫。
仮想化パネル自作という道ひとまず簡単に作れる範囲から
知っておくべきこと
ビジュアルツリーのことは多少知っておくと良い。
標準の仕様からどこまで離れることを許容しますか?
最小限、このくらいは変化します。 IsVisibleとか、VisualPanrentChangedのようなイベントが発生するタイミングは変わります。
Loaded、Unloadedも変わります。
Childrenは「今表示されている子」のリストであり、所属している全ての子を表すようにならなくなります。
レイアウトパスの前に、画面外の要素を外したりする必要があります。
つまり、特定のイベント依存で処理をしてはいけません。
事前に読んでおくべきリファレンスコードはどこかひとまず、Panel.csとFrameworkElement.csかな。
高速化のためにすること
仮想化はパネルの責務です。でも、コントロールが協力的なら仮想化は高速です。(専用のインターフェースくらいならあってもいいかなと思える理由)
まるで、すべてのコントロールが今までと同じように動かなければいけないという考え方は捨てます。(遅いものにいつまでもとらわれては速くなりません。)
レイアウトパスを上手に活用して、適切なタイミングで画面外のコントロールを低コスト化してやることです。
ビジュアルツリーの居場所はこのあたり
ビジュアルツリーを知る
イベントユーザーコー
ド
バインディングパス
レイアウトパス
描画パス
例)ボタンのビジュアルツリー
Button
ClassicBorderDecorator(ボタンのスタイル)
ContentPresenter(ボタンの中身)
StackPanel
Image TextBlock
<Button><StackPanel><Image Source=“~.bmp” /><TextBlock>ボタン
<TextBlock/></StackPanel>
</Button>
XAMLとイコールではありませんが、構造は近しいものがあります。
パネル側に実装するもの
子を追加、削除するメソッド Childrenとは別途管理します。
画面の表示範囲Viewportに応じてコントロールの着脱処理を行います。
ちょっとしたデモ速度差の体感用です。が、あまり速くなった気がしなかったらごめんなさい。それは、次回以降のネタなのです。
違い
初期表示は数十倍は高速
マウスのあたり判定も数倍高速
スクロールはちょっと遅い?(←理由は後ほど)
そんなことはいいから、ちょっとソースを見ましょうか。
たったこれだけで仮想化(パネル)
Children候補を蓄積しといてViewportに入ったら着脱
たったこれだけで(以下略)
スッカスカです
違反があります
30分で書いたので、粗はごめんなさい。
実は1つ重大な違反してます。
ScrollChangedはレイアウトパス発のイベントです。そこで、子の着脱をするということは、ユーザーコードのパス、バインディングパスをやり直す可能性が生じます。(第1回目であれほどダメだと言っていたのに)
スクロールがさほど速くなっていなかったのはこれが理由です。
仮想化しても思ったほど速くならんなーという人が悩むポイントでもあります。(重要)
まとめと次回予告
まとめ仮想化パネルは水平方向の速度を向上します。
ただし、標準とは異なる挙動をするようになるため、いくつかの禁止事項が生じます。
速さが最も際立つのは、生成時とヒットテスト
コントロールの着脱分、スクロールはちょっと遅くなります。
次回以降予告コントロールのリサイクリングによって、省メモリと高速化を同時に実現します。
Panelを継承するから発生する最大の問題について。
Zindex問題の解消方法。随一のトリッキーなパネル。
ご清聴ありがとうございました。http://proprogrammer.hatenadiary.jp/
こちらもご覧ください。