Skip to content

Commit

Permalink
Add summarize and time sorting to stats output
Browse files Browse the repository at this point in the history
  • Loading branch information
Erotemic committed Aug 3, 2023
1 parent 9bd8b09 commit ee5c126
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 36 deletions.
33 changes: 28 additions & 5 deletions line_profiler/line_profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,14 @@ def dump_stats(self, filename):
with open(filename, 'wb') as f:
pickle.dump(lstats, f, pickle.HIGHEST_PROTOCOL)

def print_stats(self, stream=None, output_unit=None, stripzeros=False):
def print_stats(self, stream=None, output_unit=None, stripzeros=False,
summarize=False, sort=False):
""" Show the gathered statistics.
"""
lstats = self.get_stats()
show_text(lstats.timings, lstats.unit, output_unit=output_unit, stream=stream, stripzeros=stripzeros)
show_text(lstats.timings, lstats.unit, output_unit=output_unit,
stream=stream, stripzeros=stripzeros,
summarize=summarize, sort=sort)

def run(self, cmd):
""" Profile a single executable statment in the main namespace.
Expand Down Expand Up @@ -260,7 +263,6 @@ def show_func(filename, start_lineno, func_name, timings, unit,
if stream is None:
stream = sys.stdout

linenos = [t[0] for t in timings]
total_time = sum(t[2] for t in timings)
if stripzeros and total_time == 0:
return
Expand All @@ -269,6 +271,8 @@ def show_func(filename, start_lineno, func_name, timings, unit,
output_unit = unit
scalar = unit / output_unit

linenos = [t[0] for t in timings]

stream.write('Total time: %g s\n' % (total_time * unit))
if os.path.exists(filename) or is_ipython_kernel_cell(filename):
stream.write(f'File: {filename}\n')
Expand Down Expand Up @@ -355,7 +359,8 @@ def show_func(filename, start_lineno, func_name, timings, unit,
stream.write('\n')


def show_text(stats, unit, output_unit=None, stream=None, stripzeros=False):
def show_text(stats, unit, output_unit=None, stream=None, stripzeros=False,
summarize=False, sort=False):
""" Show text for the given timings.
"""
if stream is None:
Expand All @@ -366,11 +371,29 @@ def show_text(stats, unit, output_unit=None, stream=None, stripzeros=False):
else:
stream.write('Timer unit: %g s\n\n' % unit)

for (fn, lineno, name), timings in sorted(stats.items()):
stats_order = sorted(stats.items())

if sort:
# Order by increasing duration
stats_order = sorted(stats_order, key=lambda kv: sum(t[2] for t in kv[1]))

for (fn, lineno, name), timings in stats_order:
show_func(fn, lineno, name, stats[fn, lineno, name], unit,
output_unit=output_unit, stream=stream,
stripzeros=stripzeros)

if summarize:
# Summarize the total time for each function

summary_rows = []
for (fn, lineno, name), timings in stats_order:
total_time = sum(t[2] for t in timings) * unit
summary_rows.append((total_time, fn, lineno, name))

for total, fn, lineno, name in summary_rows:
line = '%6.2f seconds - %s:%s:%s\n' % (total, fn, lineno, name)
stream.write(line)


def load_stats(filename):
""" Utility function to load a pickled LineStats object from a given
Expand Down
57 changes: 26 additions & 31 deletions tests/complex_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,53 +10,30 @@

@atexit.register
def _show_profile_on_end():
profile.print_stats()
profile.print_stats(summarize=1, sort=1, stripzeros=1)


@profile
def fib(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + b
print()


@profile
def funcy_fib(n):
"""
Alternatite fib function where code splits out over multiple lines
"""
a, b = (
0, 1
)
while a < n:
print(
a, end=' ')
a, b = b, \
a + b
print(
)


@profile
def fib_only_called_by_thread(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + b
print()


@profile
def fib_only_called_by_process(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + b
# FIXME: having two functions with the EXACT same code can cause issues
# a = 'no longer exactly the same'
print()
a = 'no longer exactly the same'


@profile
Expand All @@ -66,12 +43,12 @@ def main():
"""
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--size', type=int, default=10)
parser.add_argument('--serial_size', type=int, default=10)
parser.add_argument('--thread_size', type=int, default=10)
parser.add_argument('--process_size', type=int, default=10)
args = parser.parse_args()

size = args.size

for i in range(size):
for i in range(args.serial_size):
fib(i)
funcy_fib(
i)
Expand All @@ -81,7 +58,7 @@ def main():
executor = ThreadPoolExecutor(max_workers=4)
with executor:
jobs = []
for i in range(size):
for i in range(args.thread_size):
job = executor.submit(fib, i)
jobs.append(job)

Expand All @@ -98,7 +75,7 @@ def main():
executor = ProcessPoolExecutor(max_workers=4)
with executor:
jobs = []
for i in range(size):
for i in range(args.process_size):
job = executor.submit(fib, i)
jobs.append(job)

Expand All @@ -112,10 +89,28 @@ def main():
job.result()


@profile
def funcy_fib(n):
"""
Alternatite fib function where code splits out over multiple lines
"""
a, b = (
0, 1
)
while a < n:
# print(
# a, end=' ')
a, b = b, \
a + b
# print(
# )


if __name__ == '__main__':
"""
CommandLine:
cd ~/code/line_profiler/tests/
python complex_example.py --size 10
python complex_example.py --serial_size 100000 --thread_size 0 --process_size 0
"""
main()

0 comments on commit ee5c126

Please sign in to comment.