2010-05-30 10 views
10

Ho molta RAM, tuttavia, dopo aver avviato e terminato un gran numero di processi, sembra che la maggior parte della memoria virtuale delle applicazioni sia stata cercata su disco, e il passaggio a uno dei vecchi processi richiede molto tempo per carica la memoria nella RAM.E 'possibile cancellare tutta la memoria in Windows?

C'è un modo, tramite l'API di Windows o tramite chiamata del kernel, per far sì che Windows cancelli tutta la memoria (o il più possibile)? Magari sfogliando l'elenco dei processi in esecuzione e ottenere il gestore della memoria per rimuovere la pagina dalla memoria di ogni processo?

risposta

7

Bene, non è difficile da implementare. Utilizzare VirtualQueryEx() per rilevare gli indirizzi virtuali utilizzati da un processo, ReadProcessMemory() per forzare il caricamento delle pagine.

Non è probabile che faccia alcuna differenza, sarà solo il tuo programma che impiegherà per sempre il suo lavoro. La diagnostica comune per il ricaricamento lento delle pagine è un file di paging frammentato. Comune su Windows XP per esempio quando il disco non è stato deframmentato da molto tempo e gli è stato permesso di riempire frequentemente la capacità. L'utilità PageDefrag di SysInternals può aiutare a risolvere il problema.

+0

Grazie per entrambi questi suggerimenti! Fammi controllare se l'utilizzo delle due funzioni fa alcuna differenza sulle prestazioni dei processi di commutazione! –

+2

Sì, perché chiamare ReadProcessMemory su ogni byte di ogni processo sicuramente funzionerà meglio delle semplici operazioni di paging in ..... Oh, a proposito, avrai bisogno di Admin preamp e prendo il privilegio SE_DEBUG_NAME per usare il processo funzioni di memoria. –

+0

Oh, no, in realtà non voglio leggere ogni byte, voglio solo dire al gestore della memoria che potrei essere in procinto di farlo ...Sicuramente il gestore della memoria deve sapere se le parti della memoria di un processo sono state sfasate; Sono sorpreso che non abbia un'interfaccia per richiedere la memoria di paging per un processo specifico senza richiedere effettivamente il contenuto da quella memoria. Re "ogni byte di ogni processo": non mi importa se fa tutto questo in una volta mentre sono in pausa caffè, finché quando torno tutto è in memoria. –

-2

No, Windows non fornisce questa funzionalità in modo nativo. Programmi come Cacheman e RAM IDLE realizzano questo semplicemente allocando una grande porzione di RAM, forzando altre cose alla pagina su disco, che realizza in modo efficace ciò che si desidera.

+6

Ehm, sembra che darebbe il contrario di ciò che vuole. –

+0

@Neil: Vuole che le cose vengano visualizzate o messe in uscita? È difficile dire da "impunito" ... se vuole che tutto venga inserito nel cercapersone di quanto non stia cercando il comportamento predefinito di Windows, quindi ho pensato che volesse un comportamento non predefinito, che avrebbe dovuto eseguire il paging su disco. –

+0

Scusa se non era chiaro. Voglio ottenere tutto _into_ dalla memoria fisica, _off_ dall'hard disk. Anche se ho una RAM da 2 GB, ogni volta che Alt-Tab lo faccio su un altro processo, sembra che quel processo debba essere prima recuperato dal disco, cosa che voglio evitare facendo una sola chiamata "rimetti tutto in memoria fisica", prendere il caffè e poi tornare a un sistema veloce e reattivo. –

9

Aggiornamento 3: Ho caricato il mio programma completo to github.


OK, sulla base delle risposte fino ad ora, ecco un suggerimento ingenuo per uno strumento che cerca di ottenere tutti le applicazioni di back nella memoria fisica:

  1. Allocare un piccolo pezzo di memoria X, forse 4MB . (Dovrebbe essere non paginabili?)
  2. iterare su tutti i processi:
    • Per ogni processo, copiare blocchi di memoria a X. (Eventualmente sospende il processo prima?)

Supponiamo di avere 2 GB di RAM, e solo 1 GB è effettivamente richiesto dai processi. Se tutto è nella memoria fisica, copi solo 256 blocchi, non la fine del mondo. Alla fine della giornata, ci sono buone possibilità che tutti i processi siano ora interamente nella memoria fisica.

