- PR -

イベントが頻発するようなWindowsアプリケーションの挙動について

投稿者投稿内容
JK
会議室デビュー日: 2005/08/11
投稿数: 10
投稿日時: 2005-08-22 10:14
レスが遅くなりまして申し訳ありません。

渋木宏明(ひどり)さん:

引用:

「既存のアプリ」が「コントロールをカスタマイズ」しているならなおのこと、
.NET アプリケーションでも「高負荷をキューでしのぎ、落ち着いたら再描画する」
という手法で乗り切るのもありなんじゃないですか?


為替や株価のような「リアルタイムでデータ更新を反映」させるのが重要なシステムを
ご想像頂ければと思います。データ更新の待ち時間は極力少なくしたいと考えています。

引用:

表示データの量が 1000 行・数カラム程度なら、リストビューを使った方がかなり速いと思います。
ただし、リストビューアイテムの再充填(=Items.Clear() してから Items.Add() の繰り返し)はやっちゃ駄目です。
リストビューに表示されている各項目のプロパティを再設定して回るのが最速です。


この方法も試させて頂こうと思います。

なちゃさん:

引用:

ちいとだけ気になるんですが、このライブラリのイベントって非同期で発生しますよね?
イベント自体はUIスレッドにちゃんとマーシャリングされるようになっているんでしょうか?
あるいはWindowsのメッセージでイベントが発生するような形とかになっているとか?


仰っているのはマルチスレッド化したケースのことですよね? 現状では何の変哲も無い
イベント処理ですのでBeginInvoke()、EndInvoke()などはコールしておりません。

この辺に関して知見が無いので間違っていたらご指摘下さい。

引用:

ところで、更新情報というのは、最大の想定(というかおかしくなってくるとき)で、
大体秒間何回くらいなんでしょう?


現状ではこうした統計情報は取っていない状況です。サーバーは現在も本番用が
稼動しており、そこから更新データを受け取っているので、とりあえずこの状況下で
.NETクライアントが満足な動作をするか確認している、といった感じです。

引用:

Paintイベント処理中に何かしてませんか?または、Paintイベントを明示的に
発生させるとかしてませんか。(後者は別に問題ないのかな…)


Paintイベントに関しては現状では手を付けておりませんが、将来的にはデータが
更新されたときに一瞬背景色を変更する、といった加工をするかもしれません。

引用:

後、ぼのぼのさんがおっしゃった事がヒントに「画面全体を再描画すると重い」。
「画面全体を再描画中に画面に表示すべきデータを全計算」すると重いですね。
「もともと既に計算されて用意されているデータで画面全体を再描画」は軽い。
「更新が必要な一部のデータだけ計算して、画面全体を再描画」も軽い。


データセットの更新対象のローやカラムにデータを追加しているだけなので、
「更新が必要な一部のデータだけ計算して、画面全体を再描画」に当たるかと
思います。

ほげたさん:

引用:

データサイズや更新頻度がわからないのでなんとも言えませんが
以下のような基本的なしきたりはやってますか?
・渋木宏明(ひどり)さんのおっしゃるように、データ入れ替えでなく詰め替えにする。
・無駄な描画更新がされないようにBeginUpdate()する。
・内部でイベントが発生しないようにBeginLoadData()する。
XSDを使っているのであれば、キー名指定のアクセスはしていないと思いますが
これもパフォーマンスを低下させる原因となります。

あと、なちゃさんの指摘にあるマーシャリングも匂いますね。
ハンドラで InvokeRequired が true になってないか見てみてください。


恥ずかしながらBeginLoadData()やInvokeRequiredというキーワードは未知でした。
これから確認します。

Jittaさん:

引用:

データ更新の間隔(ミリ秒単位で)
1度に送られるデータのバイト数
転送に使われる回線の性能
要求性能(1秒間に何回再描画できなければならないか)

