質問

32 ビット .NET プロセスで 1,000 MB を超えるメモリを割り当てられないのはなぜだろうか。次のミニ アプリケーションは、1,000 MB を割り当てた後に OutOfMemoryException をスローします。なぜ 1.8 GB ではなく 1,000 MB なのか?変更できるプロセス全体の設定はありますか?

static void Main(string[] args)
{
    ArrayList list = new ArrayList();
    int i = 0;
    while (true)
    {
        list.Add(new byte[1024 * 1024 * 10]); // 10 MB
        i += 10;
        Console.WriteLine(i);
    }
}

追伸:ゴミ収集は役に立ちません。

私が望むものを明確にするために編集してください: データベース/ディスクに書き込む前に、非常に大量のデータを処理するサーバー アプリケーションを作成しました。すべての一時ファイルを作成する代わりに、メモリ内キャッシュを作成しました。これにより、全体が超高速になります。しかしメモリには限界があるので、その限界を調べてみました。そして、なぜ私の小さなテスト プログラムがちょうど 1,000 MB の後で OutOfMemoryException をスローしたのか疑問に思いました。

役に立ちましたか?

解決

Win32プロセスの仮想アドレス空間の上限は1.5ギガバイト(完全に真実ではない)です。さらに、.NETフレームワークで.NETプロセスが消費できるメモリの%に制限があります。 machine.configプロセスが消費することができる利用可能なメモリの%である属性memoryLimitとprocessModel要素を有しています。デフォルト値は60%です。

あなたが実行しているマシンは、2GBのメモリを持っているか、あなたが取得するつもりだ、あなたのBOOT.INIで/ 3GBスイッチを有効にしていない場合は〜プロセスあたりのメモリの1.3ギガバイト

私はKBの記事を見つけることができませんが、私の記憶が正しければ、.NET 1.1は、1.5ギガバイトを超えて対処することはできません(1.8ギガバイト?)あなたの設定に関係なく制限します。

<のhref = "http://blogs.msdn.com/tmarq/archive/2007/06/25/some-history-on-the-asp-net-cache-memory-limits.aspx" のrel = "noreferrer"> http://blogs.msdn.com/tmarq/archive/2007/06/25/some-history-on-the-asp-net-cache-memory-limits.aspxする のhttp://social.msdn .microsoft.com /掲示板/ EN-US / CLR /スレッド/ c50ea343-b41b-467d-a457-c5a735e4dfffする http://www.guidanceshare.com/wiki/ASP.NET_1.1_Performance_Guidelines_ -_Caching#Configure_the_Memory_Limitする

他のヒント

たとえ 64 ビットであっても、巨大なメモリ ブロックを持つことは決して良い考えではありません。連続したメモリと断片化により大きな問題が発生します。

ここでの問題は、連続したブロックを見つけることです。3GB モードを有効にしてみることもできます (これにより、さらに数バイトを見つけることができる可能性があります)。 本当に それに対して忠告します。ここでの答えは次のとおりです。

  • メモリの使用量を減らす
  • データベース/ファイル システムを使用する
  • x64を使用

こちらもお読みください エリック・リッパートの ブログ (彼は、.NET に関するあらゆる一般的な質問についてブログ エントリを作成しているようです...)

私は最近、32ビットプロセスで.NETでのメモリ制限の周りに大規模なプロファイリングをやっています。私たちは皆、私たちは.NETアプリケーションで2.4ギガバイト(2 ^ 31)まで割り当てることができますアイデアによって衝撃を受けるが、残念ながらこれは:(真実ではありません。アプリケーション・プロセスは、多くのスペースを使用することがあると、オペレーティング・システムが大きなを行います私たちのためにそれを管理する仕事は、しかし、.NET自体がメモリの制限をプッシュし、典型的な実際のアプリケーションのために約600〜800メガバイトを占め、独自のオーバーヘッドを持っているようだ。これは、すぐにあなたを約かかり整数の配列を割り当てていることを意味します1.4ギガバイトは、あなたが)(OutOfMemoryException例外を期待する必要があります。

もちろん、64ビットでは、この制限は、後に道起こる(のは:) 5年間でチャットしましょう)が、メモリ内のすべての一般的なサイズも大きくなるため、増加したワードサイズの(〜私はそれがだ見つける午前1.7〜2倍)ます。