Possibili convenienza e ottimizzazione opzioni:

  • Verificare prima che lo spazio totale richiesto non è più rispetto, ad esempio, il 50% dello spazio fisico totale.
  • Opzionalmente può essere eseguito solo su processi di proprietà dell'utente corrente o su un elenco specificato dall'utente.
  • Controllare prima se ciascun blocco di memoria è effettivamente trasferito su disco o meno.

Posso scorrere tutti i processi utilizzando EnumProcesses(); Sarei grato per qualsiasi suggerimento su come copiare la memoria di un intero processo in termini di quantità.


Aggiornamento: Qui è la mia funzione di esempio. Prende l'ID del processo come argomento e copia un byte da ciascuna pagina del processo. (Il secondo argomento è la dimensione della memoria processo di massima, ottenibile mediante GetSystemInfo().)

void UnpageProcessByID(DWORD processID, LPVOID MaximumApplicationAddress, DWORD PageSize) 
{ 
    MEMORY_BASIC_INFORMATION meminfo; 
    LPVOID lpMem = NULL; 

    // Get a handle to the process. 
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID); 

    // Do the work 
    if (NULL == hProcess) 
    { 
    fprintf(stderr, "Could not get process handle, skipping requested process ID %u.\n", processID); 
    } 
    else 
    { 
    SIZE_T  nbytes; 
    unsigned char buf; 

    while (lpMem < MaximumApplicationAddress) 
    { 
     unsigned int stepsize = PageSize; 

     if (!VirtualQueryEx(hProcess, lpMem, &meminfo, sizeof(meminfo))) 
     { 
     fprintf(stderr, "Error during VirtualQueryEx(), skipping process ID (error code %u, PID %u).\n", GetLastError(), processID); 
     break; 
     } 

     if (meminfo.RegionSize < stepsize) stepsize = meminfo.RegionSize; 

     switch(meminfo.State) 
     { 
     case MEM_COMMIT: 
     // This next line should be disabled in the final code 
     fprintf(stderr, "Page at 0x%08X: Good, unpaging.\n", lpMem); 

     if (0 == ReadProcessMemory(hProcess, lpMem, (LPVOID)&buf, 1, &nbytes)) 
      fprintf(stderr, "Failed to read one byte from 0x%X, error %u (%u bytes read).\n", lpMem, GetLastError(), nbytes); 
     else 
      // This next line should be disabled in the final code 
      fprintf(stderr, "Read %u byte(s) successfully from 0x%X (byte was: 0x%X).\n", nbytes, lpMem, buf); 

     break; 
     case MEM_FREE: 
     fprintf(stderr, "Page at 0x%08X: Free (unused), skipping.\n", lpMem); 
     stepsize = meminfo.RegionSize; 
     break; 
     case MEM_RESERVE: 
     fprintf(stderr, "Page at 0x%08X: Reserved, skipping.\n", lpMem); 
     stepsize = meminfo.RegionSize; 
     break; 
     default: 
     fprintf(stderr, "Page at 0x%08X: Unknown state, panic!\n", lpMem); 
     } 

     //lpMem = (LPVOID)((DWORD)meminfo.BaseAddress + (DWORD)meminfo.RegionSize); 
     lpMem += stepsize; 
    } 
    } 

    CloseHandle(hProcess); 
} 

Domanda: la regione da cui dimensione I incremento composto al massimo una pagina, o mi sto perdendo pagine? Dovrei provare a scoprire anche la dimensione della pagina e incrementare solo con il minimo delle dimensioni della regione e della dimensione della pagina? Aggiornamento 2: La dimensione della pagina è solo 4kiB! Ho modificato il codice precedente per incrementare solo in step 4kiB. Nel codice finale ci libereremmo di fprintf all'interno del ciclo.

+1

Dopo alcuni test, sto scoprendo che funziona davvero bene! Certamente ha l'effetto che un'applicazione così "non eseguita" diventa di nuovo reattiva e non richiede alcun accesso imprevisto al disco rigido. –

+0

@Tomalak: ho reso l'altra risposta accettata perché il mio programma si basa in ultima analisi su tale idea. È molto utile dopo una sessione di mplayer o di qualsiasi programma Adobe per tutta la vita sul disco. –

+0

Qualcuno può fornire un binario di questo strumento per il download e l'installazione? – TMS

Problemi correlati