Created
May 12, 2020 21:22
-
-
Save gregtatum/67f23c09d9daa4c628f87476944ecf50 to your computer and use it in GitHub Desktop.
cProfile in Python to Gecko Profiler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cProfile, pstats, StringIO, pdb, json | |
def func_a(n, l): | |
if (n > l / 2): | |
return func_b(n) | |
else: | |
return func_c(n) | |
def func_b(n): | |
return factorial_loop(n) | |
def func_c(n): | |
return factorial_loop(n) | |
def factorial_loop(n): | |
product = 1 | |
for i in range(n): | |
product = product * (i+1) | |
return product | |
def factorial_recursive(n): | |
if n == 0: | |
return 1 | |
else: | |
return n * factorial_recursive(n-1) | |
def run(): | |
result = 0 | |
# Run factorial in a loop | |
for x in range(300): | |
result += factorial_loop(x) | |
# Run a recursive factorial | |
for x in range(300): | |
result += factorial_recursive(x) | |
# Run a factorial with a different root | |
for x in range(3000): | |
result += func_a(x, 3000) | |
return result | |
def collect_profile(): | |
profile = cProfile.Profile() | |
profile.enable() | |
run() | |
profile.disable() | |
return profile | |
def print_stats(profile): | |
stream = StringIO.StringIO() | |
ps = pstats.Stats(profile, stream=stream).sort_stats('cumulative') | |
ps.print_stats() | |
print(stream.getvalue()) | |
def get_function_name(code): | |
if isinstance(code, str): | |
# This is a built-in function. | |
return code | |
else: | |
return code.co_name | |
def label(code): | |
if isinstance(code, str): | |
return ('(built-in)', 0, code) # built-in functions ('~' sorts at the end) | |
else: | |
return (code.co_filename, code.co_firstlineno, code.co_name) | |
def format_time(n): | |
s = "%s" % n | |
return s.ljust(10, ' ') | |
def get_inlinetime(entry): | |
return -entry.totaltime | |
def cprofile_to_gecko_profile(profile): | |
# https://github.com/python/cpython/blob/8d21aa21f2cbc6d50aab3f420bb23be1d081dac4/Modules/_lsprof.c#L502-L519 | |
# | |
# _lsprof.profiler_entry( | |
# code=<code object factorial_recursive at 0x1082cd830, file "profiler.py", line 11>, | |
# callcount=45150, | |
# reccallcount=44850, | |
# totaltime=0.013555, | |
# inlinetime=0.013555, | |
# calls=[ | |
# _lsprof.profiler_subentry( | |
# code=<code object factorial_recursive at 0x1082cd830, file "profiler.py", line 11>, | |
# callcount=44850, | |
# reccallcount=44551, | |
# totaltime=0.013457, | |
# inlinetime=0.013457 | |
# ) | |
# ] | |
# ) | |
# The code attribute is taken from: https://github.com/python/cpython/blob/8d21aa21f2cbc6d50aab3f420bb23be1d081dac4/Include/code.h#L10 | |
print("-----------|------------|------------------------") | |
print("total | inline | function") | |
print("-----------|------------|------------------------") | |
for entry in profile.getstats(): | |
# stringArray = list() | |
# funcTable = {} | |
# stackTable = {} | |
print("%s | %s | %s" % ( | |
format_time(entry.totaltime), | |
format_time(entry.inlinetime), | |
get_function_name(entry.code) | |
)) | |
if entry.calls == None: | |
continue | |
for sub_entry in entry.calls: | |
print("%s | %s | - calls: %s" % ( | |
format_time(sub_entry.totaltime), | |
format_time(sub_entry.inlinetime), | |
get_function_name(sub_entry.code) | |
)) | |
profile = collect_profile() | |
cprofile_to_gecko_profile(profile) | |
# pdb.set_trace() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment