Created
June 3, 2015 15:56
-
-
Save jmuhlich/b6e349c5d80ec3897a77 to your computer and use it in GitHub Desktop.
profile top-level code with line_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
# Hacks to get line_profiler to profile top-level code in a script/module. | |
# 1. The interface only allows profiling functions, but the core profiling logic | |
# actually works directly with code objects. We create a new function object | |
# from the code at the top level of the script to profile, and call | |
# profile.add_function on it. This is enough to trick the bookkeeping code in | |
# line_profiler to include the top-level code. | |
# 2. Even though the entirety of the top-level code is profiled in full, the | |
# results printer will stop at the first function definition, class definition, | |
# or lambda due to its use of inspect.getblock to retrieve the code (should it | |
# use inspect.getsource?). The quick workaround is to patch up the profiler's | |
# internal accounting data structure to lie about what line number the code | |
# begins on, using a line number that is after any function and class | |
# definitions (hopefully they are all above the code you want to profile). You | |
# will need to adjust this number in the second code block below (search for | |
# "12345"). Lambdas are still a problem, though, and I'm not sure this can be | |
# worked around easily without a patch to line_profiler itself. | |
# Note that this code assumes you are running under kernprof -l or have | |
# explicitly created your own LineProfiler object named "profile". | |
# Put this at the top of your file: | |
import inspect, types | |
__code = inspect.currentframe().f_code | |
profile.add_function(types.FunctionType(__code, globals())) | |
profile.enable() | |
# Put this at the bottom of your file (and patch up the line number on the | |
# commented line): | |
profile.disable() | |
__code_patched = types.CodeType( | |
__code.co_argcount, __code.co_nlocals, __code.co_stacksize, __code.co_flags, | |
__code.co_code, __code.co_consts, __code.co_names, __code.co_varnames, | |
__code.co_filename, __code.co_name, | |
12345, # Change this to the first line of the desired block (see 2. above) | |
__code.co_lnotab, __code.co_freevars, __code.co_cellvars) | |
profile.code_map[__code_patched] = profile.code_map[__code] | |
del profile.code_map[__code] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment