Domanda

Mi chiedo perché non riesco ad allocare più di 1.000 MB di memoria nel mio processo .NET a 32 bit.La seguente mini applicazione genera un'eccezione OutOfMemoryException dopo aver allocato 1.000 MB.Perché 1.000 MB e non dire 1,8 GB?Esiste un'impostazione a livello di processo che potrei modificare?

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);
    }
}

PS:La raccolta dei rifiuti non aiuta.

Modifica, per chiarire cosa voglio: Ho scritto un'applicazione server che gestisce quantità molto grandi di dati prima di scriverli sul database/disco.Invece di creare file temporanei per tutto, ho scritto una cache in memoria, che rende il tutto superveloce.Ma la memoria è limitata, quindi ho provato a scoprire quali sono i limiti.E mi chiedevo perché il mio piccolo programma di test lanciasse OutOfMemoryException esattamente dopo 1.000 MB.

È stato utile?

Soluzione

Il limite dello spazio degli indirizzi virtuali di un processo Win32 è 1,5 GB (non del tutto vero).Inoltre nei framework .NET esiste un limite alla percentuale di memoria che un processo .NET può consumare.Il file machine.config ha un elemento processModel con un attributo memoryLimit che è la percentuale di memoria disponibile che un processo può consumare.Il valore predefinito è 60%.

Se la macchina su cui stai utilizzando ha 2 GB di memoria o non hai abilitato l'opzione /3GB nel tuo BOOT.INI, otterrai circa 1,3 GB di memoria per processo.

Non riesco a trovare l'articolo della Knowledge Base ma, se ricordo bene, .NET 1.x non può superare il limite di 1,5 GB (1,8 GB?) indipendentemente dalle impostazioni.

http://blogs.msdn.com/tmarq/archive/2007/06/25/some-history-on-the-asp-net-cache-memory-limits.aspx http://social.msdn.microsoft.com/Forums/en-US/clr/thread/c50ea343-b41b-467d-a457-c5a735e4dfff http://www.guidanceshare.com/wiki/ASP.NET_1.1_Performance_Guidelines_-_Caching#Configure_the_Memory_Limit

Altri suggerimenti

Avere enormi blocchi di memoria non è mai una buona idea, nemmeno a 64 bit.Hai grossi problemi con la memoria contigua e la frammentazione.

Il problema qui è trovare un blocco contiguo.Potresti provare ad abilitare la modalità 3 GB (che potrebbe aiutarlo a trovare qualche byte in più) ma io Veramente sconsigliarlo.Le risposte qui sono:

  • utilizzare meno memoria
  • utilizzare un database/file system
  • usa x64

Potresti anche voler leggere Quello di Eric Lippert blog (sembra che abbia un post sul blog per ogni domanda comune su .NET...)

Recentemente ho eseguito un'ampia profilazione dei limiti di memoria in .NET su un processo a 32 bit.Siamo tutti bombardati dall'idea di poter allocare fino a 2,4 GB (2^31) in un'applicazione .NET ma sfortunatamente questo non è vero :(.Il processo di applicazione ha molto spazio da utilizzare e il sistema operativo fa un ottimo lavoro gestendolo per noi, tuttavia, .NET stesso sembra avere un proprio sovraccarico che rappresenta circa 600-800 MB per le tipiche applicazioni del mondo reale che spingono il limite di memoria .Ciò significa che non appena allochi un array di numeri interi che occupa circa 1,4 GB, dovresti aspettarti di vedere un OutOfMemoryException().

Ovviamente a 64 bit, questo limite si verifica molto più tardi (parliamo tra 5 anni :)), ma cresce anche la dimensione generale di tutto ciò che è in memoria (trovo che sia da ~ 1,7 a ~ 2 volte) a causa della maggiore dimensione della parola.

Quello che so per certo è che l'idea della memoria virtuale del sistema operativo NON ti offre sicuramente uno spazio di allocazione praticamente infinito all'interno di un processo.È lì solo in modo che tutti i 2,4 GB siano indirizzabili a tutte le (molte) applicazioni in esecuzione contemporaneamente.

Spero che questa intuizione aiuti in qualche modo.

