Last active
July 30, 2021 19:40
-
-
Save ZaxR/1e571968aaae93519fa1e710261286bd to your computer and use it in GitHub Desktop.
Get total memory size footprint of an object in python, in a human-readable format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# OTHER COOL FUNCS # | |
import collections | |
from itertools import chain | |
from sys import getsizeof | |
from typing import List, Optional, Tuple, Union | |
def get_scaled_units(number: Union[float, int], unit_scale_map: Optional[List[Tuple]] = None) -> str: | |
"""Scale `number` to units that result in the lowest number above 1, given a `unit_scale_map`. | |
Args: | |
number: Any number which should scaled to units. | |
unit_scale_map: Mappings of numbers to the units they reflect. | |
Order must be monotonic increasing. | |
Defaults to data storage units of measure. | |
""" | |
DEFAULT_UNIT_SCALE_MAP = [ | |
(1024 ** 0, 'B'), | |
(1024 ** 1, 'KB'), | |
(1024 ** 2, 'MB'), | |
(1024 ** 3, 'GB'), | |
(1024 ** 4, 'TB'), | |
(1024 ** 5, 'PB') | |
] | |
unit_scale_map = DEFAULT_UNIT_SCALE_MAP if not unit_scale_map else unit_scale_map | |
i = 0 | |
while number > unit_scale_map[i + 1][0] and i < len(unit_scale_map) - 1: | |
i += 1 | |
number /= unit_scale_map[i][0] | |
units = unit_scale_map[i][1] | |
return f"{round(number, 2)} {units}" | |
def get_total_size(object, human_readable=True, handlers=None): | |
"""Returns the approximate memory footprint of an object and all of its contents. | |
Useful because sys.getsizeof does not count nested objects. | |
Args: | |
object (see notes): Python object for which you want to find the size in bytes. | |
Container objects and or containers within container objects | |
are only supported for certain types. See `handlers`. | |
human_readable (bool): Determines if unit suffixes are used. Unit possibilities: | |
B (Byte), KB (Kilobyte), MB (Megabyte), GB (Gigabyte), | |
TB (Terabyte), and PB (Petabyte). Each step is 1024 of prior units. | |
handlers (dict): Instructions on how to handle container objects. | |
Default `handlers` include tuple, list, set, frozenset, and | |
collections.Mappings (such as dicts). | |
To add container types not available by default, | |
add handlers to iterate over their contents. | |
E.g. handlers={SomeContainerClass: iter, | |
OtherContainerClass: OtherContainerClass.get_elements} | |
Returns: | |
Byte size of `object` as an integer. | |
""" | |
handlers = handlers if handlers else {} | |
all_handlers = {**dict.fromkeys([tuple, list, set, frozenset], iter), | |
collections.Mapping: lambda d: chain.from_iterable(d.items())} | |
all_handlers.update(handlers) # user handlers take precedence | |
seen = set() # track which object id's have already been seen | |
default_size = getsizeof(0) # estimate size_of object without __sizeof__ | |
def size_of(object): | |
if id(object) in seen: # do not double count the same object | |
return 0 | |
seen.add(id(object)) | |
size = getsizeof(object, default_size) | |
for typ, handler in all_handlers.items(): | |
if isinstance(object, typ): | |
size += sum(map(size_of, handler(object))) | |
break | |
return size | |
size = size_of(object) | |
if human_readable: | |
return get_scaled_units(size) | |
return str(size) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment