none
ngen.exeの利用について RRS feed

  • 質問

  • _kimuraと申します。

    ngen.exeについて質問させていただきます。

    現在、会社の業務として.Net Framework 3.5 SP1 を使用したアプリケーションの開発を行っております。
    その際、お客様から起動速度が遅いとの連絡を受け以下の作業を行った結果、ngen.exeを使用して
    事前にネイティブコードとしてコンパイルすることで、起動時間が軽減されました。

    ※起動時間が遅くなる主な原因としては、.Net Framework用の外部の有償ツールを使用(アセンブリを参照)していることが考えられます。

    【検証内容】
    アプリケーション 平均起動時間 7.5秒
    ※.Net FrameworkのCLRの読み込み時間を除外するためにアプリケーションを2回目以降起動した際の
     10回の起動時間の平均で求めています。

    1.アセンブリをGACに登録
      → 0.5秒程度軽減

    2.アセンブリのAutheticode署名の検証の省略
      → 0.2秒程度軽減

    3.ngen.exeを使用して、アプリケーションで共通して使用するアセンブリを事前にコンパイル
      → 4秒程度軽減


    上記結果から、ngen.exeを使用してネイティブコードとして事前にコンパイルする方向で考えていますが、
    次のサイトで以下のような表現を目にいたしました。

    参照URL http://www.microsoft.com/japan/msdn/msdnmag/issues/05/04/NGen/default.aspx

    「マシン語コードが格納されている実際のメモリ ページが、OS によって複数のプロセス間で共有できるということを意味します。」

    ngen.exeをネイティブコードとしてコンパイルした、コードを複数プロセス間で共有できるというように
    解釈したのですが、その際に、アセンブリ内で共用する変数(クラス内の静的な変数)等についても、
    複数プロセス間で共有すると言うことでしょうか。

    基本的な質問で、大変申し訳ありませんがご存知でしたらお教えいただけますでしょうか。

    2010年7月6日 4:22

回答

  • ngen.exeをネイティブコードとしてコンパイルした、コードを複数プロセス間で共有できるというように
    解釈したのですが、その際に、アセンブリ内で共用する変数(クラス内の静的な変数)等についても、
    複数プロセス間で共有すると言うことでしょうか。

    そんなことはありません。
    もし、そんなことが起こったら、ngen.exe でコンパイルしたものが期待通りに動かない欠陥品になりますよね。

    実行コードと変数のあるメモリ・スタックは別の領域(アドレスブロック)にあると考えて頂ければ、納得しやすいかと思います。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク _kimura 2010年7月7日 0:56
    • 回答としてマークされていない _kimura 2010年7月7日 6:54
    • 回答としてマーク _kimura 2010年7月9日 0:32
    2010年7月6日 14:01
    モデレータ
  • 同サイトにはベースアドレスの設定によっては、ネイティブイメージの再配置処理の影響を顕著に受けると
    言う様な内容が書かれていました。実際にこのような再配置処理はどういったタイミングで発生するのでしょうか。

    マネージコードに限らず、DLL が読み込まれたときに発生する可能性があります。

    また、上記内容については「ハードバインドされたネイティブイメージ」の場合に現れるということなのですが、
    コンパイル済みのアセンブリがハードバインドされる否かの判断は可能でしょうか。

    ngen.exe のページの「解説」、「アプリケーションの起動の高速化」や「アセンブリのベース アドレスの重要性」あたりに書いてあることと同じですよね、おそらく。
    http://msdn.microsoft.com/ja-jp/library/6t9t5wcf(VS.80).aspx

    私は英語に明るくないので読み間違えているかもしれませんが、「強く結びついた」(hard-bound)を意味しているのでは?
    「起動時に多くのアセンブリを読み込まないといけないような、”強く結びついている”アプリケーションで、再配置が頻発すると、読み込み処理&再配置処理が起動時にまとめて走り、重くなるでしょ」ということを言いたいのだと解釈しています。

    その解釈の上で、”強く結びついているか”を外部から容易に判断できるかというと、難しいのではないでしょうか。
    そのアセンブリの実装・設計によるため、外部提供の場合、断定は難しいでしょう。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク _kimura 2010年7月9日 0:32
    2010年7月7日 14:41
    モデレータ
  • 1.アセンブリ(DLL)が読み込まれた場合に、その内容をメモリ上に配置する際に、
      現状のメモリの使用状態合わせて、読み込み処理及び再配置処理が行われる。

    すでにそのアドレスに読み込まれている場合などに再配置が行われると思います。

    2.”強く結びついている”アセンブリ(DefaultDependencyAttribute 属性がAlwaysのアセンブリ?)を
      多く参照しているアプリケーションは、起動時に読み込み及び再配置処理が頻発する可能性がある。

    「起動時に読み込みが頻発する」とは言えるかもしれません。
    ただし、同じレベルで「再配置処理が頻発する」とは言えません。
    ベースアドレスが散るように設定されているかもしれませんし、一緒に並べて言えるものではないでしょう。
    (前者はほぼ確実に起こるが、後者は不明瞭であるため。論理的に等価ではないというツッコミだけです)

    ngen.exe(ネイティブイメージ)を使用したアプリケーションに限らず、
    このような現象は起こりうるというということでよろしいでしょうか。

    「このような現象」が何を指しているかわかりません。
    ベースアドレスを同一に設定した DLL を起動時に多数読み込むということがあれば、読み込み&再配置が多発します。
    少なくとも Windows ではそういうものです。

     

    さて、「よろしいでしょうか?」の質問が続いていますが、ご自身で設定を変える・わざと起こさせるなどの検証をしてみませんか?
    私の回答は、少しの資料とこれまでの経験からそういう仕組みになっているのではないかという推測を多分に含みます。
    速度検証をしたわけではない、きちんと裏をとったわけではない私に聞き詰めるより、実際に速度検証をした方が有意義です。

    # 間違っても、会社の上司などに私がある回答をしていたから、それが正しいかのように証明する手段(根拠?)に使わないように。:-P
    # 回答を自分で受け取るだけではなく、それが正しいのか吟味・検証することも重要なのですから。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク _kimura 2010年7月9日 0:32
    2010年7月8日 14:22
    モデレータ

