Ejemplo n.º 1
0
        def jungleprofiler_wrapped_f(*args, **kwargs):
            ''' Wrapper that collects time and system usage data on wrapped function f'''

            # Set up LineProfiler
            lp = LineProfiler()
            lp.add_function(f)

            # Set up MemoryProfiler
            pass  # todo add Memory Profiler

            # Start Counters
            if self.t_prof: lp.enable_by_count()
            if self.m_prof: pass
            try:
                t0 = time.time()
                sio = io.StringIO()  # Collects redirected stdout
                with redirect_stdout(sio):
                    preturn = f(*args, **kwargs)
                self.stdout = sio.getvalue()
                t1 = time.time()
            finally:
                # Stop Counters
                if self.m_prof: lp.disable_by_count()
                if self.m_prof: pass  # todo add Memory Profiler

            # Collect Stats
            # print('Get Stats: %s' % lp.print_stats())

            self.walltime = t1 - t0
            return preturn, copy.deepcopy(self)
class ProfilingPanel(Panel):
    """
    Panel that displays profiling information.
    """
    title = _('Profiling')

    template = 'debug_toolbar_line_profiler/panels/profiling.html'

    def _unwrap_closure_and_profile(self, func):
        if not hasattr(func, '__code__'):
            return
        self.line_profiler.add_function(func)
        for subfunc in getattr(func, 'profile_additional', []):
            self._unwrap_closure_and_profile(subfunc)
        if func.__closure__:
            for cell in func.__closure__:
                target = cell.cell_contents
                if inspect.isclass(target) and View in inspect.getmro(target):
                    for name, value in inspect.getmembers(target):
                        if name[0] != '_' and inspect.ismethod(value):
                            self._unwrap_closure_and_profile(value)
                else:
                    self._unwrap_closure_and_profile(target)

    def process_view(self, request, view_func, view_args, view_kwargs):
        self.profiler = cProfile.Profile()
        args = (request,) + view_args
        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()
        return out

    def add_node(self, func_list, func, max_depth, cum_time=0.1):
        func_list.append(func)
        func.has_subfuncs = False
        if func.depth < max_depth:
            for subfunc in func.subfuncs():
                if (subfunc.stats[3] >= cum_time or
                        (hasattr(self.stats, 'line_stats') and
                            (subfunc.func in self.stats.line_stats.timings))):
                    func.has_subfuncs = True
                    self.add_node(func_list, subfunc, max_depth, cum_time=cum_time)

    def process_response(self, request, response):
        if not hasattr(self, 'profiler'):
            return None
        # Could be delayed until the panel content is requested (perf. optim.)
        self.profiler.create_stats()
        self.stats = DjangoDebugToolbarStats(self.profiler)
        self.stats.line_stats = self.line_profiler.get_stats()
        self.stats.calc_callees()

        root = FunctionCall(self.stats, self.stats.get_root_func(), depth=0)

        func_list = []
        self.add_node(func_list, root, 10, root.stats[3] / 8)

        self.record_stats({'func_list': func_list})
Ejemplo n.º 3
0
 def wrap(*args, **kwargs):
     profile = LineProfiler()
     profile.add_function(f)
     profile.enable_by_count()
     result = f(*args, **kwargs)
     profile.disable_by_count()
     profile.print_stats(sys.stdout)
     return result
 def profiled_func(*args, **kwargs):
     line_profiler = LineProfiler()
     line_profiler.add_function(func)
     map(lambda x: line_profiler.add_function(x), self.follow)
     line_profiler.enable_by_count()
     result = func(*args, **kwargs)
     line_profiler.disable_by_count()
     line_profiler.print_stats(stripzeros=True)
     return result
Ejemplo n.º 5
0
class Profiler(object):

    def __init__(self, *args):
        self.profile = LineProfiler()

        if len(args) > 0:
            for func in args:
                if callable(func):
                    self.add_function(func)

    def add_function(self, func):
        self.profile.add_function(func)

    def __enter__(self):
        self.profile.enable_by_count()

    def __exit__(self, type, value, traceback):
        self.profile.disable_by_count()
        self.profile.print_stats()