パッと思いつくのでこんなもん?
こういうのが上がってきて初めて、検証が開始できるんじゃないですか?


現状ではこのレベルの検証までに至っておりません。というか顧客側から
こうした検証はまだ求められていない状況です。前述のように本番データ
の負荷に耐えうるか?という観点で作業を進めているところです。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2005-08-22 11:04
引用:

為替や株価のような「リアルタイムでデータ更新を反映」させるのが重要なシステムを
ご想像頂ければと思います。データ更新の待ち時間は極力少なくしたいと考えています。



既に指摘されていることですが、そこら辺の判断には各種の数値が必要です。

雰囲気的には、自前で描画してしまった方がよさそうに思います。
あるいは、大した行数でなければリストビューを使うのでもいいかもしれません。

引用:

イベント処理ですのでBeginInvoke()、EndInvoke()などはコールしておりません。

この辺に関して知見が無いので間違っていたらご指摘下さい。



「イベント処理だから InvokeXXX が不要」な保証はどこにもありません。

引用:

現状ではこのレベルの検証までに至っておりません。というか顧客側から
こうした検証はまだ求められていない状況です。前述のように本番データ
の負荷に耐えうるか?という観点で作業を進めているところです。



それじゃ意味ないですよ。
実装によって方法でいくらでもパフォーマンスなんか変わります。

だからこそ、数値が必要なんです。
ボトルネックがどこにあるかもつかまずに想像だけで作業したって、意味ある前進は得られないです。

_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/
jk
ベテラン
会議室デビュー日: 2005/08/19
投稿数: 94
投稿日時: 2005-08-22 11:16
引用:

為替や株価のような「リアルタイムでデータ更新を反映」させるのが重要なシステムを
ご想像頂ければと思います。データ更新の待ち時間は極力少なくしたいと考えています。



という前提のようですが、そもそも1000行のデータを画面に表示できるの?
なんて、疑問があるのですが...
それは置いておいたとして、重要なシステムであればデータの取りこぼしが一番致命的に
思います。
以下の手順ではいかがでしょうか?

1)イベントの処理はキューイングして画面描画は別スレッドで行う。
2)ある程度キュー内のデータが増えてきたときは画面再描画をとめて処理する。
3)2)の処理がある一定時間(1秒とか)以上かかる場合でも定期的に再描画する。

キューに充分な大きさが割り当てられていれば、再描画をとめるまでも無いと
思いますが、キューやWindowsのメッセージキューあふれによってデータ処理が
滞ってしまうよりは、はるかにましだと思います。

人間の認知速度には限界があると思いますので画面更新頻度は1回/秒程度あれば、
充分リアルタイムとみなされると思います。
動体視力のテストゲームでもやられるつもりなのでしょうか?
また、垂直同期以上の速さで画面更新はされませんよ^^;
JK
会議室デビュー日: 2005/08/11
投稿数: 10
投稿日時: 2005-08-22 11:31
引用:

既に指摘されていることですが、そこら辺の判断には各種の数値が必要です。

雰囲気的には、自前で描画してしまった方がよさそうに思います。
あるいは、大した行数でなければリストビューを使うのでもいいかもしれません。

(snip)

それじゃ意味ないですよ。
実装によって方法でいくらでもパフォーマンスなんか変わります。

だからこそ、数値が必要なんです。
ボトルネックがどこにあるかもつかまずに想像だけで作業したって、意味ある前進は得られないです。


これは数値の如何によって推奨される既知の実装やコントロールがある
(もしくは自作する?)という意味でしょうか?

Web上にその辺りに関する資料があるようでしたらご教授下さい。

引用:

引用:

イベント処理ですのでBeginInvoke()、EndInvoke()などはコールしておりません。

この辺に関して知見が無いので間違っていたらご指摘下さい。



「イベント処理だから InvokeXXX が不要」な保証はどこにもありません。



