¿Cómo determino el tamaño de un objeto en Python?

682

Quiero saber cómo obtener el tamaño de los objetos como una cadena, un entero, etc. en Python.

Pregunta relacionada: ¿Cuántos bytes por elemento hay en una lista de Python (tupla)?

Estoy usando un archivo XML que contiene campos de tamaño que especifican el tamaño del valor. Debo analizar este XML y hacer mi codificación. Cuando quiero cambiar el valor de un campo en particular, comprobaré el campo de tamaño de ese valor. Aquí quiero comparar si el nuevo valor que voy a ingresar es del mismo tamaño que en XML. Necesito verificar el tamaño del nuevo valor. En caso de una cadena, puedo decir que es la longitud. Pero en caso de int, float, etc. Estoy confundido.

usuario46646
fuente

Respuestas:

665

Simplemente use la función sys.getsizeof definida en el sysmódulo.

sys.getsizeof(object[, default]):

Devuelve el tamaño de un objeto en bytes. El objeto puede ser cualquier tipo de objeto. Todos los objetos integrados devolverán resultados correctos, pero esto no tiene que ser cierto para extensiones de terceros, ya que es específico de la implementación.

El defaultargumento permite definir un valor que se devolverá si el tipo de objeto no proporciona medios para recuperar el tamaño y causaría a TypeError.

getsizeofllama al __sizeof__método del objeto y agrega una sobrecarga adicional al recolector de basura si el objeto es administrado por el recolector de basura.

Ejemplo de uso, en python 3.0:

>>> import sys
>>> x = 2
>>> sys.getsizeof(x)
24
>>> sys.getsizeof(sys.getsizeof)
32
>>> sys.getsizeof('this')
38
>>> sys.getsizeof('this also')
48

Si está en python <2.6 y no lo tiene sys.getsizeof, puede usar este extenso módulo en su lugar. Aunque nunca lo usé.

nosklo
fuente
181
Agregue al descargo de responsabilidad que no será válido para objetos anidados o dictados anidados o dictados en listas, etc.
JohnnyM
8
¡@ChaimG es porque cada objeto solo usa 32 bytes! El resto son referencias a otros objetos. Si desea dar cuenta de los objetos referenciados, debe definir el __sizeof__método para su clase. La dictclase python incorporada lo define, es por eso que obtienes el resultado correcto cuando usas un objeto de tipo dict.
nosklo
19
El descargo de responsabilidad y las excepciones a este trabajo cubren casi todos los casos de uso, lo que hace que la getsizeoffunción de poco valor fuera de la caja.
Robino
77
¿Por qué el entero 2 se almacena en 24 bytes?
Saher Ahwal
44
@SaherAhwal no es solo un número entero, sino un objeto completo con métodos, atributos, direcciones ...
nosklo 20/0318
369

¿Cómo determino el tamaño de un objeto en Python?

La respuesta, "Solo use sys.getsizeof" no es una respuesta completa.

Esa respuesta hace el trabajo de orden interna se opone directamente, pero no tiene en cuenta lo que esos objetos pueden contener, en concreto, qué tipos, tales como objetos personalizados, tuplas, listas, predice y conjuntos contienen. Pueden contener instancias entre sí, así como números, cadenas y otros objetos.

Una respuesta más completa

Utilizando Python 3.6 de 64 bits de la distribución Anaconda, con sys.getsizeof, he determinado el tamaño mínimo de los siguientes objetos, y noto que los conjuntos y los dictos preasignan el espacio para que los vacíos no vuelvan a crecer hasta después de una cantidad establecida (que puede variar según la implementación del idioma):

Python 3:

Empty
Bytes  type        scaling notes
28     int         +4 bytes about every 30 powers of 2
37     bytes       +1 byte per additional byte
49     str         +1-4 per additional character (depending on max width)
48     tuple       +8 per additional item
64     list        +8 for each additional
224    set         5th increases to 736; 21nd, 2272; 85th, 8416; 341, 32992
240    dict        6th increases to 368; 22nd, 1184; 43rd, 2280; 86th, 4704; 171st, 9320
136    func def    does not include default args and other attrs
1056   class def   no slots 
56     class inst  has a __dict__ attr, same scaling as dict above
888    class def   with slots
16     __slots__   seems to store in mutable tuple-like structure
                   first slot grows to 48, and so on.