Ejemplo n.º 6
0
    def test_enable_disable(self):
        lp = LineProfiler()
        self.assertEqual(lp.enable_count, 0)
        lp.enable_by_count()
        self.assertEqual(lp.enable_count, 1)
        lp.enable_by_count()
        self.assertEqual(lp.enable_count, 2)
        lp.disable_by_count()
        self.assertEqual(lp.enable_count, 1)
        lp.disable_by_count()
        self.assertEqual(lp.enable_count, 0)
        self.assertEqual(lp.last_time, {})
        lp.disable_by_count()
        self.assertEqual(lp.enable_count, 0)

        with lp:
            self.assertEqual(lp.enable_count, 1)
            with lp:
                self.assertEqual(lp.enable_count, 2)
            self.assertEqual(lp.enable_count, 1)
        self.assertEqual(lp.enable_count, 0)
        self.assertEqual(lp.last_time, {})

        with self.assertRaises(RuntimeError):
            self.assertEqual(lp.enable_count, 0)
            with lp:
                self.assertEqual(lp.enable_count, 1)
                raise RuntimeError()
        self.assertEqual(lp.enable_count, 0)
        self.assertEqual(lp.last_time, {})
Ejemplo n.º 7
0
class ProfilingDebugPanel(DebugPanel):
    """
    Panel that displays the Django version.
    """
    name = 'Profiling'
    template = 'debug_toolbar/panels/profiling.html'
    has_content = True
    
    def nav_title(self):
        return _('Profiling')
    
    def url(self):
        return ''
    
    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):
        __traceback_hide__ = True
        self.profiler = cProfile.Profile()
        args = (request,) + view_args
        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 add_node(self, func_list, func, max_depth, cum_time=0.1):
        func_list.append(func)
        func.has_subfuncs = False
        if func.depth < max_depth:
            for subfunc in func.subfuncs():
                if (subfunc.stats[3] >= cum_time or
                   (hasattr(self.stats, 'line_stats') and
                   (subfunc.func in self.stats.line_stats.timings))):
                    func.has_subfuncs = True
                    self.add_node(func_list, subfunc, max_depth, cum_time=cum_time)
    
    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()
        self.stats.calc_callees()
        
        root = FunctionCall(self.stats, self.stats.get_root_func(), depth=0)
        
        func_list = []
        self.add_node(func_list, root, 10, root.stats[3]/8)
        
        self.stats_record({'func_list': func_list})