先の投稿で「現状では何の変哲も無いイベント処理」と書きましたが、これは
「マルチスレッド化していないイベント処理」ということでした。この場合でも
InvokeXXXが必要となるケースがある、ということでしょうか?
Lichtenstein
ベテラン
会議室デビュー日: 2003/11/06
投稿数: 61
投稿日時: 2005-08-22 12:10
>たとえば、最後に描画した時刻を記憶しておいて、5秒以上経過しないうちは
>再描画しないとか。

上、自分の発言の引用ですが、兎に角こういう事をやってみてはどうですか。

DataGridが無ければ問題は発生しないんですよね? なら早いところ限界を計測して
おかないと、求める性能が不定のままです。

実際のところ、1秒に10回受信したとき0.1秒で描画、とか普通無理なのでその辺は
諦めてはどうですか。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2005-08-22 13:00
引用:

これは数値の如何によって推奨される既知の実装やコントロールがある
(もしくは自作する?)という意味でしょうか?



そういうことです。
求められている性能に対して、それを実現するための相応の設計があるはずです。

引用:

Web上にその辺りに関する資料があるようでしたらご教授下さい。



知りません。
工学的な見地から当たり前のことだと思います。

1の量を扱うものと、10000からの量を扱うものが、まったく同じでいいはずはありません。
(思想的な共通性ではなく、物理的な構成に関してです)

引用:

先の投稿で「現状では何の変哲も無いイベント処理」と書きましたが、これは
「マルチスレッド化していないイベント処理」ということでした。この場合でも
InvokeXXXが必要となるケースがある、ということでしょうか?



「マルチスレッド化していないイベント処理」の意味がよく分かりません。

通信用の DLL が内部でスレッドを使用していない保証があり、かつまたそれを扱うスレッドと UI を駆動するスレッドが同一の場合、InvokeXXX は不要です。
ほげた
ベテラン
会議室デビュー日: 2002/05/08
投稿数: 67
お住まい・勤務地: なごやん
投稿日時: 2005-08-23 02:20
引用:

渋木宏明(ひどり)さんの書き込み (2005-08-22 13:00) より:
引用:

これは数値の如何によって推奨される既知の実装やコントロールがある
(もしくは自作する?)という意味でしょうか?



そういうことです。
求められている性能に対して、それを実現するための相応の設計があるはずです。


その数値をちゃんと計測すれば、アプリケーション全体でパフォーマンスが出ないと嘆かずに
同程度の更新負荷をかけるような簡単な検証プログラムを作成して
DataGrid自体の性能に限界があるのか、使い方がまずいだけなのか
他のコンポーネントでは耐えられるのか、自前で描画すれば追いつくのか
すぐにわかると思います。

今のアプリケーションでパフォーマンスが出ないからといって
自前で苦労して作っても、単にマーシャリングしていないだけだったら意味ないですし
だいたいのオーダーだけでも計測して、目標値を決めたほうがいいですよ。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-08-23 04:59
 気になっているのですが、DataGrid の再描画を、どの様に行おうとしているのでしょう?

 例えば、DataGrid.DataSource に設定するデータを再作成しているのであれば、それってとても時間が無駄ですよね?
 そうではなく、DataSource のスポットデータを更新しても、描画が追いつかないのでしょうか?

 渋木宏明(ひどり)さんが、『リストビューアイテムの再充填はやっちゃ駄目です。』と指摘されていることですが、DataGrid でも同じように言えます。


> 前述のように本番データ
> の負荷に耐えうるか?という観点で作業を進めているところです。
 えっと・・・顧客から具体的な検証を求められていなくても、現状レベルの要求はされることが予想されるのですよね?だから、現在の本番データ負荷に耐えらるか、検証しなければならないわけですよね?
 であるなら、現在の本番データの数値をもらってくる必要があると思うのです。そうでないと、「耐えうるか」の判断が出来ないと思うのですが、いかがでしょう?

_________________

スキルアップ/キャリアアップ(JOB@IT)