como interpretas esto? Bueno, digamos que tienes un conjunto con 10 elementos. Si cada elemento tiene 100 bytes cada uno, ¿qué tan grande es la estructura de datos completa? El conjunto es 736 en sí porque se ha dimensionado una vez a 736 bytes. Luego agrega el tamaño de los elementos, por lo que son 1736 bytes en total

Algunas advertencias para las definiciones de función y clase:

Tenga en cuenta que cada definición de clase tiene una __dict__estructura proxy (48 bytes) para los atributos de clase. Cada ranura tiene un descriptor (como a property) en la definición de clase.

Las instancias ranuradas comienzan con 48 bytes en su primer elemento y aumentan en 8 cada una adicional. Solo los objetos ranurados vacíos tienen 16 bytes, y una instancia sin datos tiene muy poco sentido.

Además, cada definición de función tiene objetos de código, tal vez cadenas de documentos y otros posibles atributos, incluso a __dict__.

También tenga en cuenta que usamos sys.getsizeof()porque nos importa el uso del espacio marginal, que incluye la sobrecarga de recolección de basura para el objeto, de los documentos :

getsizeof () llama al __sizeof__método del objeto y agrega una sobrecarga adicional al recolector de basura si el objeto es administrado por el recolector de basura.

También tenga en cuenta que cambiar el tamaño de las listas (por ejemplo, agregarlas repetidamente) hace que preasignen espacio, de manera similar a los conjuntos y los dictados. Del código fuente listobj.c :

    /* This over-allocates proportional to the list size, making room
     * for additional growth.  The over-allocation is mild, but is
     * enough to give linear-time amortized behavior over a long
     * sequence of appends() in the presence of a poorly-performing
     * system realloc().
     * The growth pattern is:  0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
     * Note: new_allocated won't overflow because the largest possible value
     *       is PY_SSIZE_T_MAX * (9 / 8) + 6 which always fits in a size_t.
     */
    new_allocated = (size_t)newsize + (newsize >> 3) + (newsize < 9 ? 3 : 6);

Información histórica

Análisis de Python 2.7, confirmado con guppy.hpyy sys.getsizeof:

Bytes  type        empty + scaling notes
24     int         NA
28     long        NA
37     str         + 1 byte per additional character
52     unicode     + 4 bytes per additional character
56     tuple       + 8 bytes per additional item
72     list        + 32 for first, 8 for each additional
232    set         sixth item increases to 744; 22nd, 2280; 86th, 8424
280    dict        sixth item increases to 1048; 22nd, 3352; 86th, 12568 *
120    func def    does not include default args and other attrs
64     class inst  has a __dict__ attr, same scaling as dict above
16     __slots__   class with slots has no dict, seems to store in 
                   mutable tuple-like structure.
904    class def   has a proxy __dict__ structure for class attrs
104    old class   makes sense, less stuff, has real dict though.

Tenga en cuenta que los diccionarios ( pero no los conjuntos ) tienen una representación más compacta en Python 3.6

Creo que 8 bytes por elemento adicional de referencia tiene mucho sentido en una máquina de 64 bits. Esos 8 bytes apuntan al lugar en la memoria donde está el elemento contenido. Los 4 bytes son de ancho fijo para Unicode en Python 2, si recuerdo correctamente, pero en Python 3, str se convierte en un Unicode de ancho igual al ancho máximo de los caracteres.

(Y para más información sobre tragamonedas, vea esta respuesta )

Una función más completa

Queremos una función que busque los elementos en listas, tuplas, conjuntos, dictos, obj.__dict__'s' y obj.__slots__otras cosas en las que aún no hemos pensado.

Queremos confiar en gc.get_referentshacer esta búsqueda porque funciona en el nivel C (lo que lo hace muy rápido). La desventaja es que get_referents puede devolver miembros redundantes, por lo que debemos asegurarnos de no contar dos veces.

Las clases, los módulos y las funciones son singletons: existen una vez en la memoria. No estamos tan interesados ​​en su tamaño, ya que no hay mucho que podamos hacer al respecto, son parte del programa. Así que evitaremos contarlos si se hace referencia a ellos.

Vamos a utilizar una lista negra de tipos para no incluir todo el programa en nuestro recuento de tamaños.

import sys
from types import ModuleType, FunctionType
from gc import get_referents

# Custom objects know their class.
# Function objects seem to know way too much, including modules.
# Exclude modules as well.
BLACKLIST = type, ModuleType, FunctionType


