@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

StackTraceと最適化について

1
投稿者投稿内容
まめ
会議室デビュー日: 2006/03/02
投稿数: 8
投稿日時: 2008-10-30 22:57
ASP.NET初心者です。

いきなりですが、VisualStudio 2005)にて WEBプロジェクトを作成しています。
StackTrace クラス を使用してメソッドの呼び出し履歴を取得しようとしました。
普通に作成すると、なんなく取得できるのですが、あるロジックの組み方において、
呼び出し履歴に乗るはずのメソッドが1つ抜けることがあることがわかりました。

たとえば、Method1() の中で Method2()を呼び、その中にはMethod3()を呼ぶ
ロジックのみが実装されている状態で、Method3()の中で
StackTrace st = new StackTrace(true);
で取得したStackTraceオブジェクトに、Method2()だけ抜けることがあります。

色々調べてみましたが、ヘルプの
「StackTrace では、最適化処理中に実行されたコード変換が原因で、
予期したほど多くのメソッド呼び出しが報告されない場合があります。」
という記述以外、それらしい原因がわかりませんでした。

WindowsFormアプリの場合、ビルドオプションで最適化の指定ができたと
思いますが、WEBプロジェクトではそのような指定がなさそうです。

また、作成された APP_WEB_xxx.DLLを MSIL逆アセンプラで 
逆アセンブリングしてみても、ちゃんとMethod2()を通っているように見えます。

昔のVC++とかだと最適化でそのようなことはあったかもしれませんが。

長文になってしまいましたが、皆様にお伺いしたいのは以下の3点です。
@このような現象に遭遇したことはありますか?
A回避する方法はわかりますか?
B最適化されたかどうかを調べる手段はありますか?

よろしくお願いします。
よこけん
大ベテラン
会議室デビュー日: 2006/01/31
投稿数: 216
投稿日時: 2008-10-30 23:51
@このような現象に遭遇したことはありますか?
再現させたことならあります。


A回避する方法はわかりますか?
Web プロジェクトは、WindowsForm アプリと同じくビルドオプションでコードの最適化を抑止できるはずです。
見当たらないということは、もしかして Web プロジェクトではなく Web サイトなんじゃないでしょうか?
その場合、コンパイル時に /optimize オプションを付加するよう、Web.config で指定します。
次の記述を configuration の直下に記述すればいけると思います。
コード:
<system.codedom>
    <compilers>
        <compiler
         language="c#;cs;csharp"
         extension=".cs"
         compilerOptions="/optimize"
         type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
         warningLevel="1"/>
    </compilers>
</system.codedom>



あと、特定のメソッドおよびその呼び出し元に対して最適化を抑止する方法は、ちょうどこの前ブログに書きましたので、こちらを参照してください。
JIT 最適化にも負けずに呼び出し元のメソッドを取得する方法


B最適化されたかどうかを調べる手段はありますか?
どういう状況においての調べ方でしょうか。

MSIL 逆アセンブラや Reflector を使用して確認するには、アセンブリに DebuggableAttribute が付加されているかどうか、そして引数 modes に DebuggableAttribute.DebuggingModes.DisableOptimizations が指定されているかどうかを調べます。

プログラムから動的に確認するには、DebuggableAttribute が付加されているかどうか、そして
IsJITOptimizerDisabled プロパティが true であるかどうかを調べます。



> MSIL逆アセンプラで 
> 逆アセンブリングしてみても、ちゃんとMethod2()を通っているように見えます。
メソッドの履歴が欠けていたのは、JIT コンパイル時の最適化が原因ですので、MSIL レベルでは確認できません。

_________________
C#と諸々
よこけん
大ベテラン
会議室デビュー日: 2006/01/31
投稿数: 216
投稿日時: 2008-10-31 00:06
肝心なこと書き忘れてました。

最適化を抑止するということは、当然ですがパフォーマンスに影響する可能性があります。どれほどの影響を及ぼすかは実際に計測しなければわかりません。
そのことを充分考慮した上で、抑止するかどうかを決定してください。
_________________
C#と諸々
まめ
会議室デビュー日: 2006/03/02
投稿数: 8
投稿日時: 2008-10-31 23:29
ご回答ありがとうございました!!
今日は時間がなくて試せませんでしたが、非常に参考になります。

ご指摘通り、「Web サイト」での話でした。
また、後ほどレポートします。
まめ
会議室デビュー日: 2006/03/02
投稿数: 8
投稿日時: 2008-11-04 23:14
紹介していただいたURLを参考にして、「Webサイト」で再現できました。
実行用環境では確実に再現するのに、どうやってもDebug環境では再現できず
困っていました。

「Webサイトの発行」を行って作成されたAPP_WEB_xxx.DLLには、
DebuggableAttributeが付加されていないのですね。
Reflectorを使用してわかりました。
デバッグ環境では、当然のごとくDebuggableAttributeも
DebuggableAttribute.DebuggingModes.DisableOptimizationsも
付加されていました。

ちなみにWeb.Configには"/optimize"オプションは、
指定しておりませんでした。

ありがとうございました。

#パフォーマンスはかなり違いますね、最適化するか否かで。
イメージ的に、Webサイトの発行≒WindowsアプリのReleaseビルドという感触です。
1

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