Inizialmente avevo risposto a qualcosa correlato qui (sono ancora un principiante, quindi non sono sicuro di come dovrei fare questi collegamenti):

Esiste un limite di memoria per un singolo processo .NET

Puoi allocare MOLTA PIÙ memoria di ~ 2 GB creando la tua applicazione su un'architettura a 64 bit, che richiede la creazione di una nuova configurazione di build in Visual Studio e che la build dell'applicazione verrà eseguita solo su versioni a 64 bit di Windows .In .NET, utilizzando l'opzione di build predefinita "Qualsiasi CPU" per l'applicazione, trovo che sono in grado di allocare solo circa 1,5 GB di memoria dall'heap (anche su computer Windows a 64 bit), perché l'applicazione in realtà funziona solo in modalità a 32 bit quando è costruito in modalità "Qualsiasi CPU".Ma compilando sull'architettura x64, puoi allocare molta, molta più memoria dall'heap durante l'esecuzione della tua applicazione e di seguito spiegherò come creare una build x64 per la tua applicazione:

Ancora una volta, utilizzando la normale opzione di compilazione "Qualsiasi CPU" (predefinita) nel tuo progetto .NET, la tua applicazione verrà SEMPRE eseguita in modalità a 32 bit, anche su un sistema operativo Windows a 64 bit.Pertanto non sarà possibile allocare più di 1,5-2 GB di memoria RAM durante l'esecuzione dell'applicazione.Per eseguire la tua applicazione .NET in vera modalità a 64 bit, dovrai accedere al gestore della configurazione della build e creare un tipo di build per l'architettura x64, quindi ricompilare il programma per x64 utilizzando esplicitamente quel tipo di build.L'opzione della modalità build x64 può essere creata per la soluzione .NET utilizzando i seguenti passaggi:

  1. Nel riquadro "Esplora soluzioni" di Visual Studio, fare clic con il pulsante destro del mouse sull'icona della soluzione e scegliere l'opzione "Gestione configurazione" dal menu a comparsa.Verrà aperta la finestra di dialogo "Configuration Manager" di compilazione per il file della soluzione .NET.
  2. Sul lato destro, nella parte superiore della finestra di dialogo "Configuration Manager", fare clic sulla freccia giù e selezionare l'opzione "<nuovo>".Verrà aperta la finestra di dialogo "Nuova piattaforma di soluzione".
  3. Nella finestra di dialogo "Nuova piattaforma di soluzione", per l'opzione "Piattaforma", scegli "x64" dal menu a discesa.Quindi fare clic sul pulsante "OK" e la nuova opzione di build x64 sarà ora disponibile nella finestra di dialogo Gestione configurazione.
  4. Quindi, nella finestra di dialogo "Configuration Manager", seleziona "x64" nel menu a discesa "Active Solution Platform".Fare clic sul pulsante "Chiudi".
  5. Nel riquadro "Esplora soluzioni" di Visual Studio, fai clic con il pulsante destro del mouse sull'icona CS Project e scegli l'opzione "Proprietà" dal menu a comparsa (l'ultima opzione nella parte inferiore di questo menu).Verrà aperta la finestra delle proprietà del progetto CS.
  6. Sul lato sinistro della finestra delle proprietà del progetto CS, fai clic sulla scheda "Build" per visualizzare le proprietà di build per il tuo progetto di codice.Nella parte superiore di questa finestra, nota che la "Piattaforma" ora dovrebbe indicare "x64" (in contrapposizione all'opzione predefinita "Qualsiasi CPU").Se il menu a discesa "Piattaforma" non mostra "x64", dovresti selezionarlo ora.
  7. Quindi crea semplicemente il tuo codice e nella cartella "bin", ora dovresti avere una cartella x64 con la nuova build a 64 bit della tua applicazione al suo interno.

L'utilizzo di una build a 64 bit della tua applicazione su un sistema operativo Windows a 64 bit consentirà al tuo programma di allocare molto più di ~ 2 GB di memoria, presumibilmente fino a 2 ^ 64 spazi di indirizzi (se hai RAM e spazio su disco disponibili, che sono i veri fattori limitanti al momento della stesura di questa risposta).

Se ANCORA stai esaurendo la memoria nella tua applicazione, puoi anche aumentare la dimensione del file di paging della memoria di Windows.Su Windows, il file di paging consente al sistema operativo di spostare la memoria dalla RAM al disco, se esaurisce lo spazio di memoria RAM.Ma lo spostamento di sezioni di memoria RAM da e verso il disco comporta un notevole dispendio di tempo, quindi potrebbe avere un impatto negativo sulle prestazioni della tua applicazione.Indipendentemente dalle prestazioni, aumentando la dimensione della pagina, potresti (in teoria) rendere il file di pagina tanto grande quanto lo spazio libero disponibile su C:unità del tuo computer Windows.In tal caso, l'applicazione sarà in grado di allocare, ad esempio, fino a 4 TB di memoria (o qualsiasi quantità di memoria su cui è impostata la dimensione del file di paging) durante l'esecuzione del programma.Per modificare le impostazioni del file di paging per il tuo computer Windows, procedi come segue:

  1. Apri la finestra di dialogo "Proprietà del sistema" facendo clic con il pulsante destro del mouse su "Questo PC" e scegliendo l'opzione "Proprietà" nel menu a comparsa.Questa operazione può essere eseguita anche nelle versioni successive di Windows (Windows 10, Win 2012 Server, ecc...) andando su "Start" > "Pannello di controllo" > "Sistema e sicurezza" > "Sistema".
  2. Sul lato sinistro della finestra di dialogo "Sistema", fare clic sull'opzione "Proprietà di sistema avanzate".Verrà visualizzata la scheda "Avanzate" della finestra di dialogo "Proprietà del sistema" legacy per Windows.
  3. Nella scheda "Avanzate" della finestra di dialogo "Proprietà del sistema", fare clic sul pulsante "Impostazioni" nella casella "Prestazioni".Si aprirà la finestra di dialogo "Opzioni prestazioni".
  4. Nella finestra di dialogo "Opzioni prestazioni", fare clic sulla scheda "Avanzate" per visualizzare l'impostazione della dimensione corrente per il file di paging della memoria di Windows.
  5. Per aumentare la dimensione del file di paging, fare clic sul pulsante "Cambia" e si aprirà la finestra di dialogo "Memoria virtuale".
  6. Nella finestra di dialogo "Memoria virtuale", seleziona l'unità "C:", quindi in "Dimensione personalizzata", imposta le dimensioni "Iniziale" e "Massima".Puoi utilizzare qualsiasi dimensione fino alla quantità massima di spazio libero sulla C:unità, ma apportando questa modifica si riserverà lo spazio per il file di paging sul disco rigido.
  7. Quindi fare clic su "Ok" in tutte le finestre di dialogo per confermare le nuove impostazioni.Quindi riavvia il computer per assicurarti che tutte le modifiche siano state completate correttamente e che le nuove impostazioni del file di paging siano operative.

Ad ogni modo, spero che questo aiuti le persone a capire perché possono incorrere in questo problema di limitazione di memoria di 1,5 - 2 GB in un'applicazione .NET, anche se in esecuzione su un computer Windows a 64 bit.Questo può essere un problema molto confuso per le persone e spero che la mia spiegazione abbia senso.Non esitate a inviarmi messaggi con domande su questa risposta, se necessario.

Penso che il problema qui sia che questa applicazione aggiungerà 10 MB con ogni ciclo creato e il ciclo è:"mentre(true)" significa che aggiungerà questi 10 MB finché l'applicazione non verrà arrestata.Quindi, se dovesse funzionare per 100 loop, avrebbe aggiunto quasi 1 GB alla RAM e suppongo che lo avrebbe fatto in meno di 30 secondi.Il punto è che stai provando a 10 megabyte di memoria per ciclo, in un ciclo infinito

Mi dispiace davvero se non ho capito il tuo punto, ma:

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);
        }
    }
}

Hai provato il metodo using?E questa potrebbe essere una domanda stupida, ma perché hai creato un ciclo eterno?O se provi il codice rimuovi i simboli >.> xD.

Fonte: http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top