C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[8]: 関数呼び出しの際のオーバーヘッドに関して


(過去ログ 17 を表示中)

[トピック内 11 記事 (1 - 11 表示)]  << 0 >>

■6417 / inTopicNo.1)  関数呼び出しの際のオーバーヘッドに関して
  
□投稿者/ yagiey (9回)-(2007/08/10(Fri) 13:33:19)

分類:[C#] 

C#における、関数呼び出しの際のオーバーヘッドに関して質問させていただきます。

例として、System.Windows.Formsを継承したMyFormクラスについて考えます。
MyFormのLoadのタイミングで何かやろうとする場合、一般には以下の方法があるかと思います。
(リフレクションは考えないこととします)
1. OnLoadメソッドのオーバーライド
2. Loadイベントハンドラを定義して、Loadイベントにアタッチ

1と2のうちどちらが実行時のコストが小さくて済むのでしょうか?
私の感覚としては、

1の場合:
動的ポリモーフィズムを前提にしている(仮想関数を用いている)という時点でそれなりにコストがかかる。
(仮想関数テーブルに相当するものがあるのか知らんけど...。)

2の場合:
Loadイベントに登録するハンドラをMyForm_Loadとします。
MyForm_LoadはFormのOnLoadで呼ばれることになりますよね(推測)。
となると、1の場合のコストに加えて、「デリゲートによるイベントハンドラの実行」というコストがかかってしまう。

ということで、「1の方がコストが小さくて済む」というのが私の結論です。
皆さんの意見をお聞かせ頂ければ、うれしく思います。

引用返信 編集キー/
■6430 / inTopicNo.2)  Re[1]: 関数呼び出しの際のオーバーヘッドに関して
□投稿者/ パピ (1回)-(2007/08/10(Fri) 17:29:26)
No6417 (yagiey さん) に返信
> C#における、関数呼び出しの際のオーバーヘッドに関して質問させていただきます。
>
> 例として、System.Windows.Formsを継承したMyFormクラスについて考えます。
> MyFormのLoadのタイミングで何かやろうとする場合、一般には以下の方法があるかと思います。
> (リフレクションは考えないこととします)
> 1. OnLoadメソッドのオーバーライド
> 2. Loadイベントハンドラを定義して、Loadイベントにアタッチ
>
> 1と2のうちどちらが実行時のコストが小さくて済むのでしょうか?
> 私の感覚としては、
>
> 1の場合:
> 動的ポリモーフィズムを前提にしている(仮想関数を用いている)という時点でそれなりにコストがかかる。
> (仮想関数テーブルに相当するものがあるのか知らんけど...。)
>
> 2の場合:
> Loadイベントに登録するハンドラをMyForm_Loadとします。
> MyForm_LoadはFormのOnLoadで呼ばれることになりますよね(推測)。
> となると、1の場合のコストに加えて、「デリゲートによるイベントハンドラの実行」というコストがかかってしまう。
>
> ということで、「1の方がコストが小さくて済む」というのが私の結論です。
> 皆さんの意見をお聞かせ頂ければ、うれしく思います。
>

 すいません。 分かりません。
引用返信 編集キー/
■6434 / inTopicNo.3)  Re[1]: 関数呼び出しの際のオーバーヘッドに関して
□投稿者/ Jitta (396回)-(2007/08/10(Fri) 18:19:30)
No6417 (yagiey さん) に返信
> C#における、関数呼び出しの際のオーバーヘッドに関して質問させていただきます。
>
> 例として、System.Windows.Formsを継承したMyFormクラスについて考えます。
> MyFormのLoadのタイミングで何かやろうとする場合、一般には以下の方法があるかと思います。
> (リフレクションは考えないこととします)
> 1. OnLoadメソッドのオーバーライド
> 2. Loadイベントハンドラを定義して、Loadイベントにアタッチ
>
> 1と2のうちどちらが実行時のコストが小さくて済むのでしょうか?

この場合、コストではなく、メソッドの目的で選んでください。On*は、イベントを発生させるメソッドです。どこかに「ロードする」処理があり、そいつが他の処理を実行する前にOnLoadを呼び出しています。ロードのタイミングで行いたいなら、イベントハンドラの中で行います。何らかの条件でハンドラを呼び出すかどうかをきめる、イベント引数を変更したいなら、OnLoadで行います。
引用返信 編集キー/
■6438 / inTopicNo.4)  Re[2]: 関数呼び出しの際のオーバーヘッドに関して
□投稿者/ なちゃ (50回)-(2007/08/10(Fri) 18:30:54)
単にコストで言えば、OnLoadの方が少ないでしょう。
delegateの呼び出しは比較的重いですし、特にControlのイベントは単なるdelegateの呼び出しではなく、
ディクショナリからの検索という操作が入ります。

