30

私のメモリは 4G の物理メモリですが、1.5G のメモリ オブジェクトを作成しただけでもメモリ例外が発生したのはなぜですか。理由はありますか?(同時に、タスク マネージャーの [パフォーマンス] タブで、メモリが完全に占有されていないこともわかりました。また、ここに入力することもできました。つまり、メモリは実際には少なくないので、他のメモリ制限に達したと思います)?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestBigMemoryv1
{
    class MemoryHolderFoo
    {
        static Random seed = new Random();
        public Int32 holder1;
        public Int32 holder2;
        public Int64 holder3;

        public MemoryHolderFoo()
        {
            // prevent from optimized out
            holder1 = (Int32)seed.NextDouble();
            holder2 = (Int32)seed.NextDouble();
            holder3 = (Int64)seed.NextDouble();
        }
    }

    class Program
    {
        static int MemoryThreshold = 1500; //M
        static void Main(string[] args)
        {
            int persize = 16;
            int number = MemoryThreshold * 1000 * 1000/ persize;
            MemoryHolderFoo[] pool = new MemoryHolderFoo[number];
            for (int i = 0; i < number; i++)
            {
                pool[i] = new MemoryHolderFoo();
                if (i % 10000 == 0)
                {
                    Console.Write(".");
                }
            }

            return;
        }
    }
}
4

7 に答える 7

41

通常の 32 ビット Windows アプリでは、プロセスには 2GB のアドレス可能なメモリしかありません。これは、使用可能な物理メモリの量とは無関係です。

したがって、2GB が利用可能ですが、割り当て可能な最大値は 1.5 です。重要なのは、コードがプロセスで実行されている唯一のコードではないということです。残りの 0.5 GB は、おそらくプロセス中の CLR と断片化です。

更新: 64 ビット プロセスの .Net 4.5 では、gcAllowVeryLargeObjects設定が有効になっている場合、大きな配列を持つことができます。

64 ビット プラットフォームで、合計サイズが 2 ギガバイト (GB) を超える配列を有効にします。配列内の要素の最大数は UInt32.MaxValue です。

<configuration>
  <runtime>
    <gcAllowVeryLargeObjects enabled="true" />
  </runtime>
</configuration>
于 2009-02-28T04:42:34.350 に答える
10

他のポイントに追加するだけです。大量のメモリにアクセスしたい場合は、x64 を検討してください。ただし、1 つのオブジェクトの最大サイズは依然として 2GB であることに注意してください。また、x64 では参照が大きくなるため、実際には参照型の最大配列/リスト サイズが小さくなることを意味します。もちろん、その限界に達する頃には、とにかく間違ったことをしている可能性があります!

その他のオプション:

  • ファイルを使用する
  • データベースを使用する

(明らかに、両方ともインプロセスメモリと比較してパフォーマンスの違いがあります)


更新: 4.5 より前のバージョンの .NET では、最大オブジェクト サイズは 2GB です。4.5 以降では、 gcAllowVeryLargeObjectsが有効になっている場合、より大きなオブジェクトを割り当てることができます。の制限stringは影響を受けませんが、リストは配列によって支えられているため、「配列」は「リスト」もカバーする必要があることに注意してください。

于 2009-02-28T06:36:55.230 に答える
5

以前の返信に追加するだけです。/3Gb[およびオプションでuserva]ブートフラグで起動されたシステムでは、2Gbの制限を超えることができます。

于 2009-02-28T05:02:45.643 に答える
5

Visual Studio の既定のコンパイル モードである 32 ビット プロセスではなく、64 ビット プロセスをビルドしていることを確認します。これを行うには、プロジェクトを右クリックし、[プロパティ] -> [ビルド] -> [プラットフォーム ターゲット: x64] を選択します。他の 32 ビット プロセスと同様に、32 ビットでコンパイルされた Visual Studio アプリケーションには 2 GB の仮想メモリ制限があります。

各プロセスには、アドレス空間と呼ばれる独自の仮想メモリがあり、実行するコードと操作するデータをそこにマップします。32 ビット プロセスは 32 ビットの仮想メモリ アドレス ポインターを使用します。これにより、32 ビット プロセスがアドレス指定できる仮想メモリの量の絶対上限が 4GB (2^32) になります。ただし、オペレーティング システムは (独自のコードとデータを参照するために) その半分を必要とし、プロセスごとに 2GB の制限を作成します。32 ビット アプリケーションがそのアドレス空間の 2GB 全体を消費しようとすると、コンピューターの物理メモリがいっぱいになっていない場合でも、「System.OutOfMemory」が返されます。

64 ビット プロセスにはこの制限がありません。64 ビット ポインターを使用するため、理論上の最大アドレス空間は 16 エクサバイト (2^64) です。実際には、Windows x64 ではプロセスの仮想メモリが 8TB に制限されています。メモリ制限の問題の解決策は、64 ビットでコンパイルすることです。

ただし、Visual Studio でのオブジェクトのサイズは既定で 2 GB に制限されています。合計サイズが 2GB を超える複数のアレイを作成できますが、デフォルトでは 2GB を超えるアレイを作成することはできません。それでも 2GB を超える配列を作成したい場合は、次のコードを app.config ファイルに追加してください。

<configuration>
  <runtime>
    <gcAllowVeryLargeObjects enabled="true" />
  </runtime>
</configuration>
于 2013-06-26T13:49:35.100 に答える
4

もう 1 つ知っておくべきことがあります。一部の .NET オブジェクトには、「連続した」メモリが必要です。つまり、大きな配列を割り当てようとしている場合、システムはプロセスに十分な空きメモリを必要とするだけでなく、そのすべての空きメモリを 1 つの大きなチャンクにする必要があります...そして残念ながら、プロセスメモリは時間の経過とともに断片化されるため、これは可能性があります利用できません。

一部のオブジェクト/データ型にはこの要件があり、一部のオブジェクト/データ型にはありません...どれがそうかは思い出せませんが、StringBuilder と MemoryStream には異なる要件があることを思い出すようです。

于 2009-07-20T00:35:24.413 に答える
4

他のポスターが述べたように、32 ビット アプリとして最大 2Gb のアドレス指定可能なメモリがあります。オーバーヘッドを忘れないでください。9,300 万個のオブジェクトの配列を作成しています。オブジェクトごとに 4 バイトのオーバーヘッドが発生すると、350Mb のメモリが余分に必要になります。

于 2009-02-28T04:56:05.207 に答える
3

32 ビットの Windows オペレーティング システムでは、1 つのアプリケーションがアクセスできる最大の「ユーザー モード」メモリは 2GB です...ボックスに 4GB のメモリがあると仮定します。

Windows サーバーでのアンマネージ VC++ アプリケーションのメモリ消費

http://blogs.technet.com/markrussinovich/archive/2008/07/21/3092070.aspx

(昨日ほとんど同じことを聞いたので、あなたがこれを聞いたのはおかしいです...)

于 2009-02-28T04:40:43.590 に答える