Profiling¶
Silk can be used to profile arbitrary blocks of code and provides silk_profile
, a Python decorator and a context manager for this purpose. Profiles will then appear in the ‘Profiling’ tab within Silk’s user interface.
Decorator¶
The decorator can be applied to both functions and methods:
@silk_profile(name='View Blog Post')
def post(request, post_id):
p = Post.objects.get(pk=post_id)
return render_to_response('post.html', {
'post': p
})
class MyView(View):
@silk_profile(name='View Blog Post')
def get(self, request):
p = Post.objects.get(pk=post_id)
return render_to_response('post.html', {
'post': p
})
Context Manager¶
silk_profile
can also be used as a context manager:
def post(request, post_id):
with silk_profile(name='View Blog Post #%d' % self.pk):
p = Post.objects.get(pk=post_id)
return render_to_response('post.html', {
'post': p
})
Dynamic Profiling¶
Decorators and context managers can also be injected at run-time. This is useful if we want to narrow down slow requests/database queries to dependencies.
Dynamic profiling is configured via the SILKY_DYNAMIC_PROFILING
option in your settings.py
:
"""
Dynamic function decorator
"""
SILKY_DYNAMIC_PROFILING = [{
'module': 'path.to.module',
'function': 'foo'
}]
# ... is roughly equivalent to
@silk_profile()
def foo():
pass
"""
Dynamic method decorator
"""
SILKY_DYNAMIC_PROFILING = [{
'module': 'path.to.module',
'function': 'MyClass.bar'
}]
# ... is roughly equivalent to
class MyClass(object):
@silk_profile()
def bar(self):
pass
"""
Dynamic code block profiling
"""
SILKY_DYNAMIC_PROFILING = [{
'module': 'path.to.module',
'function': 'foo',
# Line numbers are relative to the function as opposed to the file in which it resides
'start_line': 1,
'end_line': 2,
'name': 'Slow Foo'
}]
# ... is roughly equivalent to
def foo():
with silk_profile(name='Slow Foo'):
print (1)
print (2)
print(3)
print(4)
Note that dynamic profiling behaves in a similar fashion to that of the python mock framework in that we modify the function in-place e.g:
""" my.module """
from another.module import foo
# ...do some stuff
foo()
# ...do some other stuff
We would profile foo
by dynamically decorating my.module.foo as opposed to another.module.foo
:
SILKY_DYNAMIC_PROFILING = [{
'module': 'my.module',
'function': 'foo'
}]
If we were to apply the dynamic profile to the functions source module another.module.foo
after it has already been imported, no profiling would be triggered.