まあしかし、WindowsFormでこの程度のコストは、通常は気にするようなものではないでしょう。
意味で使い分けることの方が重要です。

引用返信 編集キー/
■6439 / inTopicNo.5)  Re[3]: 関数呼び出しの際のオーバーヘッドに関して
□投稿者/ なちゃ (51回)-(2007/08/10(Fri) 18:33:24)
No6438 (なちゃ さん) に返信
> 単にコストで言えば、OnLoadの方が少ないでしょう。
> delegateの呼び出しは比較的重いですし、特にControlのイベントは単なるdelegateの呼び出しではなく、
> ディクショナリからの検索という操作が入ります。

ああそうそう、この操作は別にLoadイベントハンドラが登録されてなくても起こる
(登録されているかどうか検索する)わけですから、OnLoadだけでも一緒といえば一緒ですね。


引用返信 編集キー/
■6441 / inTopicNo.6)  Re[4]: 関数呼び出しの際のオーバーヘッドに関して
□投稿者/ yagiey (13回)-(2007/08/10(Fri) 23:09:38)
フォームの追加でMyFormクラスを追加して、デザイナの画面でフォームをダブルクリックするとMyForm_Loadが出来ちゃうじゃないですか。
それでこんなこと考えてたんですけど、
> この場合、コストではなく、メソッドの目的で選んでください。
ですよねー。いや、すんません。
大前提ですよねー。なんも考えてませんでした。


> delegateの呼び出しは比較的重いですし、特にControlのイベントは単なるdelegateの呼び出しではなく、ディクショナリからの検索という操作が入ります。
> ああそうそう、この操作は別にLoadイベントハンドラが登録されてなくても起こる(登録されているかどうか検索する)わけですから、OnLoadだけでも一緒といえば一緒ですね。
FormクラスのOnLoad関数がどう実装されているかは知りませんが、もし
class Form : ほげほげ
{
 public event EventHandler Load;
 protected virtual void OnLoad(EventArgs e)
 {
  if (Load != null) Load(this, e);
 }

 // その他実装の詳細...
}
ってな感じになってるとしたら、Loadイベントにハンドラが登録されているかどうかは上記のようなif文だけで済むんじゃないかなと思います。
あくまで推測ですが。
んでさらに私の思い込み(ヲイ!)では、Loadがnullじゃなかったら、登録されているハンドラを片っ端から実行して回るイメージです。
あ、そうだとしたら、!=演算子がどう実装されているか問題ですね。!=演算のコストが大きければ元も子も無いですね。
そんなこんなで、ディクショナリにする意味もよく理解できていません。
気が向いたらで構いません、その辺のことに関してもう少しお話を伺いたいです。


書き込みありがとうございました。
引き続き、書き込みは大歓迎です。

解決済み
引用返信 編集キー/
■6442 / inTopicNo.7)  Re[5]: 関数呼び出しの際のオーバーヘッドに関して
□投稿者/ なちゃ (52回)-(2007/08/10(Fri) 23:59:22)
余談ですが…

>ってな感じになってるとしたら、Loadイベントにハンドラが登録されているかどうかは上記のようなif文だけで済むんじゃないかなと思います。

>特にControlのイベントは
ここが重要だったわけですが。
「Component.Events プロパティ」あたりからいろいろたどるとわかるかも。

引用返信 編集キー/
■6445 / inTopicNo.8)  Re[6]: 関数呼び出しの際のオーバーヘッドに関して
□投稿者/ yagiey (14回)-(2007/08/11(Sat) 02:09:36)
> ここが重要だったわけですが。
> 「Component.Events プロパティ」あたりからいろいろたどるとわかるかも。
Component.Eventsの存在を知ることが出来ただけでかなりの収穫です。ありがとうございます。

んで、早速ググってみました。
http://www.microsoft.com/japan/msdn/community/gdn/ShowPost-29152.htm
になちゃさんがコメントしてるじゃあーりませんかぁ。

えーと、イベントはLoadやPaintやSelectedIndexChangedやetc...、それこそ枚挙に暇がありません。
ハンドラの引数の**EventArgsのまちまちです。
さらに、それぞれのイベントに複数のイベントハンドラをつっ込めますよね。
それなのにComponent.Eventsプロパティが単なるEventHandlerのリストっぽいEventHandlerListクラスのなのが腑に落ちません。