def getsize(obj):
    """sum size of object & members."""
    if isinstance(obj, BLACKLIST):
        raise TypeError('getsize() does not take argument of type: '+ str(type(obj)))
    seen_ids = set()
    size = 0
    objects = [obj]
    while objects:
        need_referents = []
        for obj in objects:
            if not isinstance(obj, BLACKLIST) and id(obj) not in seen_ids:
                seen_ids.add(id(obj))
                size += sys.getsizeof(obj)
                need_referents.append(obj)
        objects = get_referents(*need_referents)
    return size

Para contrastar esto con la siguiente función incluida en la lista blanca, la mayoría de los objetos saben cómo atravesarse para la recolección de basura (que es aproximadamente lo que estamos buscando cuando queremos saber qué tan caros en memoria son ciertos objetos. Esta funcionalidad es utilizada por gc.get_referents.) Sin embargo, esta medida tendrá un alcance mucho más amplio de lo que pretendíamos si no tenemos cuidado.

Por ejemplo, las funciones saben bastante sobre los módulos en los que se crean.

Otro punto de contraste es que las cadenas que son claves en los diccionarios generalmente están internadas para que no se dupliquen. La verificación id(key)también nos permitirá evitar contar duplicados, lo que hacemos en la siguiente sección. La solución de la lista negra omite las teclas de conteo que son cadenas por completo.

Tipos incluidos en la lista blanca, visitante recursivo (implementación anterior)

Para cubrir la mayoría de estos tipos, en lugar de depender del módulo gc, escribí esta función recursiva para tratar de estimar el tamaño de la mayoría de los objetos de Python, incluidos la mayoría de los elementos incorporados, los tipos en el módulo de colecciones y los tipos personalizados (ranurado y de otro modo) .

Este tipo de función proporciona un control mucho más detallado sobre los tipos que vamos a contar para el uso de la memoria, pero tiene el peligro de omitir los tipos:

import sys
from numbers import Number
from collections import Set, Mapping, deque

try: # Python 2
    zero_depth_bases = (basestring, Number, xrange, bytearray)
    iteritems = 'iteritems'
except NameError: # Python 3
    zero_depth_bases = (str, bytes, Number, range, bytearray)
    iteritems = 'items'

def getsize(obj_0):
    """Recursively iterate to sum size of object & members."""
    _seen_ids = set()
    def inner(obj):
        obj_id = id(obj)
        if obj_id in _seen_ids:
            return 0
        _seen_ids.add(obj_id)
        size = sys.getsizeof(obj)
        if isinstance(obj, zero_depth_bases):
            pass # bypass remaining control flow and return
        elif isinstance(obj, (tuple, list, Set, deque)):
            size += sum(inner(i) for i in obj)
        elif isinstance(obj, Mapping) or hasattr(obj, iteritems):
            size += sum(inner(k) + inner(v) for k, v in getattr(obj, iteritems)())
        # Check for custom object instances - may subclass above too
        if hasattr(obj, '__dict__'):
            size += inner(vars(obj))
        if hasattr(obj, '__slots__'): # can have __slots__ with __dict__
            size += sum(inner(getattr(obj, s)) for s in obj.__slots__ if hasattr(obj, s))
        return size
    return inner(obj_0)

Y lo probé de manera bastante informal (debería probarlo unitariamente):

>>> getsize(['a', tuple('bcd'), Foo()])
344
>>> getsize(Foo())
16
>>> getsize(tuple('bcd'))
194
>>> getsize(['a', tuple('bcd'), Foo(), {'foo': 'bar', 'baz': 'bar'}])
752
>>> getsize({'foo': 'bar', 'baz': 'bar'})
400
>>> getsize({})
280
>>> getsize({'foo':'bar'})
360
>>> getsize('foo')
40
>>> class Bar():
...     def baz():
...         pass
>>> getsize(Bar())
352
>>> getsize(Bar().__dict__)
280
>>> sys.getsizeof(Bar())
72
>>> getsize(Bar.__dict__)
872
>>> sys.getsizeof(Bar.__dict__)
280

Esta implementación desglosa las definiciones de clase y las definiciones de función porque no buscamos todos sus atributos, pero dado que solo deberían existir una vez en la memoria para el proceso, su tamaño realmente no importa demasiado.

