Source code for skneuromsi.utils.memtools

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# This file is part of the
#   Scikit-NeuroMSI Project (https://github.com/renatoparedes/scikit-neuromsi).
# Copyright (c) 2021-2025, Renato Paredes; Cabral, Juan
# License: BSD 3-Clause
# Full Text:
#     https://github.com/renatoparedes/scikit-neuromsi/blob/main/LICENSE.txt

# =============================================================================
# DOCS
# =============================================================================

"""
Memory usage and impact analysis tools.

This module provides classes and functions to calculate and represent memory
usage and impact of Python objects.
"""

# =============================================================================
# IMPORTS
# =============================================================================

import dataclasses as dclss

import humanize

import psutil

from pympler import asizeof


# =============================================================================
# MEMORY USAGE
# =============================================================================


@dclss.dataclass(frozen=True)
class _MemoryUsage:
    """
    Dataclass representing memory usage.

    Parameters
    ----------
    size : int
        The size of the memory usage in bytes.

    Attributes
    ----------
    size : int
        The size of the memory usage in bytes.
    hsize : str
        The human-readable string representation of the memory usage size.
    """

    size: int

    @property
    def hsize(self):
        """
        Get the human-readable string representation of the memory usage size.

        Returns
        -------
        str
            Human-readable string representation of the memory usage size.
        """
        return humanize.naturalsize(self.size)

    def __repr__(self):
        return f"<memusage {self.hsize!r}>"


[docs] def memory_usage(obj): """ Calculate the memory usage of an object. Parameters ---------- obj : object The object to calculate memory usage for. Returns ------- _MemoryUsage An instance of _MemoryUsage containing the calculated memory size. """ size = asizeof.asizeof(obj) return _MemoryUsage(size=size)
# ============================================================================= # MEMORY IMPACT # ============================================================================= @dclss.dataclass(frozen=True, slots=True) class _MemoryImpact: """Dataclass representing memory impact. Parameters ---------- expected_size : int The expected size of the memory impact in bytes. vmem : object The virtual memory object. """ expected_size: int vmem: object @property def total_ratio(self): """Get the ratio of the expected size to the total memory.""" return self.expected_size / self.vmem.total @property def available_ratio(self): """Get the ratio of the expected size to the available memory.""" return self.expected_size / self.vmem.available @property def hexpected_size(self): """Get the human-readable representation of the expected size.""" return humanize.naturalsize(self.expected_size) @property def havailable_memory(self): """Get the human-readable representation of the available memory.""" return humanize.naturalsize(self.vmem.available) @property def htotal_memory(self): """Get the human-readable string representation of the total memory.""" return humanize.naturalsize(self.vmem.total) def __repr__(self): """Return a string representation of the MemoryImpact object.""" return ( f"<memimpact expected_size={self.hexpected_size!r}, " f"total_ratio={self.total_ratio}, " f"available_ratio={self.available_ratio}>" )
[docs] def memory_impact(obj, *, size_factor=1, num_objects=1): """Calculate the memory impact of an object. Parameters ---------- obj : object The object to calculate memory impact for. num_objects : int, optional Number of objects to consider (default is 1). size_factor : float, optional Factor to multiply the expected size by (default is 1). Size factor is a factor to multiply the expected size by. It is assumed that most objects are a little bigger or smaller than the expected size. For example, if `size_factor=1.2` then the expected size is multiplied by 1.2, this means that most objects will be 20% bigger than the expected size. If `size_factor=0.75` then most objects will be 35% smaller. Returns ------- _MemoryImpact An instance of _MemoryImpact containing the calculated impact metrics. """ if size_factor < 0: raise ValueError("size_factor must be a positive value") # the size of the object in the memory obj_memory = memory_usage(obj) # the expected size of the "num_objects" object in the memory # based on the size factor and the number of objects expected_size = num_objects * obj_memory.size * size_factor vmem = psutil.virtual_memory() return _MemoryImpact( expected_size=expected_size, vmem=vmem, )