Python getetsof profunda lista con contenidos?

Me sorprendió que sys.getsizeof( 10000*[x] ) sea ​​40036 independientemente de x: 0, “a”, 1000 * “a”, {}.
¿Hay un deep_getsizeof que considere adecuadamente los elementos que comparten memoria?
(La pregunta surgió al observar las tablas de la base de datos en memoria como el rango (1000000) -> nombres de provincia: ¿lista o dictado)?
(Python es 2.6.4 en una ppc de mac.)

Agregado: 10000 * [“Mississippi”] es de 10000 punteros a un “Mississippi”, como han señalado varias personas. Prueba esto:

 nstates = [AlabamatoWyoming() for j in xrange(N)] 

donde AlabamatoWyoming () -> una cadena “Alabama” .. “Wyoming”. ¿Qué es deep_getsizeof (nstates)?
(¿Cómo podemos decir?

  • un deep_getsizeof adecuado: difícil, ~ gc trazador
  • estimación de vm total
  • Conocimiento interno de la implementación de Python.
  • adivinar.

Se agregó 25jan: vea también cuándo-hace-python-asigna-nueva-memoria-para-cadenas-idénticas

Echa un vistazo a guppy / heapy ; No he jugado demasiado con esto, pero algunos de mis compañeros de trabajo lo han utilizado para perfilar la memoria con buenos resultados.

La documentación podría ser mejor, pero esta guía hace un trabajo decente para explicar los conceptos básicos.

10000 * [x] producirá una lista de 10000 veces el mismo objeto , por lo que el tamaño es en realidad más cercano al correcto de lo que crees. Sin embargo, un tamaño profundo es muy problemático porque es imposible decirle a Python cuando desea detener la medición. Cada objeto hace referencia a un objeto tipográfico. ¿Debería contarse el objeto tipográfico? ¿Qué sucede si la referencia al objeto de tipo es la última, por lo que si elimina el objeto, el objeto de tipo también desaparecerá? ¿Qué pasa si tiene varios objetos (diferentes) en la lista que se refieren al mismo objeto de cadena? ¿Debe contarse una vez o varias veces?

En resumen, obtener el tamaño de una estructura de datos es muy complicado, y sys.getsizeof () nunca debería haberse agregado: S

Si la lista solo contiene objetos con la misma longitud, puede obtener un número de estimación más preciso al hacer esto

 def getSize(array): return sys.getsizeof(array) + len(array) * sys.getsizeof(array[0]) 

Obviamente no va a funcionar tan bien para cadenas con longitud variable.

Si solo desea calcular el tamaño para la depuración o durante el desarrollo y no le importa el rendimiento, puede repetir de forma recursiva todos los elementos y calcular el tamaño total. Tenga en cuenta que esta solución no va a manejar varias referencias al mismo objeto correctamente.

Escribí una herramienta llamada RememberMe exactamente para esto. Uso básico:

 from rememberme import memory a = [1, 2, 3] b = [a, a, a] print(memory(a)) # 172 bytes print(memory(b)) # 260 bytes. Duplication counted only once. 

Espero eso ayude.

mylist = 10000 * [x] significa crear una lista de tamaño 10000 con 10000 referencias al objeto x .

El objeto x no se copia , solo existe uno en la memoria.

Entonces, para usar getsizeof, sería: sys.getsizeof(mylist) + sys.getsizeof(x)