Aaron Hall
fuente
55
Puede agregar que esta respuesta es específica de CPython (lo que está implícito al obtener Python a través de Anaconda)
gerrit
1
CPython es la implementación de referencia, y acabo de revisar los documentos en línea de jython que proporcionan la misma API, por lo que creo que esto funcionará en otras implementaciones, siempre que implementen las API.
Aaron Hall
para mí no funcionó para matrices numpy enmascaradas y sin máscara stackoverflow.com/q/58675479/2132157
GM
95

El módulo del paquete Pymplerasizeof puede hacer esto.

Use de la siguiente manera:

from pympler import asizeof
asizeof.asizeof(my_object)

A diferencia sys.getsizeof, funciona para tus objetos creados por ti mismo . Incluso funciona con numpy.

>>> asizeof.asizeof(tuple('bcd'))
200
>>> asizeof.asizeof({'foo': 'bar', 'baz': 'bar'})
400
>>> asizeof.asizeof({})
280
>>> asizeof.asizeof({'foo':'bar'})
360
>>> asizeof.asizeof('foo')
40
>>> asizeof.asizeof(Bar())
352
>>> asizeof.asizeof(Bar().__dict__)
280
>>> A = rand(10)
>>> B = rand(10000)
>>> asizeof.asizeof(A)
176
>>> asizeof.asizeof(B)
80096

Como se mencionó ,

El tamaño del código (byte) de los objetos como clases, funciones, métodos, módulos, etc. se puede incluir mediante la configuración de la opción code=True.

Y si necesita otra vista de datos en vivo, Pympler's

El módulo muppyse utiliza para la supervisión en línea de una aplicación Python y el módulo Class Trackerproporciona análisis fuera de línea de la vida útil de los objetos Python seleccionados.

serv-inc
fuente
Esta función es bastante lenta para objetos más grandes. ¿Existe un equivalente "rápido" que funcione para objetos creados por uno mismo?
Shuklaswag
Todavía no lo he probado, pero org.apache.spark.util.SizeEstimatorpuede ser relevante
Shuklaswag
1
@Shuklaswag: si usas chispa, bien podría ser. ¿Crees que la conversión + estimación de Java es más rápida que los métodos integrados de Python? ¿O entendí mal?
serv-inc
3
Vale la pena señalar que pymplertiene la capacidad de tener en cuenta el tamaño del código ejecutable de las funciones y otras llamadas y objetos de código.
mtraceur
Recibo una TypeErrorexcepción: "el objeto 'NoneType' no es invocable" cada vez que mi objeto personalizado tiene algún subobjeto en su "árbol" con valor None. ¿Hay alguna solución rápida para esto?
James Hirschorn
81

Para matrices numpy, getsizeofno funciona, para mí siempre devuelve 40 por alguna razón:

from pylab import *
from sys import getsizeof
A = rand(10)
B = rand(10000)

Entonces (en ipython):

In [64]: getsizeof(A)
Out[64]: 40

In [65]: getsizeof(B)
Out[65]: 40

Felizmente, sin embargo:

In [66]: A.nbytes
Out[66]: 80

In [67]: B.nbytes
Out[67]: 80000
Mike Dewar
fuente
29
> Todos los objetos integrados devolverán resultados correctos, pero esto no tiene que ser cierto para extensiones de terceros, ya que es específico de la implementación. docs.python.org/library/sys.html#sys.getsizeof
warvariuc
33
"Si está utilizando una matriz numpy ( docs.scipy.org/doc/numpy/reference/arrays.ndarray.html ), puede usar el atributo 'ndarray.nbytes' para evaluar su tamaño en la memoria". stackoverflow.com/a/15591157/556413
glarrain
17
Supongo que 40 bytes son correctos, sin embargo, getsizeof()solo le da el tamaño del objeto (el encabezado de la matriz), no de los datos que contiene. Lo mismo para los contenedores de python donde sys.getsizeof([1,2,4]) == sys.getsizeof([1,123**456,4]) == 48, mientras quesys.getsizeof(123**456) = 436
yota
3
Parece que la getsizeof()función se cambió en algún momento para devolver el valor esperado.
dshin
14

Esto puede ser más complicado de lo que parece dependiendo de cómo desee contar las cosas. Por ejemplo, si tiene una lista de entradas, ¿desea el tamaño de la lista que contiene las referencias a las entradas? (es decir, solo una lista, no lo que contiene), o desea incluir los datos reales señalados, en cuyo caso debe tratar con referencias duplicadas y cómo evitar el doble recuento cuando dos objetos contienen referencias a El mismo objeto.

