2011-07-11 11 views
6

Haciendo algunos perfiles (mem & de velocidad) Me ha picado el hecho de que win7 parece estar asignando exactamente el doble de RAM que pido ... Tenga en cuenta que este es el primero vez que realizo un perfil tan activo en win7, entonces realmente no sé qué esperar.asignando ram muestra el doble de uso de RAM en el administrador de tareas

Estoy asignando cantidades precisas de RAM en un bucle utilizando una edición expresa de MSVC en win7 (64 bits). La aplicación está compilada y se ejecuta en 32 bits.

Asigné 24 MB de memoria RAM y el administrador de tareas muestra que mi aplicación usa 48MB (en todas las columnas de memoria, incluido el cometido, ya que en realidad estoy copiando en las nuevas regiones). Cuando obtenga 24 más (ahora debería ser 48MB), mi aplicación salta a 96, etc.

Se asignan como 1,000,000 de estructuras de 24 bytes.

He buscado en la red pero no he encontrado nada que coincida exactamente con mis observaciones.

¿Alguien tiene una pista?

Si esto es solo un truco del sistema operativo (¿o incompetencia?), ¿Hay alguna herramienta que pueda darme el consumo real de memoria de un proceso? (es difícil encontrar fugas, cuando la aplicación brota para comenzar ;-)

[----------- editado, información adicional -----------]

Nota (por la ruta en la barra de título de la consola) que estoy construyendo en modo Release (utilizando todas las configuraciones de proyecto "vacías" de MSVC 2010), por lo que no se asigna memoria de "depuración" (que puede ser bastante extenso en algunos proyectos).

aquí es una aplicación de C corta, completa, que ilustra el comportamiento:

#include <stdio.h> 
#include <assert.h> 
#include <conio.h> 
#include <stdlib.h> 
typedef unsigned int u32; 
typedef struct myStruct MYS; 
struct myStruct { 
    u32 type; 
    union { 
     u32 value; 
     char * str; 
     void * data; 
     MYS ** block; 
     MYS * plug; 
    }; 
    u32 state, msg, count, index; 
}; 
int main(int argc, char *argv[]){ 
    int i, j; 
    MYS *ref; 
    printf ("size of myStruct: %d\n\n", sizeof(MYS)); 
    for(i=0; i < 10; i ++){ 
     printf("allocating started...\n"); 
     for (j = 0; j < 1000000 ; j ++){ 
      ref = (MYS *) malloc(sizeof(MYS)); 
      assert(ref); 
      memset(ref, 0, sizeof(MYS)); 
     } 
     printf(" Done... Press 'enter' for Next Batch\n"); 
     _getch(); 
    } 
    _getch(); 
    return 0; 
} 

y una imagen que muestra la memoria en mi máquina después de un bucle. Cada dos ejecuciones, ¡agrega ~ 48MB en vez de 24MB!

process info after 1 loop (should be ~24MB)

+2

¿Puedes mostrar la línea donde asignas la memoria? –

+6

¿Estás seguro de que struct tiene realmente 24 bytes? Puede haber una alineación pasando que lo rellena. – davin

+0

Pregunta editada ... Agregué un ejemplo de código completo con detalles de construcción adicionales y una imagen de mi administrador de tareas después de un ciclo. Espero que esto ayude :-) – moliad

Respuesta

3

Esto se debe probablemente a una combinación de relleno, estructuras de organización interna, y las restricciones de alineación de memoria.

Cuando invoque malloc(size), no obtendrá realmente un búfer de size bytes. Obtiene un búfer que es al menos de size bytes. Esto se debe a que, por razones de eficiencia, su sistema operativo prefiere administrar memorias intermedias de memoria en solo un par de tamaños diferentes y no personalizará los búferes para ahorrar espacio. Por ejemplo, si pides 24 bytes en Mac OS, obtendrás un buffer de 32 bytes (un desperdicio de 25%).

Agregue a esa sobrecarga de asignación las estructuras que su SO usa para administrar malloc búferes ed (probablemente contando unos pocos bytes adicionales por asignación), y el hecho de que el relleno puede aumentar el tamaño de su objeto (a un múltiplo del compilador alineación preferida), y verá que la asignación de millones de objetos pequeños en memorias intermedias individuales es muy costosa.

Resumen de la historia larga: asigne solo un búfer grande de sizeof (YourType) * 1000000 y no debería ver ninguna sobrecarga perceptible. Asigne un millón de objetos sizeof (YourType), y terminará desperdiciando mucho espacio.

+0

gracias, ¿así que debería implementar mis propios asignadores agrupados (eficientes en memoria) para estas estructuras? Manejaré millones de estas pequeñas estructuras. algo que asigna un número n a la vez y luego mantiene un registro de cuánto le queda antes de que se requiera la siguiente asignación (y viceversa para la liberación). – moliad

+0

Sí, si necesita manejar muchas y pequeñas asignaciones, debe crear un asignador que use 'malloc' para reservar grandes porciones de memoria a la vez. – zneak

+0

Por cierto, hice bastantes pruebas y parece que todas las llamadas de malloc en mi casilla win7 agregan 20-30 bytes adicionales (promedio basado en millones de allocs de diferentes tamaños). así que supongo que el asignador del sistema está bastante hambriento de memoria (tiene muchos valores que rastrea para cualquier asignación dada). – moliad

0

malloc no es un servicio del sistema operativo en Windows, sino que es implementado por su compilador. Puede tener su propia estrategia de asignación, como lo indica la otra respuesta, y a menudo se construye sobre el HeapAlloc que tiene algunos gastos generales propios.

Llame al VirtualAlloc si desea asignar un número específico de páginas.

Cuestiones relacionadas