mirror of
https://github.com/aykhans/AzSuicideDataVisualization.git
synced 2025-04-21 18:23:35 +00:00
98 lines
3.3 KiB
Python
98 lines
3.3 KiB
Python
"""
|
|
Memory usage profiler for Python.
|
|
|
|
"""
|
|
import inspect
|
|
import sys
|
|
|
|
from pympler import muppy
|
|
|
|
|
|
class MProfiler(object):
|
|
"""A memory usage profiler class.
|
|
|
|
Memory data for each function is stored as a 3-element list in the
|
|
dictionary self.memories. The index is always a codepoint (see below).
|
|
The following are the definitions of the members:
|
|
|
|
[0] = The number of times this function was called
|
|
[1] = Minimum memory consumption when this function was measured.
|
|
[2] = Maximum memory consumption when this function was measured.
|
|
|
|
A codepoint is a list of 3-tuple of the type
|
|
(filename, functionname, linenumber). You can omit either element, which
|
|
will cause the profiling to be triggered if any of the other criteria
|
|
match. E.g.
|
|
- (None, foo, None), will profile any foo function,
|
|
- (bar, foo, None) will profile only the foo function from the bar file,
|
|
- (bar, foo, 17) will profile only line 17 of the foo function defined
|
|
in the file bar.
|
|
|
|
Additionally, you can define on what events you want the profiling be
|
|
triggered. Possible events are defined in
|
|
http://docs.python.org/lib/debugger-hooks.html.
|
|
|
|
If you do not define either codepoints or events, the profiler will
|
|
record the memory usage in at every codepoint and event.
|
|
|
|
"""
|
|
|
|
def __init__(self, codepoints=None, events=None):
|
|
"""
|
|
keyword arguments:
|
|
codepoints -- a list of points in code to monitor (defaults to all
|
|
codepoints)
|
|
events -- a list of events to monitor (defaults to all events)
|
|
"""
|
|
self.memories = {}
|
|
self.codepoints = codepoints
|
|
self.events = events
|
|
|
|
def codepoint_included(self, codepoint):
|
|
"""Check if codepoint matches any of the defined codepoints."""
|
|
if self.codepoints is None:
|
|
return True
|
|
for cp in self.codepoints:
|
|
mismatch = False
|
|
for i in range(len(cp)):
|
|
if (cp[i] is not None) and (cp[i] != codepoint[i]):
|
|
mismatch = True
|
|
break
|
|
if not mismatch:
|
|
return True
|
|
return False
|
|
|
|
def profile(self, frame, event, arg): # arg req to match signature
|
|
"""Profiling method used to profile matching codepoints and events."""
|
|
if (self.events is None) or (event in self.events):
|
|
frame_info = inspect.getframeinfo(frame)
|
|
cp = (frame_info[0], frame_info[2], frame_info[1])
|
|
if self.codepoint_included(cp):
|
|
objects = muppy.get_objects()
|
|
size = muppy.get_size(objects)
|
|
if cp not in self.memories:
|
|
self.memories[cp] = [0, 0, 0, 0]
|
|
self.memories[cp][0] = 1
|
|
self.memories[cp][1] = size
|
|
self.memories[cp][2] = size
|
|
else:
|
|
self.memories[cp][0] += 1
|
|
if self.memories[cp][1] > size:
|
|
self.memories[cp][1] = size
|
|
if self.memories[cp][2] < size:
|
|
self.memories[cp][2] = size
|
|
|
|
def run(self, cmd):
|
|
sys.setprofile(self.profile)
|
|
try:
|
|
exec(cmd)
|
|
finally:
|
|
sys.setprofile(None)
|
|
return self
|
|
|
|
|
|
if __name__ == "__main__":
|
|
p = MProfiler()
|
|
p.run("print('hello')")
|
|
print(p.memories)
|