2012-09-08 21 views
10

En mi clase tenemos una misión y una de las preguntas afirma:perder a propósito toda la memoria principal para aprender la fragmentación

la fragmentación de memoria en C: Diseñar, implementar y ejecutar un programa en C que hace el siguiente: asigna memoria para una secuencia de matrices de 3 m de tamaño 500000 elementos cada una; luego desasigna todas las matrices pares y asigna una secuencia de m matrices de tamaño 700000 elementos cada una. Mida las cantidades de tiempo que su programa requiere para las asignaciones de la primera secuencia y para la segunda secuencia. Elija m para que agote toda la memoria principal disponible para su programa. Explicar los tiempos de su

Mi aplicación de esto es la siguiente:

#include <iostream> 
#include <time.h> 
#include <algorithm> 

void main(){ 
    clock_t begin1, stop1, begin2, stop2; 
    double tdif = 0, tdif2 = 0; 
    for(int k=0;k<1000;k++){ 
    double dif, dif2; 
    const int m = 50000; 
    begin1 = clock(); 
    printf("Step One\n"); 
    int *container[3*m]; 
    for(int i=0;i<(3*m);i++) 
    { 
     int *tmpAry = (int *)malloc(500000*sizeof(int)); 
     container[i] = tmpAry; 
    } 
    stop1 = clock(); 
    printf("Step Two\n"); 
    for(int i=0;i<(3*m);i+=2) 
    { 
    free(container[i]); 
    } 
    begin2 = clock(); 
    printf("Step Three\n"); 
    int *container2[m]; 
    for(int i=0;i<m;i++) 
    { 
    int *tmpAry = (int *)malloc(700000*sizeof(int)); 
    container2[i] = tmpAry; 
    } 
    stop2 = clock(); 
    dif = (stop1 - begin1)/1000.00; 
    dif2 = (stop2 - begin2)/1000.00; 
    tdif+=dif; 
    tdif/=2; 
    tdif2+=dif2; 
    tdif2/=2; 
} 
printf("To Allocate the first array it took: %.5f\n",tdif); 
printf("To Allocate the second array it took: %.5f\n",tdif2); 
system("pause"); 
}; 

He cambiado esto de diferentes maneras, pero las consistencias que veo son que cuando inicialmente asignar la memoria de 3 * m * 500000 arrays de elementos. Utiliza toda la memoria principal disponible. Pero cuando digo que los libere, la memoria no se vuelve a liberar en el sistema operativo, entonces, cuando va a asignar las matrices de elementos m * 700000, lo hace en el archivo de página (memoria de intercambio) para que no muestre fragmentación de memoria. .

El código anterior ejecuta esto 1000 veces y lo promedia, lleva bastante tiempo. El primer promedio de secuencia tomó 2.06913 segundos y la segunda secuencia duró 0.67594 segundos. Para mí, se supone que la segunda secuencia tarda más tiempo en mostrar cómo funciona la fragmentación, pero debido al intercambio que se utiliza, esto no ocurre. ¿Hay alguna forma de evitar esto o estoy equivocado en mi suposición?

Preguntaré al profesor sobre lo que tengo el lunes, pero hasta entonces cualquier ayuda sería apreciada.

+1

"Elija m para que agote toda la memoria principal disponible para su programa", que en realidad puede ser bastante difícil en algunos sistemas.Mientras escribo, tengo 2 GB de memoria principal, pero un proceso en Windows de 32 bits solo puede usar 2 GB de espacio de direcciones virtuales de todos modos. Si tuviera 3GB de memoria principal, sería imposible que un proceso lo use todo. Lo que no puedo recordar, sin embargo, es si todos los procesos de 32 bits comparten los mismos 2GB y los otros 1GB solo los utilizan el sistema operativo y los controladores, o si Windows de 32 bits puede compartir 3GB correctamente entre los procesos. –

+3

Algunos sistemas operativos no asignarán la memoria principal hasta que realmente se haya escrito, por lo que sus tiempos pueden no significar mucho en términos de fragmentación. Puede estar prácticamente fragmentado. –

+3

Algo más que comprobar: dependiendo de su sistema operativo y la configuración, es posible que esté llegando al umbral 'mmap' en' malloc'. 50000 elementos está justo por debajo del valor predeterminado de 'M_MMAP_MAX', y si está en Linux de 32 bits, los bloques tienen más de' M_MMAP_THRESHOLD'. Si de hecho está activando 'mmap', en lugar de usar el heap, las asignaciones terminan como asignaciones individuales y no sufren fragmentación. Intenta reducir el tamaño de los bloques. –

Respuesta

2

Muchas implementaciones de libc (glibc Creo incluido) no liberan memoria de nuevo al sistema operativo cuando se llama free(), pero que sea para que pueda usarlo en la próxima distribución sin syscall. Además, debido a la complejidad de la paginación moderna y las etiquetas de la memoria virtual, nunca se puede estar seguro de dónde hay algo en la memoria física, lo que hace que sea casi imposible fragmentarlo intencionalmente (incluso si se trata de fragmentación). Tienes que recordar, todos memoria virtual, y todos memoria física son bestias diferentes.

(Lo siguiente está escrito para Linux, pero probablemente es aplicable a Windows y OSX)

Cuando el programa hace que las primeras asignaciones, digamos que hay suficiente memoria física para el sistema operativo para exprimir todas las páginas. No están todos uno al lado del otro en la memoria física, están dispersos donde sea que puedan estar. A continuación, el sistema operativo modifica la tabla de páginas para crear un conjunto de direcciones continuas virtuales, que hacen referencia a las páginas dispersas en la memoria. Pero esta es la cuestión: porque realmente no usas la primera memoria que asignas, se convierte en un buen candidato para intercambiar. Entonces, cuando vengas a hacer las próximas asignaciones, el sistema operativo que se está quedando sin memoria probablemente cambie algunas de esas páginas para dejar sitio a las nuevas. Debido a esto, en realidad está midiendo las velocidades de disco y la eficiencia del mecanismo de búsqueda de sistemas de operaciones, no la fragmentación.

Recuerde, un conjunto de direcciones virtuales continuas casi nunca es físicamente continuo en la práctica (o incluso en la memoria).

Cuestiones relacionadas