diff options
| author | Dave McLain | 2011-04-26 14:39:01 -0500 | 
|---|---|---|
| committer | Dave McLain | 2011-04-26 14:46:07 -0500 | 
| commit | cf82001f197288c9816c2d7adcc09c08205cfa42 (patch) | |
| tree | 1f62e181c376c63e0e7b895db6ecf764fe8da673 | |
| parent | a3e8ce8eb1c4e2d1482a22d3a7e0dba7f4ff3201 (diff) | |
| download | django-debug-toolbar-cf82001f197288c9816c2d7adcc09c08205cfa42.tar.bz2 | |
Integrating line_profiler
| -rw-r--r-- | debug_toolbar/panels/profiling.py | 52 | ||||
| -rw-r--r-- | debug_toolbar/templates/debug_toolbar/panels/profiling.html | 19 | 
2 files changed, 57 insertions, 14 deletions
| diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py index 68aafb7..53e333e 100644 --- a/debug_toolbar/panels/profiling.py +++ b/debug_toolbar/panels/profiling.py @@ -5,6 +5,14 @@ from django.utils.translation import ugettext_lazy as _  from django.utils.safestring import mark_safe  from debug_toolbar.panels import DebugPanel +try: +    from line_profiler import LineProfiler, show_func +    DJ_PROFILE_USE_LINE_PROFILER = True +except ImportError:     +    DJ_PROFILE_USE_LINE_PROFILER = False +     + +from cStringIO import StringIO  import cProfile  from pstats import Stats  from colorsys import hsv_to_rgb @@ -20,13 +28,6 @@ class DjangoDebugToolbarStats(Stats):                      break          return self.__root -    def print_call_tree_node(self, function, depth, max_depth, cum_filter=0.1): -        self.print_line(function, depth=depth) -        if depth < max_depth: -            for called in self.all_callees[function].keys(): -                if self.stats[called][3] >= cum_filter: -                    self.print_call_tree_node(called, depth+1, max_depth, cum_filter=cum_filter) -  class FunctionCall(object):      def __init__(self, statobj, func, depth=0, stats=None, id=0, parent_ids=[], hsv=(0,0.5,1)):          self.statobj = statobj @@ -39,6 +40,7 @@ class FunctionCall(object):          self.id = id          self.parent_ids = parent_ids          self.hsv = hsv +        self._line_stats_text = None      def parent_classes(self):          return self.parent_classes @@ -118,6 +120,18 @@ class FunctionCall(object):      def indent(self):          return 16 * self.depth +         +    def line_stats_text(self): +        if self._line_stats_text is None: +            lstats = self.statobj.line_stats +            if self.func in lstats.timings: +                out = StringIO() +                fn, lineno, name = self.func +                show_func(fn, lineno, name, lstats.timings[self.func], lstats.unit, stream=out) +                self._line_stats_text = out.getvalue() +            else: +                self._line_stats_text = False +        return self._line_stats_text  class ProfilingDebugPanel(DebugPanel):      """ @@ -135,14 +149,34 @@ class ProfilingDebugPanel(DebugPanel):      def title(self):          return _('Profiling') +    def _unwrap_closure_and_profile(self, func): +        if not hasattr(func, 'func_code'): +            return +        self.line_profiler.add_function(func) +        if func.func_closure: +            for cell in func.func_closure: +                if hasattr(cell.cell_contents, 'func_code'): +                    self._unwrap_closure_and_profile(cell.cell_contents) +      def process_view(self, request, view_func, view_args, view_kwargs):          self.profiler = cProfile.Profile()          args = (request,) + view_args -        return self.profiler.runcall(view_func, *args, **view_kwargs) +        if DJ_PROFILE_USE_LINE_PROFILER: +            self.line_profiler = LineProfiler() +            self._unwrap_closure_and_profile(view_func) +            self.line_profiler.enable_by_count() +            out = self.profiler.runcall(view_func, *args, **view_kwargs) +            self.line_profiler.disable_by_count() +        else: +            self.line_profiler = None +            out = self.profiler.runcall(view_func, *args, **view_kwargs) +        return out      def process_response(self, request, response):          self.profiler.create_stats()          self.stats = DjangoDebugToolbarStats(self.profiler) +        if DJ_PROFILE_USE_LINE_PROFILER: +            self.stats.line_stats = self.line_profiler.get_stats()          return response      def add_node(self, func_list, func, max_depth, cum_time=0.1): @@ -150,7 +184,7 @@ class ProfilingDebugPanel(DebugPanel):          func.has_subfuncs = False          if func.depth < max_depth:              for subfunc in func.subfuncs(): -                if subfunc.stats[3] >= cum_time: +                if subfunc.stats[3] >= cum_time or (subfunc.func in self.stats.line_stats.timings):                      func.has_subfuncs = True                      self.add_node(func_list, subfunc, max_depth, cum_time=cum_time) diff --git a/debug_toolbar/templates/debug_toolbar/panels/profiling.html b/debug_toolbar/templates/debug_toolbar/panels/profiling.html index ebc91cc..ef42230 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/profiling.html +++ b/debug_toolbar/templates/debug_toolbar/panels/profiling.html @@ -4,10 +4,10 @@  	<thead>  		<tr>  			<th>{% trans "Call" %}</th> -			<th>{% trans "TotTime" %}</th> -			<th>{% trans "Per" %}</th>  			<th>{% trans "CumTime" %}</th>  			<th>{% trans "Per" %}</th> +			<th>{% trans "TotTime" %}</th> +			<th>{% trans "Per" %}</th>  			<th>{% trans "Count" %}</th>  		</tr>  	</thead> @@ -25,12 +25,21 @@  						<span class="stack">{{ call.func_std_string }}</span>  					</div>  				</td> -				<td>{{ call.tottime|floatformat:3 }}</td> -				<td>{{ call.tottime_per_call|floatformat:3 }}</td>  				<td>{{ call.cumtime|floatformat:3 }}</td>  				<td>{{ call.cumtime_per_call|floatformat:3 }}</td> +				<td>{{ call.tottime|floatformat:3 }}</td> +				<td>{{ call.tottime_per_call|floatformat:3 }}</td>  				<td>{{ call.count }}</td>  			</tr> +			{% if call.line_stats_text %} +			<tr> +				<td colspan='6'> +					<pre style='font-family:Courier, monospace'> +						{{ call.line_stats_text }} +					</pre> +				</td> +			</tr> +			{% endif %}  		{% endfor %}  	</tbody> -</table> +</table>
\ No newline at end of file | 