Es posible que desee echar un vistazo a uno de los perfiladores de memoria de Python, como pysizer, para ver si satisfacen sus necesidades.

Brian
fuente
14

Python 3.8 (Q1 2019) cambiará algunos de los resultados de sys.getsizeof, según lo anunciado por Raymond Hettinger:

Los contenedores de Python son 8 bytes más pequeños en las compilaciones de 64 bits.

tuple ()  48 -> 40       
list  []  64 ->56
set()    224 -> 216
dict  {} 240 -> 232

Esto viene después del problema 33597 y el trabajo de Inada Naoki ( methane) en torno a Compact PyGC_Head y PR 7043

Esta idea reduce el tamaño de PyGC_Head a dos palabras .

Actualmente, PyGC_Head toma tres palabras ; gc_prev, gc_nextY gc_refcnt.

  • gc_refcnt se utiliza al recopilar, para la eliminación de prueba.
  • gc_prev Se utiliza para el seguimiento y el seguimiento.

Entonces, si podemos evitar el seguimiento / no seguimiento durante la eliminación de prueba, gc_prevy gc_refcntpodemos compartir el mismo espacio de memoria.

Ver commit d5c875b :

Eliminado un Py_ssize_tmiembro de PyGC_Head.
El tamaño de todos los objetos rastreados por GC (por ejemplo, tupla, lista, dict) se reduce en 4 u 8 bytes.

VonC
fuente
10

Habiendo encontrado este problema muchas veces, escribí una pequeña función (inspirada en la respuesta de @ aaron-hall) y pruebas que hacen lo que esperaba que hiciera sys.getsizeof:

https://github.com/bosswissam/pysize

Si estás interesado en la historia de fondo, aquí está

EDITAR: Adjuntando el siguiente código para una fácil referencia. Para ver el código más actualizado, consulte el enlace de github.

    import sys

    def get_size(obj, seen=None):
        """Recursively finds size of objects"""
        size = sys.getsizeof(obj)
        if seen is None:
            seen = set()
        obj_id = id(obj)
        if obj_id in seen:
            return 0
        # Important mark as seen *before* entering recursion to gracefully handle
        # self-referential objects
        seen.add(obj_id)
        if isinstance(obj, dict):
            size += sum([get_size(v, seen) for v in obj.values()])
            size += sum([get_size(k, seen) for k in obj.keys()])
        elif hasattr(obj, '__dict__'):
            size += get_size(obj.__dict__, seen)
        elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes, bytearray)):
            size += sum([get_size(i, seen) for i in obj])
        return size
wissam
fuente
7

Aquí hay un script rápido que escribí basado en las respuestas anteriores para enumerar los tamaños de todas las variables

for i in dir():
    print (i, sys.getsizeof(eval(i)) )
alexey
fuente
No está mal, es ambiguo. sys.getsizeof siempre devolverá el valor necesario, por lo que no es necesario perder rendimiento con try..except.
der_fenix
oh, ese es un buen punto y no lo pensé, el código en la forma en que está ahora solo muestra cómo fue escrito cronológicamente, primero supe sobre numpy (por lo tanto, nbytes), luego busqué una solución más genérica . Gracias por la explicación _ / \ _
alexey
7

Puede serializar el objeto para derivar una medida que esté estrechamente relacionada con el tamaño del objeto:

import pickle

## let o be the object, whose size you want to measure
size_estimate = len(pickle.dumps(o))

Si desea medir objetos que no se pueden encurtir (por ejemplo, debido a expresiones lambda), cloudpickle puede ser una solución.

Alguien
fuente
4

Use sys.getsizeof () si NO desea incluir tamaños de objetos vinculados (anidados).

Sin embargo, si desea contar los subobjetos anidados en listas, dictados, conjuntos, tuplas, y generalmente ESTO es lo que está buscando, use la función recursiva deep sizeof () como se muestra a continuación:

import sys
def sizeof(obj):
    size = sys.getsizeof(obj)
    if isinstance(obj, dict): return size + sum(map(sizeof, obj.keys())) + sum(map(sizeof, obj.values()))
    if isinstance(obj, (list, tuple, set, frozenset)): return size + sum(map(sizeof, obj))
    return size