私は確かに知っては、オペレーティングシステムから仮想メモリのアイデアは間違いなく一つのプロセスの中にあなたの事実上無限の割り当てスペースを与えないということです。フル2.4ギガバイトが一度に実行されているすべての(多くの)アプリケーションにアドレス指定可能となるように、それだけあります。

私はこの洞察はやや役立ちます願っています。

私はもともとここに関連する何かを答え(私はまだニュービーだので、私はこれらのリンクを行うことになっていますかわからない):

ですそこに単一の.NETプロセスのメモリ制限

アプリケーションを 64 ビット アーキテクチャにビルドすると、約 2 GB より多くのメモリを割り当てることができます。これには、Visual Studio で新しいビルド構成を作成する必要があり、そのアプリケーションのビルドは 64 ビット バージョンの Windows でのみ実行されます。 。.NET では、アプリケーションのデフォルトの「任意の CPU」ビルド オプションを使用すると、(64 ビット Windows マシンであっても) ヒープから約 1.5 GB のメモリしか割り当てられないことがわかりました。これは、アプリケーションが実際に「Any CPU」モードでビルドされている場合は、32 ビット モードでのみ実行されます。ただし、x64 アーキテクチャにコンパイルすると、アプリケーションの実行中にヒープからはるかに多くのメモリを割り当てることができます。アプリケーション用の x64 ビルドを作成する方法を以下で説明します。

繰り返しになりますが、.NET プロジェクトで通常 (デフォルト) の「任意の CPU」ビルド オプションを使用すると、アプリケーションは 64 ビット Windows OS であっても、常に 32 ビット モードで実行されます。したがって、アプリケーションの実行中に約 1.5 ~ 2 GB を超える RAM メモリを割り当てることはできません。.NET アプリケーションを真の 64 ビット モードで実行するには、ビルド構成マネージャーに移動して、x64 アーキテクチャ用のビルド タイプを作成し、そのビルド タイプを使用してプログラムを x64 用に明示的に再コンパイルする必要があります。x64 ビルド モード オプションは、次の手順を使用して .NET ソリューション用に作成できます。

  1. Visual Studio の [ソリューション エクスプローラー] ペインで、ソリューション アイコンを右クリックし、ポップアップ メニューから [構成マネージャー] オプションを選択します。これにより、.NET ソリューション ファイルのビルドの [構成マネージャー] ダイアログ ウィンドウが開きます。
  2. ビルドの「構成マネージャー」ダイアログの上部右側で、下矢印をクリックして「<新規>」オプションを選択します。[新しいソリューション プラットフォーム] ダイアログが開きます。
  3. [新しいソリューション プラットフォーム] ダイアログの [プラットフォーム] オプションで、ドロップダウン メニューから [x64] を選択します。次に、[OK] ボタンをクリックすると、新しい x64 ビルド オプションが [構成マネージャー] ダイアログで使用できるようになります。
  4. 次に、[構成マネージャー] ダイアログで、[アクティブ ソリューション プラットフォーム] ドロップダウン メニューから [x64] を選択します。「閉じる」ボタンをクリックします。
  5. Visual Studio の [ソリューション エクスプローラー] ペインで、CS プロジェクト アイコンを右クリックし、ポップアップ メニューから [プロパティ] オプションを選択します (このメニューの一番下にある最後のオプション)。これにより、CS プロジェクトのプロパティ ウィンドウが開きます。
  6. CS プロジェクトのプロパティ ウィンドウの左側で、[ビルド] タブをクリックして、コード プロジェクトのビルド プロパティを表示します。このウィンドウの上部にある [プラットフォーム] に (デフォルトの [任意の CPU] オプションではなく) [x64] と表示されていることに注目してください。「プラットフォーム」ドロップダウンに「x64」が表示されない場合は、ここで選択する必要があります。
  7. 次に、コードをビルドするだけで、「bin」フォルダー内に、アプリケーションの新しい 64 ビット ビルドを含む x64 フォルダーが作成されます。

64 ビット Windows OS 上でアプリケーションの 64 ビット ビルドを使用すると、プログラムは ~2GB をはるかに超えるメモリ (おそらく最大 2^64 アドレス空間) を割り当てることができます (RAM とディスク領域が利用可能な場合)。この回答を書いている時点では、これらが実際の制限要因です)。

