Skip to content

Commit

Permalink
Merge pull request #7 from reallistic/cleanup_collector
Browse files Browse the repository at this point in the history
Cleanup some dead code in the collector, add Pyloot.stop to the README
  • Loading branch information
reallistic committed Jun 11, 2020
2 parents c89dd10 + 390b939 commit 190c1b6
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 28 deletions.
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ Otherwise, threading.Thread is used.
"""
loot.start()

"""
Stop running the collector background thread.
NOTE: This does not do a "final" collection.
To ensure objects were collected in a short lived execution, call collect_objects().
:param blocking: When true, wait until the thread has died
"""
loot.stop()

"""
Return a WSGI compatible application serving the PyLoot remote backend and
and the website.
Expand Down Expand Up @@ -76,7 +86,7 @@ app = DispatcherMiddleware(app, {
# Embedded code
from pyloot import PyLoot
...
pyloot = PyLoot(host="127.0.0.1", port=8030)
pyloot = PyLoot(host="127.0.0.1", port=8000)
...
```
```shell script
Expand All @@ -86,7 +96,7 @@ usage: pyloot [-h HOST] [-p PORT] [--help]

optional arguments:
-h HOST, --host HOST Host to listen on. (Default: 0.0.0.0)
-p PORT, --port PORT Port to listen on. (Default: 8030)
-p PORT, --port PORT Port to listen on. (Default: 8000)
--help show this help message and exit
```

Expand All @@ -111,7 +121,7 @@ app.mount("/_pyloot", WSGIMiddleware(pyloot_wrapper))

# Screenshots
### View history of object counts by object group:
![history screenshot](https://raw.githubusercontent.com/reallistic/pyloot/master/docs/historypage.png)
![history screenshot](https://raw.githubusercontent.com/reallistic/pyloot/master/docs/history.png)

### Modify history page size
![history screenshot](https://raw.githubusercontent.com/reallistic/pyloot/master/docs/history-pageLimit.png)
Expand Down
8 changes: 8 additions & 0 deletions pyloot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ def start(self):
logger.debug("Finished starting pyloot looter thread")

def stop(self, blocking=False):
"""
Stop running the collector background thread.
NOTE: This does not do a "final" collection.
To ensure objects were collected in a short lived execution, call collect_objects().
:param blocking: When true, wait until the thread has died
"""
self._running = False
if blocking:
self._thread_ended.wait()
Expand Down
27 changes: 5 additions & 22 deletions pyloot/collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def _safe_getattr(obj: object, k: str, default: Any = Exception):
try:
from zope.interface.ro import C3

if isinstance(obj, C3) or issubclass(obj, C3):
if isinstance(obj, C3) or issubclass(obj, C3): # type: ignore
if k.startswith("ORIG_"):
return "__ignored_zope_interface_C3_{}__".format(k)
except (ImportError, TypeError):
Expand Down Expand Up @@ -92,38 +92,21 @@ def _should_include_object(ref: object, ignore_set: Set[int]) -> bool:
return True


def get_child_ids(obj: object, ignore_set: Set[int]) -> List[int]:
def get_child_ids(obj: object) -> List[int]:
"""
Return children of the provided object using gc.get_referents
:param obj: The object
:param ignore_set: A set of `id()`s which should be ignored.
:return: List of object ids
"""
return [id(child) for child in gc.get_referents(obj)]


def get_parent_ids(obj: object, ignore_set: Set[int]) -> List[int]:
"""
Return children of the provided object using gc.get_referents
:param obj: The object
:param ignore_set: A set of `id()`s which should be ignored.
:return: List of object ids
"""
return [
id(parent)
for parent in gc.get_referrers(obj)
if _should_include_object(parent, ignore_set)
]


def get_data(obj: object, ignore_set: Set[int]) -> ObjectDescriptor:
def get_data(obj: object) -> ObjectDescriptor:
"""
Return a Object descriptor for the given object
:param obj: The object
:param ignore_set: A set of `id()`s which should be ignored.
:return:
"""
obj_type = type(obj)
Expand All @@ -134,7 +117,7 @@ def get_data(obj: object, ignore_set: Set[int]) -> ObjectDescriptor:
id=id(obj),
attrs=_safe_get_attrs(obj),
parent_ids=[],
child_ids=get_child_ids(obj, ignore_set),
child_ids=get_child_ids(obj),
repr=_safe_repr(obj),
)

Expand Down Expand Up @@ -162,7 +145,7 @@ def get_object_descriptors(

objs = [obj for obj in objs if _should_include_object(obj, ignore_set)]
ignore_set.add(id(objs))
results = [get_data(obj, ignore_set) for obj in objs]
results = [get_data(obj) for obj in objs]
del objs
del ignore_set
child_to_parent: Dict[int, Set[int]] = defaultdict(set)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

setup(
name="pyloot",
versioning="distance",
versioning="post",
setup_requires="setupmeta",
author="Michael Chase",
description="Multiprocessing compatible memory leak debugger inspired by dozer/dowser",
Expand Down
4 changes: 2 additions & 2 deletions tests/test_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
def test_store_blank_slate():
backend = InMemoryBackend()
test_obj = dict(a=1)
obj_descr = collector.get_data(test_obj, set())
obj_descr = collector.get_data(test_obj)
backend.store([obj_descr])

descrs = backend.fetch()
Expand All @@ -29,7 +29,7 @@ def test_store_blank_slate():
assert history[0].counts == [1, 1]

test_obj2 = dict(a=1)
obj_descr2 = collector.get_data(test_obj2, set())
obj_descr2 = collector.get_data(test_obj2)

# new obj should increase data and count
backend.store([obj_descr, obj_descr2])
Expand Down

0 comments on commit 190c1b6

Please sign in to comment.