Source code for pasteur.utils.leaks

""" Simple wrapper module that helps with finding memory leaks.

>>> from pasteur.utils.leaks import clear, check, graph
>>> clear()
>>> a = suspicious_fun()
>>> del a # remove result of function
>>> check() # prints new objects, should be empty or contain misc. python objects

Rerun a few times, if `check()` prints new objects, especially big ones, with specific
frequency, run `graph('suspicious_class')` to produce a graph of what keeps the
object in memory.

Example output of check:
```
set                     5365       +32
CategoricalDtype          72       +32
Index                     75       +31
ObjectEngine              61       +30
ReferenceType          16491       +20
slice                    154       +19
BlockPlacement            62       +19
cell                   17802       +17
method                  1105       +16
CategoricalAccessor       32       +16
CategoricalBlock          32       +16
Flags                     34       +10
Series                    30        +9
SingleBlockManager        30        +9
NumericBlock              30        +3
Int64Index                 7        +3
Int64Engine                5        +2
DataFrame                  4        +1 < suspicious, +1 per iteration
BlockManager               4        +1 < suspicious
ExtensionBlock             2        +1 < suspicious
IntegerArray               2        +1 < suspicious
```"""

import logging

def _get_obj():
    try:
        import objgraph # type: ignore
        return objgraph
    except:
        print("Module 'objgraph' is required to use this module.")
        raise

logger = logging.getLogger(__name__)


[docs] def clear(): objgraph = _get_obj() objgraph.growth()
[docs] def check(info: str): objgraph = _get_obj() result = objgraph.growth(1000) if not result: return width = max(len(name) for name, _, _ in result) for name, count, delta in result: info += "\n%-*s%9d %+9d" % (width, name, count, delta) logger.warning(info)
[docs] def graph(name: str): objgraph = _get_obj() import random from io import StringIO from urllib.parse import quote with StringIO() as output: objgraph.show_chain( objgraph.find_backref_chain( random.choice(objgraph.by_type(name)), objgraph.is_proper_module ), output=output, ) print("https://dreampuf.github.io/GraphvizOnline/#" + quote(output.getvalue()))