アプリケーションのメモリがまだ不足している場合は、Windows メモリ ページ ファイルのサイズを増やすこともできます。Windows では、ページ ファイルにより、オペレーティング システムが RAM メモリ領域を使い果たした場合にメモリを RAM からディスクに移動できます。ただし、RAM メモリのセクションをディスクとの間で移動するには多大な時間コストがかかるため、アプリケーションのパフォーマンスに大きな影響を与える可能性があります。パフォーマンスに関係なく、ページ サイズを増やすことで、(理論上は) C: 上に利用可能な空き領域と同じ大きさのページ ファイルを作成できます。Windows マシンのドライブ。その場合、アプリケーションはプログラムの実行中に、たとえば最大 4 TB のメモリ (またはページ ファイル サイズに設定されている任意の量のメモリ) を割り当てることができます。Windows マシンのページ ファイル設定を変更するには、次の手順を実行します。

  1. [この PC] を右クリックし、ポップアップ メニューの [プロパティ] オプションを選択して、[システムのプロパティ] ダイアログを開きます。これは、Windows の新しいバージョン (Windows 10、Win 2012 Server など) でも、[スタート] > [コントロール パネル] > [システムとセキュリティ] > [システム] に移動して実行できます。
  2. [システム]ダイアログの左側で、[詳細システムのプロパティ]オプションをクリックします。これにより、Windows の従来の「システムのプロパティ」ダイアログの「詳細」タブが表示されます。
  3. 「システムのプロパティ」ダイアログの「詳細」タブで、「パフォーマンス」ボックスの「設定」ボタンをクリックします。「パフォーマンス オプション」ダイアログが開きます。
  4. [パフォーマンス オプション] ダイアログで、[詳細] タブをクリックして、Windows メモリ ページ ファイルの現在のサイズ設定を確認します。
  5. ページファイルのサイズを増やすには、「変更」ボタンをクリックすると「仮想メモリ」ダイアログが開きます。
  6. 「仮想メモリ」ダイアログで「C:」ドライブを選択し、「カスタム サイズ」で「初期」サイズと「最大」サイズを設定します。C: の空き領域の最大量まで、任意のサイズを使用できます。ただし、この変更を行うと、ハード ドライブ上にページ ファイル用のスペースが確保されます。
  7. 次に、すべてのダイアログで「OK」をクリックして、新しい設定を確定します。次に、コンピュータを再起動して、すべての変更が適切に完了し、新しいページ ファイル設定が動作していることを確認します。

とにかく、これが、64 ビット Windows マシンで実行している場合でも、.NET アプリケーションでこの 1.5 ~ 2 GB のメモリ制限の問題が発生する理由を理解するのに役立つことを願っています。これは人々にとって非常に混乱する問題かもしれませんが、私の説明が意味をなすことを願っています。必要に応じて、この回答に関する質問をお気軽にメッセージください。

アプリケーションが停止するまで、それはこれらの10MBsを追加することを意味し、「しばらく(真)」:

私はここでの問題は、このアプリケーションは、それが行うすべてのループで10メガバイトを追加していく予定ということで、ループがあると思います。それは100 forループを実行するようにしたのであれば、それはRAMに近い1GBsに追加しているだろう、と私はそれが30秒未満でこれを行っているだろうと仮定しています。私のポイントは、あなたは決して終わることのないループ内で、ループあたりのメモリの10メガバイトの者にしようとしているさ。

私はあなたのポイントを取得していない場合は誠に申し訳ありませんが、ます:

static void Main(string[] args)
{
    ArrayList list = new ArrayList();
    int i = 0;
    while (true)
    {
        using(byte newBt = new byte[1024 * 1024 * 10])
        {
            list.Add(newBt); // 10 MB
            i += 10;
            Console.WriteLine(i);
        }
    }
}

あなたが使用しての方法を試したことがありますか?そして、これは愚かな質問かもしれませんが、なぜ、あなたは永遠のループを作成したのですか? Oあなたは>。> xDでコードストリップにシンボルをしよう。

ソース: http://msdn.microsoft .COM / EN-US /ライブラリ/ yh598w02(V = vs.80).aspxの

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top