RTTIすらまともに使ったことが無く静的に凝り固まったC++厨の私としましては、リフレクションなる言語のダークサイドな部分にはあまり触りたくないので深追いしたくない反面、気になって仕方がありません。
これをきっかけに恐る恐る勉強させていただきます。

# テンプレート駆使してメタプログラミングやってるC++のコードを保守する気にはなりませんが、リフレクション使いまくりなコードの保守はそれに通じるものがあるのかなと思いました。
# ってか、当初の関数呼び出しのコストの話題はどこへやら...。

ありがとうございました!!
引用返信 編集キー/
■6446 / inTopicNo.9)  Re[7]: 関数呼び出しの際のオーバーヘッドに関して
□投稿者/ yagiey (15回)-(2007/08/11(Sat) 11:50:29)
> リフレクションなる言語のダークサイドな部分にはあまり触りたくないので深追いしたくない反面、気になって仕方がありません。

http://msdn2.microsoft.com/ja-jp/library/yt1k2w4e(VS.80).aspx
http://msdn2.microsoft.com/ja-jp/library/8843a9ch(VS.80).aspx
http://hongliang.seesaa.net/article/7090383.html
とか見てみましたが、このEventsプロパティとリフレクションとはあんまり関係ないですね。

http://www.microsoft.com/japan/msdn/community/gdn/ShowPost-29152.htm
に対する一つの提案だった、ってだけみたいですね。


しかし、コントロール類とかイベントが盛りだくさんなクラスではイベント周りが単純に
public event EventHandler SomeEvent;
protected virtual void OnSomeEvent(EventArgs e)
{
 if (SomeEvent != null) SomeEvent(this, e);
}
じゃないってことが分かり、勉強になりました。
解決済み
引用返信 編集キー/
■6449 / inTopicNo.10)  Re[7]: 関数呼び出しの際のオーバーヘッドに関して
□投稿者/ 渋木宏明(ひどり) (296回)-(2007/08/12(Sun) 01:15:35)
渋木宏明(ひどり) さんの Web サイト
> ハンドラの引数の**EventArgsのまちまちです。
> さらに、それぞれのイベントに複数のイベントハンドラをつっ込めますよね。
> それなのにComponent.Eventsプロパティが単なるEventHandlerのリストっぽいEventHandlerListクラスのなのが腑に落ちません。

各イベントのイベント引数である EventArgs の型がまちまちであっても、すべて EventArgs 型派生であるため、EventArgs 型を引数に取る単純なイベントハンドラと型互換性が保たれているからです。

># ってか、当初の関数呼び出しのコストの話題はどこへやら...。

単なる技術的興味だったのかもしれませんが、毎度々々プログラミングに取り組む前から呼び出しコストの問題を気にするくらいなら、.NET なんかでプログラミングすることはあきらめた方がいいです。

実行コストが最も重要である分野のプログラミングには .NET は向きません。それこそ今からでもアセンブラや pure C に取り組むべきでしょう。

そういう特殊な分野が対象ではなく、より一般的な問題を扱う場合、細々した部分のコストを気にするよりも基本的なロジックを見直す方が劇的に実行性能が改善される場合が多いはずです。
引用返信 編集キー/
■6454 / inTopicNo.11)  Re[8]: 関数呼び出しの際のオーバーヘッドに関して
□投稿者/ れい (36回)-(2007/08/12(Sun) 16:11:57)
No6449 (渋木宏明(ひどり) さん) に返信
>>ハンドラの引数の**EventArgsのまちまちです。
>>さらに、それぞれのイベントに複数のイベントハンドラをつっ込めますよね。
>>それなのにComponent.Eventsプロパティが単なるEventHandlerのリストっぽいEventHandlerListクラスのなのが腑に落ちません。
>
> 各イベントのイベント引数である EventArgs の型がまちまちであっても、すべて EventArgs 型派生であるため、EventArgs 型を引数に取る単純なイベントハンドラと型互換性が保たれているからです。

それぞれのイベントに複数のハンドラを入れられるのは、
Delegateは複数のメソッドを呼ぶ、Multicast Delegateとすることもできるからですね。

余談ですが。
EventHandlerListってEventHandler型でなく、Delegate型のリストなんですよね。
型チェックはないので、どんなDelegateでも入れられます。
EventHandler型へ変換できなくてはならないという制約が課せられる場所は
個々のOnXXXメソッドにあります。

もうひとつ。
Multicast Delegateは登録されているメソッドを順番に呼ぶんですが、
一つでも例外を投げると残りは呼ばれません。
どこまで呼んだのか判らないのはなんとかならないのかなぁ。
呼び出される側のメソッドでも、何で呼び出されないのかわからないし。
OnXXXで変なエラー処理をしてはまりました。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -