Vedo un comportamento completamente diverso quando si esegue un programma che tenta di superare RSS su macchine diverse. Il codice è qualcosa di simile:malloc si comporta in modo diverso su macchine diverse
...
char** s = (char**)malloc(10000*sizeof(char*));
for (i = 0; i < 10000; i++){
s[i] = (char*)malloc(1000*1000*sizeof(char));
if (s[i] == NULL) {
printf("cannot allocate memory for s[%d]",i);
exit(1);
}
}
int j = 0;
while(1){
for (i = 0; i < 10000; i++){
for (j = 0; j < 1000*1000; j++) {
s[i][j] = 1;
}
if ((i % 100) == 0) printf("i = %d\n", i);
}
}
for (i = 0; i < 10000; i++)
free(s[i]);
free(s);
...
Il codice sopra tenta di allocare circa 10 GB di memoria utilizzando malloc. Le prime due macchine che ho provato su questo codice sono state eseguite su Linux kernel 2.6 e l'ultima su Linux kernel Linux 2.4. Ecco i comportamenti che vedo su queste macchine:
Machine1: la memoria viene allocata utilizzando overcommit di memoria, ma quando si assegnano valori alle posizioni di memoria nel ciclo while, assegna solo quanto consentito da RSS. Così OOM Killer uccide il processo quando viene stampato i = 3800, che è circa 4 GB di memoria di questa macchina.
Machine2: la memoria viene allocata utilizzando l'overcommit di memoria e il ciclo while si attiva per sempre, allocando le pagine dalla memoria virtuale. Il processo diventa un po 'più lento dopo che i = 3800 viene stampato, il che è normale.
machine3: questa macchina ha solo 2 GB di memoria. La memoria non può nemmeno essere assegnata. Sembra che l'over commit non sia impostato o che il kernel 2.4 non supporti l'allocazione delle pagine delle macchine virtuali usando malloc! Quindi nel primo ciclo for esce quando si alloca memoria per i = 2138
L'azione desiderata è quella che si verifica in machine2. Qualcuno sa quali opzioni (del kernel?) Devono essere impostate per consentire al sistema operativo di allocare pagine di memoria virtuale usando malloc e avviare il paging mentre la memoria richiesta supera l'RSS?
Grazie
Dove è "if (s! = NULL)" della prima allocazione? –
Preferenza personale: invece di 'char ** s = (char **) malloc (10000 * sizeof (char *));' and 's [i] = (char *) malloc (10000 * sizeof (char)); 'Vorrei fare' char ** s = malloc (10000 * sizeof * s); 'e' s [i] = malloc (10000 * sizeof ** s); '. In questo modo, se 's' cambia da un' char ** 'a un' wchar_t ** 'in futuro, tutte le chiamate di' malloc' si adatteranno se necessario. In generale, il cast del valore di ritorno 'malloc()' non è necessario in C, ed è considerato da alcuni (come me) una cattiva idea in quanto ostacola la manutenibilità. –
Architettura? x86_64? –