2016-06-25 1 views
0

私が実行した場合、次のコードは、私の記憶の上に何の影響も与えないだろうと述べている:なぜオブジェクトをインスタンス化するのは、そのオブジェクトが使用されるまで実行されないのですか? C#ので

Console.WriteLine("press a key to allocate the memory"); 
Console.ReadKey(); 
double[] hudgeBunchOfMemory = new double[100000000]; 
Console.WriteLine("allocated"); 
Console.ReadKey(); 

しかし、私は、配列を反復処理し、それらを使用する場合、割り当てはちょうどこののように、実行されますサンプル:

Console.WriteLine("press a key to allocate the memory"); 
Console.ReadKey(); 
double[] hudgeBunchOfMemory = new double[100000000]; 
for (long i = 0; i < 100000000; i++) 
{ 
    hudgeBunchOfMemory[i] = i + 1; 
} 
Console.WriteLine("allocated"); 
Console.ReadKey(); 

何がこの動作を生成しますか?私は、リリースとデバッグモードの両方でのVisual Studio 2012でコードをルーン文字が刻まれている、と私は、タスクマネージャでメモリの変化を述べてきた、そしてそれがかかるので、それは違いを観察本当に単純なことができ

EDIT

800メガバイトのメモリ。

はそれが、この動作について、最も適切な質問は:コードが実行され、メモリはまだalocatedない、またはそれがまったく実行されず、JITコンパイラによって回避しますか?

+5

ヒント - コンパイラはかなりスマートです。 –

+0

リリースモードとデバッグモードで実行し、適切なツールを使用してメモリを測定します。あなたはここに不可欠な情報を提供しません。 –

+2

訂正:ランタイムはかなりスマートです。コンパイラは、設計上、そうではありません。コンパイラは、すべてのメモリを割り当てるコードを喜んで発行します。最適化されず、生成されたCILコードを調べると、それが表示されます。 – hvd

答えて

6

あなたが見ている統計、おそらくタスクマネージャでは、をワーキングセットです。プロセスが使用する物理メモリの量を測定します。 RAM。 Windowsの(またはLinuxやOSX)のようなオンデマンド・ページ仮想メモリ・オペレーティング・システム上で

double[] hudgeBunchOfMemory = new double[100000000]; 

、その文はないは、RAMを割り当てません。 CLRは、OSの仮想メモリ機能をフルに活用し、アドレス空間をに割り当てます。メモリに4096バイトごとに1つずつ、プロセッサに番号を付けます。

は、あなたが実際にその割り当てが効果を取って見ることができる、あなたはそれを見るために、タスクマネージャの列を追加する必要があります。 [表示]> [列の選択]を使用するか、列見出しを右クリックして[コミットサイズ]を選択します。また、「ページ違反」を選択して、より多くの洞察力を与えます。

これで、最初のスニペットの違いが表示されます。 enterを押すと、Commit sizeカラムが上に飛びます。 CLRは、VirtualAlloc()でアドレス空間を割り当て、メモリ予約ががコミットされていることを確認しました。、ページングファイルに800000000バイトも割り当てました。 doワーキングセットは、4096バイトの1つあたりの番号を格納するページテーブルマッピングエントリを格納するために使用されるRAMです。そしてCLRが最初にそれらのページを使用すると想定するので意図的に熱くする2ページ(8192バイト)。

これで、2番目のスニペットの持つ効果を確認できるようになりました。配列要素にアクセスすると、ペダルは金属を満たす必要があります。には、配列要素を格納するためにRAMを割り当てる必要があります。非常に低いレベルでは、メモリアドレスを書き込む命令によってページフォールトが発生します。これによりOSにはの要求ページ番号機能が実装され、物理メモリを割り当てる必要があります。これで、ワーキングセットとページフォルトカウンタの両方がジップアップしていることがわかります。あなたが変わるのを見るのが速すぎるかもしれないが、現代のマシンはたくさんのRAMを持っている。 OSがRAMを取得して他のプロセスから取り除くために戦わなければならないときではないかもしれません。ハードページフォールトは高価です。コメントで間違った推測の

多くは、彼らが対処されるべきです。いいえ、コンパイラもジッタもこれに何ら影響しません。これは純粋にOSの動作です。デバッグビルドとリリースビルドの両方で同じ動作をします。 1番目のスニペットで配列を実際に使用していないにもかかわらず、Commit Sizeカウンタからわかるように、ではなく、はジッタオプティマイザによって排除されます。どんなnewステートメントについても保守的であり、常にその副作用が可視であると仮定します。

関連する問題