2009-08-13 18 views
9

me preguntaba cuánta memoria hace un objeto que hereda de "objeto" y no tiene campos/propiedades toman? Y creo que los métodos no. Correcto ? Estoy hablando de objetos .net.memoria tomada de un objeto C#

+0

Buena pregunta. Yo diría crear algunos millones de ellos y ver la diferencia de memoria antes y después. A menos que alguien ya haya hecho esto. –

+0

Es por eso que pregunté. Necesitaba saber el uso de memoria de la aplicación con millones de objetos. Entonces la respuesta para la aplicación de 32 bits es el tamaño de todos los campos +8 bytes. –

Respuesta

11

bien, ya que tanto Andrés y Guffa han dado respuestas que yo creo que está mal ...

Hay una sobrecarga de 8 bytes para todos los objetos (en 86), pero hay también un tamaño mínimo de 12 bytes. No sé por qué ... pero significa que estas dos clases tanto toman 12 bytes por ejemplo:

public class OneField 
{ 
    private int field; 
} 

public class NoFields 
{ 
} 

prueba:

using System; 

public class OneField 
{ 
    private int field; 
} 

public class NoFields {} 

public class Test 
{ 
    static void Main(string[] args) 
    { 
     int size = int.Parse(args[0]); 
     switch (args[1]) 
     { 
      case "NoFields": 
       TestNoFields(size); 
       break; 
      case "OneField": 
       TestOneField(size); 
       break; 
     } 
    } 

    static void TestNoFields(int size) 
    { 
     NoFields[] array = new NoFields[size]; 
     long start = GC.GetTotalMemory(true); 
     for (int i=0; i < size; i++) 
     { 
      array[i] = new NoFields(); 
     } 
     long end = GC.GetTotalMemory(true); 
     GC.KeepAlive(array); 
     Console.WriteLine("Size per instance: {0}", 
          (end-start)/(double)size); 
    } 

    static void TestOneField(int size) 
    { 
     OneField[] array = new OneField[size]; 
     long start = GC.GetTotalMemory(true); 
     for (int i=0; i < size; i++) 
     { 
      array[i] = new OneField(); 
     } 
     long end = GC.GetTotalMemory(true); 
     GC.KeepAlive(array); 
     Console.WriteLine("Size per instance: {0}", 
          (end-start)/(double)size); 
    } 
} 

Esto es feo porque no he deliberadamente ido para cualquier tipo genérico o cualquier otra cosa que pueda causar problemas. Algunas pruebas de funcionamiento:

>test 1000000 NoFields 
Size per instance: 12.000024 
>test 1000000 OneField 
Size per instance: 12.000024 
>test 1000 NoFields 
Size per instance: 12 
>test 1000 OneField 
Size per instance: 12 

(JITting sobrecarga etc explica por qué el número no es siempre un número entero exacto - por lo tanto, por qué hago la división en coma flotante.)

de pruebas con un int adicional muestra de campo el uso va hasta 16, lo que demuestra que en realidad está haciendo algo sensato :)

+0

Buen punto sobre el mínimo de 12 bytes, pero creo que el espíritu de la pregunta se refería exactamente a qué información es "heredada" de 'System.Object'. Sin embargo, tienes razón de que en x86, el primer campo es "libre", por así decirlo, pero sin la sobrecarga de 'System.Object', los primeros 3 campos podrían haber sido gratis :) Aún así, +1 para esta importante distinción. –

0

La única cabeza que incurriría con un tipo de referencia sería de 4 bytes para el puntero del tipo de objeto y 4 bytes para el índice de bloques de sincronización.

Así que en total, 8 bytes de sobrecarga.

3

un objeto tiene dos referencias/punteros adicionales para que sus propios datos.

Así, en un sistema de 32 bits del objeto tomaría 8 bytes, en un sistema de 64 bits que tomaría 16 bytes.

Corrección:
Como dijo Jon, el tamaño mínimo para un objeto es de 12 bytes. La información que encontré hasta ahora dice que el GC requiere esto.

+4

No - hay un tamaño de objeto mínimo de 12 bytes en x86, por alguna razón, pero se obtiene el primer campo "libre" :) –

+0

De acuerdo con esta http://msdn.microsoft.com/en-us/magazine/cc163791 .aspx el GC requiere que el objeto tenga al menos 12 bytes por alguna razón. – Guffa

Cuestiones relacionadas