すべての返信

  • ngen.exeをネイティブコードとしてコンパイルした、コードを複数プロセス間で共有できるというように
    解釈したのですが、その際に、アセンブリ内で共用する変数(クラス内の静的な変数)等についても、
    複数プロセス間で共有すると言うことでしょうか。

    そんなことはありません。
    もし、そんなことが起こったら、ngen.exe でコンパイルしたものが期待通りに動かない欠陥品になりますよね。

    実行コードと変数のあるメモリ・スタックは別の領域(アドレスブロック)にあると考えて頂ければ、納得しやすいかと思います。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク _kimura 2010年7月7日 0:56
    • 回答としてマークされていない _kimura 2010年7月7日 6:54
    • 回答としてマーク _kimura 2010年7月9日 0:32
    2010年7月6日 14:01
    モデレータ
  • 回答いただきありがとう御座います。

    実行コードと変数のあるメモリ・スタックは別の領域(アドレスブロック)にあると考えて頂ければ、納得しやすいかと思います。

    確かに、そのように考えれば納得できました。

    大変申し訳ありませんが、ngen.exeについて別の内容で数点質問させていただきます。

    NGenイメージのベースアドレスについて、次のサイトで以下のような内容を目にいたしました。

    参照URL:
    http://www.microsoft.com/japan/msdn/msdnmag/issues/05/04/NGen/default.aspx?loc=&side=true#a

    「NGen イメージの正しいベース アドレスを取得することは、少なくともアンマネージ コード モジュールと同様に重要です。」
    「C#、Visual Basic、C++ の各コンパイラには、生成するアセンブリのベース アドレスを制御するためのオプションがあります。」

    今回、ngen.exeを使用してネイティブコード(ネイティブイメージ)を予め生成してキャッシュに
    登録しようとする対象が外部の有償ツールのアセンブリになります。
    その為、アセンブリのベースアドレスを制御するためのオプションをどのように設定して、
    コンパイルされているかについては不明な状態です。

    同サイトにはベースアドレスの設定によっては、ネイティブイメージの再配置処理の影響を顕著に受けると
    言う様な内容が書かれていました。実際にこのような再配置処理はどういったタイミングで発生するのでしょうか。

    また、上記内容については「ハードバインドされたネイティブイメージ」の場合に現れるということなのですが、
    コンパイル済みのアセンブリがハードバインドされる否かの判断は可能でしょうか。

    基本的な質問で大変申し訳ありませんが、お教えいただけますでしょうか。

    2010年7月7日 1:21
  • 同サイトにはベースアドレスの設定によっては、ネイティブイメージの再配置処理の影響を顕著に受けると
    言う様な内容が書かれていました。実際にこのような再配置処理はどういったタイミングで発生するのでしょうか。

    マネージコードに限らず、DLL が読み込まれたときに発生する可能性があります。

    また、上記内容については「ハードバインドされたネイティブイメージ」の場合に現れるということなのですが、
    コンパイル済みのアセンブリがハードバインドされる否かの判断は可能でしょうか。

    ngen.exe のページの「解説」、「アプリケーションの起動の高速化」や「アセンブリのベース アドレスの重要性」あたりに書いてあることと同じですよね、おそらく。
    http://msdn.microsoft.com/ja-jp/library/6t9t5wcf(VS.80).aspx

    私は英語に明るくないので読み間違えているかもしれませんが、「強く結びついた」(hard-bound)を意味しているのでは?
    「起動時に多くのアセンブリを読み込まないといけないような、”強く結びついている”アプリケーションで、再配置が頻発すると、読み込み処理&再配置処理が起動時にまとめて走り、重くなるでしょ」ということを言いたいのだと解釈しています。

    その解釈の上で、”強く結びついているか”を外部から容易に判断できるかというと、難しいのではないでしょうか。
    そのアセンブリの実装・設計によるため、外部提供の場合、断定は難しいでしょう。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク _kimura 2010年7月9日 0:32
    2010年7月7日 14:41
    モデレータ
  • 回答いただきありがとう御座います。

    マネージコードに限らず、DLL が読み込まれたときに発生する可能性があります。

    申し訳ありません。上記のような内容にあまり詳しくないため、確認として質問させていただきます。

    1.アセンブリ(DLL)が読み込まれた場合に、その内容をメモリ上に配置する際に、
      現状のメモリの使用状態合わせて、読み込み処理及び再配置処理が行われる。

    2.”強く結びついている”アセンブリ(DefaultDependencyAttribute 属性がAlwaysのアセンブリ?)を
      多く参照しているアプリケーションは、起動時に読み込み及び再配置処理が頻発する可能性がある。

    と言うことでしょうか。となると、ngen.exe(ネイティブイメージ)を使用したアプリケーションに限らず、
    このような現象は起こりうるというということでよろしいでしょうか。

    また、上記内容から考えると、ngen.exeを使用した際の致命的なエラーという訳ではなく、
    「起動速度の高速化の恩恵を受けられない場合があります」という認識でよろしいでしょうか。

     

    2010年7月8日 1:12
  • 1.アセンブリ(DLL)が読み込まれた場合に、その内容をメモリ上に配置する際に、
      現状のメモリの使用状態合わせて、読み込み処理及び再配置処理が行われる。

    すでにそのアドレスに読み込まれている場合などに再配置が行われると思います。

    2.”強く結びついている”アセンブリ(DefaultDependencyAttribute 属性がAlwaysのアセンブリ?)を
      多く参照しているアプリケーションは、起動時に読み込み及び再配置処理が頻発する可能性がある。

    「起動時に読み込みが頻発する」とは言えるかもしれません。
    ただし、同じレベルで「再配置処理が頻発する」とは言えません。
    ベースアドレスが散るように設定されているかもしれませんし、一緒に並べて言えるものではないでしょう。
    (前者はほぼ確実に起こるが、後者は不明瞭であるため。論理的に等価ではないというツッコミだけです)

    ngen.exe(ネイティブイメージ)を使用したアプリケーションに限らず、
    このような現象は起こりうるというということでよろしいでしょうか。

    「このような現象」が何を指しているかわかりません。
    ベースアドレスを同一に設定した DLL を起動時に多数読み込むということがあれば、読み込み&再配置が多発します。
    少なくとも Windows ではそういうものです。

     

    さて、「よろしいでしょうか?」の質問が続いていますが、ご自身で設定を変える・わざと起こさせるなどの検証をしてみませんか?
    私の回答は、少しの資料とこれまでの経験からそういう仕組みになっているのではないかという推測を多分に含みます。
    速度検証をしたわけではない、きちんと裏をとったわけではない私に聞き詰めるより、実際に速度検証をした方が有意義です。

    # 間違っても、会社の上司などに私がある回答をしていたから、それが正しいかのように証明する手段(根拠?)に使わないように。:-P
    # 回答を自分で受け取るだけではなく、それが正しいのか吟味・検証することも重要なのですから。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク _kimura 2010年7月9日 0:32
    2010年7月8日 14:22
    モデレータ
  • 度々のご回答を頂ありがとう御座いました。

    速度検証をしたわけではない、きちんと裏をとったわけではない私に聞き詰めるより、実際に速度検証をした方が有意義です。

    確かにその通りです。私の方で検証作業を続けたいと思います。

    MSDNのngen.exeに関するヘルプを見る限りでは、今回会社で開発するシステムについては、
    ngen.exeによる恩恵を受けれるような条件を満たしている為、実害等をご存知でしたらお教え頂きたいと考えた次第です。

    また、ngen.exeを使用した際の起動時間については、現在幾つかの環境で確認したところPCスペックの差にもよりますが、
    今のところ全環境で起動速度が向上している為、有効な手段の一つと考えております。

    再配置処理等に関して、検証後に質問もしくは報告をさせていただきたいと思います。

    2010年7月9日 0:31