Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@ this would result in::

Output will follow::

Line # Mem usage Increment Line Contents
==============================================
3 @profile
4 5.97 MB 0.00 MB def my_func():
5 13.61 MB 7.64 MB a = [1] * (10 ** 6)
6 166.20 MB 152.59 MB b = [2] * (2 * 10 ** 7)
7 13.61 MB -152.59 MB del b
8 13.61 MB 0.00 MB return a
Line # Mem usage Increment Occurences Line Contents
============================================================
3 38.816 MiB 38.816 MiB 1 @profile
4 def my_func():
5 46.492 MiB 7.676 MiB 1 a = [1] * (10 ** 6)
6 199.117 MiB 152.625 MiB 1 b = [2] * (2 * 10 ** 7)
7 46.629 MiB -152.488 MiB 1 del b
8 46.629 MiB 0.000 MiB 1 return a


The first column represents the line number of the code that has been
Expand Down
27 changes: 17 additions & 10 deletions memory_profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,10 @@ def memory_usage(proc=-1, interval=.1, timeout=None, timestamps=False,
to this file instead of stored in memory and returned at the end of
the subprocess. Useful for long-running processes.
Implies timestamps=True.

max_iterations : int
Limits the number of iterations (calls to the process being monitored). Relevent
when the process is a python function.
when the process is a python function.

Returns
-------
Expand Down Expand Up @@ -357,7 +357,7 @@ def memory_usage(proc=-1, interval=.1, timeout=None, timestamps=False,
raise

p.join(5 * interval)

if (n_measurements > 4) or (current_iter == max_iter) or (interval < 1e-6):
break
interval /= 10.
Expand Down Expand Up @@ -643,7 +643,12 @@ def trace(self, code, lineno, prev_lineno):

prev_line_value = self[code].get(prev_lineno, None) if prev_lineno else None
prev_line_memory = prev_line_value[1] if prev_line_value else 0
self[code][lineno] = (max(previous_inc, memory-prev_line_memory), max(memory, previous_memory))
occ_count = self[code][lineno][2] + 1 if lineno in self[code] else 1
self[code][lineno] = (
previous_inc + (memory - prev_line_memory),
max(memory, previous_memory),
occ_count,
)

def items(self):
"""Iterate on the toplevel code blocks."""
Expand Down Expand Up @@ -800,10 +805,10 @@ def disable(self):
def show_results(prof, stream=None, precision=1):
if stream is None:
stream = sys.stdout
template = '{0:>6} {1:>12} {2:>12} {3:<}'
template = '{0:>6} {1:>12} {2:>12} {3:>10} {4:<}'

for (filename, lines) in prof.code_map.items():
header = template.format('Line #', 'Mem usage', 'Increment',
header = template.format('Line #', 'Mem usage', 'Increment', 'Occurences',
'Line Contents')

stream.write(u'Filename: ' + filename + '\n\n')
Expand All @@ -817,13 +822,15 @@ def show_results(prof, stream=None, precision=1):
for (lineno, mem) in lines:
if mem:
inc = mem[0]
mem = mem[1]
mem = template_mem.format(mem)
total_mem = mem[1]
total_mem = template_mem.format(total_mem)
occurences = mem[2]
inc = template_mem.format(inc)
else:
mem = u''
total_mem = u''
inc = u''
tmp = template.format(lineno, mem, inc, all_lines[lineno - 1])
occurences = u''
tmp = template.format(lineno, total_mem, inc, occurences, all_lines[lineno - 1])
stream.write(to_str(tmp))
stream.write(u'\n\n')

Expand Down
81 changes: 81 additions & 0 deletions test/test_increment_display.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import unittest

from memory_profiler import LineProfiler, profile, show_results
from io import StringIO


class TestIncrementDisplay(unittest.TestCase):
"""Tests memory incrementation / decrementation display"""

def test_loop_count(self):

def some_loop():
for i in range(12): # line -2
a = 1 # line -1

profiler = LineProfiler()
wrapped = profiler(some_loop)
wrapped()
show_results(profiler)
for_line = list(list(profiler.code_map.values())[0].values())[-2]
looped_instruction = list(list(profiler.code_map.values())[0].values())[-1]

self.assertEqual(for_line[2], 13)
self.assertEqual(looped_instruction[2], 12)

def test_normal_incr(self):

def normal_incr():
use_some_memory = [1] * (10 ** 6)

profiler = LineProfiler()
wrapped = profiler(normal_incr)
wrapped()

show_results(profiler)
results = list(list(profiler.code_map.values())[0].values())[-1]

self.assertGreater(results[0], 0)
self.assertGreater(results[1], results[0])
self.assertEqual(results[2], 1)

def test_loop_incr(self):

def loop_incr():
a = []
b = [2] * (2 * 10 ** 7) # line -4
for i in range(3):
c = [2] * (2 * 10 ** 7) # line -2
a.append(c)

profiler = LineProfiler()
wrapped = profiler(loop_incr)
wrapped()

show_results(profiler)
b_line = list(list(profiler.code_map.values())[0].values())[-4]
c_line = list(list(profiler.code_map.values())[0].values())[-2]
self.assertAlmostEqual(b_line[2] * 3, c_line[2], delta=1)
self.assertEqual(c_line[2], 3)

def test_decr(self):

def del_stuff():
b = [2] * (2 * 10 ** 7)
del b

profiler = LineProfiler()
wrapped = profiler(del_stuff)
wrapped()

show_results(profiler)
b_line = list(list(profiler.code_map.values())[0].values())[-2]
del_line = list(list(profiler.code_map.values())[0].values())[-1]

self.assertGreater(0, del_line[0])
self.assertGreater(del_line[1], 0)
self.assertAlmostEqual(-del_line[0], b_line[0], delta=1)


if __name__ == '__main__':
unittest.main()