También puede encontrar esta función en la ingeniosa caja de herramientas, junto con muchas otras frases útiles útiles:

https://github.com/mwojnars/nifty/blob/master/util.py

Marcin Wojnarski
fuente
3

Si no necesita el tamaño exacto del objeto, pero aproximadamente para saber qué tan grande es, una forma rápida (y sucia) es dejar que el programa se ejecute, dormir durante un período prolongado de tiempo y verificar el uso de la memoria (ej. : Monitor de actividad de Mac) por este proceso particular de Python. Esto sería efectivo cuando intente encontrar el tamaño de un solo objeto grande en un proceso de Python. Por ejemplo, recientemente quería verificar el uso de la memoria de una nueva estructura de datos y compararlo con el de la estructura de datos establecida de Python. Primero escribí los elementos (palabras de un gran libro de dominio público) en un conjunto, luego verifiqué el tamaño del proceso y luego hice lo mismo con la otra estructura de datos. Descubrí que el proceso de Python con un conjunto está tomando el doble de memoria que la nueva estructura de datos. De nuevo, no lo harías No podrá decir exactamente que la memoria utilizada por el proceso es igual al tamaño del objeto. A medida que el tamaño del objeto aumenta, esto se reduce a medida que la memoria consumida por el resto del proceso se vuelve insignificante en comparación con el tamaño del objeto que está tratando de monitorear.

picmate 涅
fuente
1
La pregunta pregunta cómo hacerlo en python , no solo para encontrar el uso de memoria de los objetos de python, y usar un monitor de actividad de Mac o cualquier otro software similar no está usando python mediante programación. Dicho esto, verificar el uso de memoria de los procesos de Python de esta manera generalmente es una buena manera de asegurarse de que nada haya salido mal ...
Tom Wyllie
@TomWyllie, gracias, pero rechazar esta respuesta conlleva la connotación negativa de que la respuesta en sí misma es incorrecta y no logra nada. El método que menciono podría no implementarse en Python, pero es una forma práctica de obtener una estimación aproximada del tamaño de un objeto Python. Sabía que no estaba respondiendo la pregunta exacta, sin embargo, el método podría ser útil para que otra persona obtenga un resultado similar.
picmate 涅
1

Puede utilizar getSizeof () como se menciona a continuación para determinar el tamaño de un objeto

import sys
str1 = "one"
int_element=5
print("Memory size of '"+str1+"' = "+str(sys.getsizeof(str1))+ " bytes")
print("Memory size of '"+ str(int_element)+"' = "+str(sys.getsizeof(int_element))+ " bytes")
tenedor
fuente
0

Utilizo este truco ... May no será preciso en objetos pequeños, pero creo que es mucho más preciso para un objeto complejo (como la superficie de un juego de cartas) en lugar de sys.getsizeof ()

import pygame as pg
import os
import psutil
import time


process = psutil.Process(os.getpid())
pg.init()    
vocab = ['hello', 'me', 'you', 'she', 'he', 'they', 'we',
         'should', 'why?', 'necessarily', 'do', 'that']

font = pg.font.SysFont("monospace", 100, True)

dct = {}

newMem = process.memory_info().rss  # don't mind this line
Str = f'store ' + f'Nothing \tsurface use about '.expandtabs(15) + \
      f'0\t bytes'.expandtabs(9)  # don't mind this assignment too

usedMem = process.memory_info().rss

for word in vocab:
    dct[word] = font.render(word, True, pg.Color("#000000"))

    time.sleep(0.1)  # wait a moment

    # get total used memory of this script:
    newMem = process.memory_info().rss
    Str = f'store ' + f'{word}\tsurface use about '.expandtabs(15) + \
          f'{newMem - usedMem}\t bytes'.expandtabs(9)

    print(Str)
    usedMem = newMem

En mi Windows 10, Python 3.7.3, el resultado es:

store hello          surface use about 225280    bytes
store me             surface use about 61440     bytes
store you            surface use about 94208     bytes
store she            surface use about 81920     bytes
store he             surface use about 53248     bytes
store they           surface use about 114688    bytes
store we             surface use about 57344     bytes
store should         surface use about 172032    bytes
store why?           surface use about 110592    bytes
store necessarily    surface use about 311296    bytes
store do             surface use about 57344     bytes
store that           surface use about 110592    bytes
Hzzkygcs
fuente