class ProfilingPanel(Panel):
    """
    Panel that displays profiling information.
    """
    title = _('Profiling')

    template = 'debug_toolbar_line_profiler/panels/profiling.html'

    def _unwrap_closure_and_profile(self, func):
        if not hasattr(func, '__code__'):
            return
        self.line_profiler.add_function(func)
        for subfunc in getattr(func, 'profile_additional', []):
            self._unwrap_closure_and_profile(subfunc)
        if PY2:
            func_closure = func.func_closure
        else:
            func_closure = func.__closure__

        if func_closure:
            for cell in func_closure:
                target = cell.cell_contents
                if hasattr(target, '__code__'):
                    self._unwrap_closure_and_profile(cell.cell_contents)
                if inspect.isclass(target) and View in inspect.getmro(target):
                    for name, value in inspect.getmembers(target):
                        if name[0] != '_' and inspect.ismethod(value):
                            self._unwrap_closure_and_profile(value)

    def process_view(self, request, view_func, view_args, view_kwargs):
        self.view_func = view_func
        self.profiler = cProfile.Profile()
        args = (request,) + view_args
        self.line_profiler = LineProfiler()
        self._unwrap_closure_and_profile(view_func)
        signals.profiler_setup.send(sender=self,
                                    profiler=self.line_profiler,
                                    view_func=view_func,
                                    view_args=view_args,
                                    view_kwargs=view_kwargs)
        self.line_profiler.enable_by_count()
        out = self.profiler.runcall(view_func, *args, **view_kwargs)
        self.line_profiler.disable_by_count()
        return out

    def add_node(self, func_list, func, max_depth, cum_time=0.1):
        """
        add_node does a depth first traversal of the call graph, appending a
        FunctionCall object to func_list, so that the Django template only
        has to do a single for loop over func_list that can render a tree
        structure

        Parameters:
            func_list is an array that will have a FunctionCall for each call
                added to it
            func is a FunctionCall object that will have all its callees added
            max_depth is the maximum depth we should recurse
            cum_time is the minimum cum_time a function should have to be
                included in the output
        """
        func_list.append(func)
        func.has_subfuncs = False
        # this function somewhat dangerously relies on FunctionCall to set its
        # subfuncs' depth argument correctly
        if func.depth >= max_depth:
            return

        # func.subfuncs returns FunctionCall objects
        subs = sorted(func.subfuncs(), key=FunctionCall.cumtime, reverse=True)
        for subfunc in subs:
            # a sub function is important if it takes a long time or it has
            # line_stats
            if (subfunc.cumtime() >= cum_time or
                    (hasattr(self.stats, 'line_stats') and
                     subfunc.func in self.stats.line_stats.timings)):
                func.has_subfuncs = True
                self.add_node(
                    func_list=func_list,
                    func=subfunc,
                    max_depth=max_depth,
                    cum_time=subfunc.cumtime()/16)

    def process_response(self, request, response):
        if not hasattr(self, 'profiler'):
            return None
        # Could be delayed until the panel content is requested (perf. optim.)
        self.profiler.create_stats()
        self.stats = DjangoDebugToolbarStats(self.profiler)
        self.stats.line_stats = self.line_profiler.get_stats()
        self.stats.calc_callees()

        func_list = []
        root_func = self.stats.get_root_func(self.view_func)

        if root_func is not None:
            root_node = FunctionCall(statobj=self.stats,
                                     func=root_func,
                                     depth=0)
            self.add_node(
                func_list=func_list,
                func=root_node,
                max_depth=10,
                cum_time=root_node.cumtime() / 8
            )
        # else:
        # what should we do if we didn't detect a root function? It's not
        # clear what causes this, but there are real world examples of it (see
        # https://github.com/dmclain/django-debug-toolbar-line-profiler/issues/11)

        self.record_stats({'func_list': func_list})
Ejemplo n.º 9
0
class ProfilingPanel(Panel):
    """
    Panel that displays profiling information.
    """
    title = _('Profiling')

    template = 'debug_toolbar_line_profiler/panels/profiling.html'

    def _unwrap_closure_and_profile(self, func):
        if not hasattr(func, '__code__'):
            return
        self.line_profiler.add_function(func)
        for subfunc in getattr(func, 'profile_additional', []):
            self._unwrap_closure_and_profile(subfunc)
        if PY2:
            func_closure = func.func_closure
        else:
            func_closure = func.__closure__

        if func_closure:
            for cell in func_closure:
                target = cell.cell_contents
                if hasattr(target, '__code__'):
                    self._unwrap_closure_and_profile(cell.cell_contents)
                if inspect.isclass(target) and View in inspect.getmro(target):
                    for name, value in inspect.getmembers(target):
                        if name[0] != '_' and inspect.ismethod(value):
                            self._unwrap_closure_and_profile(value)

    def process_view(self, request, view_func, view_args, view_kwargs):
        self.view_func = view_func
        self.profiler = cProfile.Profile()
        args = (request,) + view_args
        self.line_profiler = LineProfiler()
        self._unwrap_closure_and_profile(view_func)
        signals.profiler_setup.send(sender=self,
                                    profiler=self.line_profiler,
                                    view_func=view_func,
                                    view_args=view_args,
                                    view_kwargs=view_kwargs)
        self.line_profiler.enable_by_count()
        out = self.profiler.runcall(view_func, *args, **view_kwargs)
        self.line_profiler.disable_by_count()
        return out

    def add_node(self, func_list, func, max_depth, cum_time=0.1):
        """
        add_node does a depth first traversal of the call graph, appending a
        FunctionCall object to func_list, so that the Django template only
        has to do a single for loop over func_list that can render a tree
        structure

        Parameters:
            func_list is an array that will have a FunctionCall for each call
                added to it
            func is a FunctionCall object that will have all its callees added
            max_depth is the maximum depth we should recurse
            cum_time is the minimum cum_time a function should have to be
                included in the output
        """
        func_list.append(func)
        func.has_subfuncs = False
        # this function somewhat dangerously relies on FunctionCall to set its
        # subfuncs' depth argument correctly
        if func.depth >= max_depth:
            return

        # func.subfuncs returns FunctionCall objects
        subs = sorted(func.subfuncs(), key=FunctionCall.cumtime, reverse=True)
        for subfunc in subs:
            # a sub function is important if it takes a long time or it has
            # line_stats
            if (subfunc.cumtime() >= cum_time or
                    (hasattr(self.stats, 'line_stats') and
                     subfunc.func in self.stats.line_stats.timings)):
                func.has_subfuncs = True
                self.add_node(
                    func_list=func_list,
                    func=subfunc,
                    max_depth=max_depth,
                    cum_time=subfunc.cumtime()/16)

    def process_response(self, request, response):
        if not hasattr(self, 'profiler'):
            return None
        # Could be delayed until the panel content is requested (perf. optim.)
        self.profiler.create_stats()
        self.stats = DjangoDebugToolbarStats(self.profiler)
        self.stats.line_stats = self.line_profiler.get_stats()
        self.stats.calc_callees()

        func_list = []
        root_func = self.stats.get_root_func(self.view_func)

        if root_func is not None:
            root_node = FunctionCall(statobj=self.stats,
                                     func=root_func,
                                     depth=0)
            self.add_node(
                func_list=func_list,
                func=root_node,
                max_depth=10,
                cum_time=root_node.cumtime() / 8
            )
        # else:
        # what should we do if we didn't detect a root function? It's not
        # clear what causes this, but there are real world examples of it (see
        # https://github.com/dmclain/django-debug-toolbar-line-profiler/issues/11)

        self.record_stats({'func_list': func_list})
Ejemplo n.º 10
0
class ProfilingDebugPanel(DebugPanel):
    """
    Panel that displays the Django version.
    """
    name = 'Profiling'
    template = 'debug_toolbar/panels/profiling.html'
    has_content = True

    def nav_title(self):
        return _('Profiling')

    def url(self):
        return ''

    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):
        __traceback_hide__ = True
        self.profiler = cProfile.Profile()
        args = (request, ) + view_args
        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 add_node(self, func_list, func, max_depth, cum_time=0.1):
        func_list.append(func)
        func.has_subfuncs = False
        if func.depth < max_depth:
            for subfunc in func.subfuncs():
                if (subfunc.stats[3] >= cum_time
                        or (hasattr(self.stats, 'line_stats') and
                            (subfunc.func in self.stats.line_stats.timings))):
                    func.has_subfuncs = True
                    self.add_node(func_list,
                                  subfunc,
                                  max_depth,
                                  cum_time=cum_time)

    def process_response(self, request, response):
        __traceback_hide__ = True
        if not hasattr(self, 'profiler'):
            return None
        self.profiler.create_stats()
        self.stats = DjangoDebugToolbarStats(self.profiler)
        if DJ_PROFILE_USE_LINE_PROFILER:
            self.stats.line_stats = self.line_profiler.get_stats()
        self.stats.calc_callees()

        root = FunctionCall(self.stats, self.stats.get_root_func(), depth=0)

        func_list = []
        self.add_node(func_list, root, 10, root.stats[3] / 8)

        self.record_stats({'func_list': func_list})